fix(els): rename not working

This commit is contained in:
Shunsuke Shibayama 2024-01-24 22:08:06 +09:00
parent 2fdf5224b5
commit c514d0d83d
9 changed files with 108 additions and 17 deletions

View file

@ -702,6 +702,13 @@ impl<'a> HIRVisitor<'a> {
return Some(param.sig.vi.clone()); return Some(param.sig.vi.clone());
} }
} }
for guard in params.guards.iter() {
if let GuardClause::Bind(bind) = guard {
if let Some(vi) = self.get_def_info(bind, token) {
return Some(vi);
}
}
}
None None
} }

View file

@ -21,6 +21,8 @@ use lsp_types::{
WorkspaceEdit, WorkspaceEdit,
}; };
#[allow(unused_imports)]
use crate::_log;
use crate::server::{ELSResult, RedirectableStdout, Server}; use crate::server::{ELSResult, RedirectableStdout, Server};
use crate::util::{self, NormalizedUrl}; use crate::util::{self, NormalizedUrl};
@ -31,7 +33,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let uri = NormalizedUrl::new(params.text_document_position.text_document.uri); let uri = NormalizedUrl::new(params.text_document_position.text_document.uri);
let pos = params.text_document_position.position; let pos = params.text_document_position.position;
if let Some(tok) = self.file_cache.get_symbol(&uri, pos) { if let Some(tok) = self.file_cache.get_symbol(&uri, pos) {
// self.send_log(format!("token: {tok}"))?; // _log!(self, "tok: {tok}");
if let Some(vi) = self if let Some(vi) = self
.get_visitor(&uri) .get_visitor(&uri)
.and_then(|visitor| visitor.get_info(&tok)) .and_then(|visitor| visitor.get_info(&tok))

View file

@ -5,3 +5,4 @@
.C = Class { .a = Int } .C = Class { .a = Int }
.C. .C.
func self = self func self = self
aplus self, x = self.a + x

View file

@ -216,6 +216,19 @@ fn test_rename() -> Result<(), Box<dyn std::error::Error>> {
for (_, change) in edit.changes.unwrap() { for (_, change) in edit.changes.unwrap() {
assert_eq!(change.len(), 1); assert_eq!(change.len(), 1);
} }
client.notify_save(uri_b.clone().raw())?;
client.wait_diagnostics()?;
let edit = client
.request_rename(uri_b.clone().raw(), 4, 14, "b")?
.unwrap();
assert_eq!(edit.changes.as_ref().unwrap().iter().count(), 2);
for (uri, change) in edit.changes.unwrap() {
if uri.as_str().ends_with("b.er") {
assert_eq!(change.len(), 2);
} else {
assert_eq!(change.len(), 1); // c.er
}
}
Ok(()) Ok(())
} }

View file

@ -86,12 +86,21 @@ fn debind(ident: &Identifier) -> Option<Str> {
} }
} }
fn escape_name(name: &str, vis: &VisibilityModifier, def_line: u32, def_col: u32) -> Str { fn escape_name(
name: &str,
vis: &VisibilityModifier,
def_line: u32,
def_col: u32,
is_attr: bool,
) -> Str {
let name = name.replace('!', "__erg_proc__"); let name = name.replace('!', "__erg_proc__");
let name = name.replace('$', "__erg_shared__"); let name = name.replace('$', "__erg_shared__");
// For public APIs, mangling is not performed because `hasattr`, etc. cannot be used. // For public APIs, mangling is not performed because `hasattr`, etc. cannot be used.
// For automatically generated variables, there is no possibility of conflict. // For automatically generated variables, there is no possibility of conflict.
if vis.is_private() && !name.starts_with('%') { if vis.is_private() && !name.starts_with('%') {
if is_attr {
return Str::from(format!("::{name}"));
}
let line_mangling = match (def_line, def_col) { let line_mangling = match (def_line, def_col) {
(0, 0) => "".to_string(), (0, 0) => "".to_string(),
(0, _) => format!("_C{def_col}"), (0, _) => format!("_C{def_col}"),
@ -115,6 +124,7 @@ fn escape_ident(ident: Identifier) -> Str {
&ident.vi.vis.modifier, &ident.vi.vis.modifier,
ident.vi.def_loc.loc.ln_begin().unwrap_or(0), ident.vi.def_loc.loc.ln_begin().unwrap_or(0),
ident.vi.def_loc.loc.col_begin().unwrap_or(0), ident.vi.def_loc.loc.col_begin().unwrap_or(0),
ident.vi.kind.is_instance_attr(),
) )
} else if let Some(py_name) = ident.vi.py_name { } else if let Some(py_name) = ident.vi.py_name {
py_name py_name
@ -126,6 +136,7 @@ fn escape_ident(ident: Identifier) -> Str {
vis, vis,
ident.vi.def_loc.loc.ln_begin().unwrap_or(0), ident.vi.def_loc.loc.ln_begin().unwrap_or(0),
ident.vi.def_loc.loc.col_begin().unwrap_or(0), ident.vi.def_loc.loc.col_begin().unwrap_or(0),
ident.vi.kind.is_instance_attr(),
) )
} }
} }
@ -1055,6 +1066,7 @@ impl PyCodeGenerator {
&VisibilityModifier::Public, &VisibilityModifier::Public,
vi.def_loc.loc.ln_begin().unwrap_or(0), vi.def_loc.loc.ln_begin().unwrap_or(0),
vi.def_loc.loc.col_begin().unwrap_or(0), vi.def_loc.loc.col_begin().unwrap_or(0),
false,
) )
.to_string() .to_string()
} }
@ -1430,6 +1442,7 @@ impl PyCodeGenerator {
&VisibilityModifier::Public, &VisibilityModifier::Public,
0, 0,
0, 0,
false,
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -713,8 +713,18 @@ impl Context {
self.pop(); self.pop();
errs errs
})?; })?;
let call = if let Some(Expr::Call(call)) = &def.body.block.first() {
Some(call)
} else {
None
};
let (_ctx, errs) = self.check_decls_and_pop(); let (_ctx, errs) = self.check_decls_and_pop();
self.register_gen_const(def.sig.ident().unwrap(), obj, def.def_kind().is_other())?; self.register_gen_const(
def.sig.ident().unwrap(),
obj,
call,
def.def_kind().is_other(),
)?;
if errs.is_empty() { if errs.is_empty() {
Ok(ValueObj::None) Ok(ValueObj::None)
} else { } else {

View file

@ -1170,7 +1170,7 @@ impl Context {
let t = Type::Mono(format!("{}{ident}", self.name).into()); let t = Type::Mono(format!("{}{ident}", self.name).into());
let class = GenTypeObj::class(t, None, None, false); let class = GenTypeObj::class(t, None, None, false);
let class = ValueObj::Type(TypeObj::Generated(class)); let class = ValueObj::Type(TypeObj::Generated(class));
self.register_gen_const(ident, class, false) self.register_gen_const(ident, class, Some(call), false)
} }
"Trait" => { "Trait" => {
let ident = var.ident().unwrap(); let ident = var.ident().unwrap();
@ -1178,7 +1178,7 @@ impl Context {
let trait_ = let trait_ =
GenTypeObj::trait_(t, TypeObj::builtin_type(Type::Failure), None, false); GenTypeObj::trait_(t, TypeObj::builtin_type(Type::Failure), None, false);
let trait_ = ValueObj::Type(TypeObj::Generated(trait_)); let trait_ = ValueObj::Type(TypeObj::Generated(trait_));
self.register_gen_const(ident, trait_, false) self.register_gen_const(ident, trait_, Some(call), false)
} }
_ => Ok(()), _ => Ok(()),
}, },
@ -1189,6 +1189,11 @@ impl Context {
pub(crate) fn register_const_def(&mut self, def: &ast::Def) -> TyCheckResult<()> { pub(crate) fn register_const_def(&mut self, def: &ast::Def) -> TyCheckResult<()> {
let id = Some(def.body.id); let id = Some(def.body.id);
let __name__ = def.sig.ident().map(|i| i.inspect()).unwrap_or(UBAR); let __name__ = def.sig.ident().map(|i| i.inspect()).unwrap_or(UBAR);
let call = if let Some(ast::Expr::Call(call)) = &def.body.block.first() {
Some(call)
} else {
None
};
match &def.sig { match &def.sig {
ast::Signature::Subr(sig) => { ast::Signature::Subr(sig) => {
if sig.is_const() { if sig.is_const() {
@ -1226,6 +1231,7 @@ impl Context {
self.register_gen_const( self.register_gen_const(
def.sig.ident().unwrap(), def.sig.ident().unwrap(),
obj, obj,
call,
def.def_kind().is_other(), def.def_kind().is_other(),
)?; )?;
} else { } else {
@ -1266,7 +1272,7 @@ impl Context {
} }
self.pop(); self.pop();
if let Some(ident) = sig.ident() { if let Some(ident) = sig.ident() {
self.register_gen_const(ident, obj, def.def_kind().is_other())?; self.register_gen_const(ident, obj, call, def.def_kind().is_other())?;
} }
} else { } else {
self.pre_define_var(sig, id)?; self.pre_define_var(sig, id)?;
@ -1517,6 +1523,7 @@ impl Context {
&mut self, &mut self,
ident: &Identifier, ident: &Identifier,
obj: ValueObj, obj: ValueObj,
call: Option<&ast::Call>,
alias: bool, alias: bool,
) -> CompileResult<()> { ) -> CompileResult<()> {
let vis = self.instantiate_vis_modifier(&ident.vis)?; let vis = self.instantiate_vis_modifier(&ident.vis)?;
@ -1538,7 +1545,7 @@ impl Context {
let meta_t = gen.meta_type(); let meta_t = gen.meta_type();
self.register_type_alias(ident, gen.into_typ(), meta_t) self.register_type_alias(ident, gen.into_typ(), meta_t)
} }
TypeObj::Generated(gen) => self.register_gen_type(ident, gen), TypeObj::Generated(gen) => self.register_gen_type(ident, gen, call),
TypeObj::Builtin { t, meta_t } => self.register_type_alias(ident, t, meta_t), TypeObj::Builtin { t, meta_t } => self.register_type_alias(ident, t, meta_t),
}, },
// TODO: not all value objects are comparable // TODO: not all value objects are comparable
@ -1567,6 +1574,7 @@ impl Context {
&mut self, &mut self,
ident: &Identifier, ident: &Identifier,
gen: GenTypeObj, gen: GenTypeObj,
call: Option<&ast::Call>,
) -> CompileResult<()> { ) -> CompileResult<()> {
match gen { match gen {
GenTypeObj::Class(_) => { GenTypeObj::Class(_) => {
@ -1579,7 +1587,7 @@ impl Context {
2, 2,
self.level, self.level,
); );
self.gen_class_new_method(&gen, &mut ctx)?; self.gen_class_new_method(&gen, call, &mut ctx)?;
self.register_gen_mono_type(ident, gen, ctx, Const) self.register_gen_mono_type(ident, gen, ctx, Const)
} else { } else {
let params = gen let params = gen
@ -1599,7 +1607,7 @@ impl Context {
2, 2,
self.level, self.level,
); );
self.gen_class_new_method(&gen, &mut ctx)?; self.gen_class_new_method(&gen, call, &mut ctx)?;
self.register_gen_poly_type(ident, gen, ctx, Const) self.register_gen_poly_type(ident, gen, ctx, Const)
} }
} }
@ -1641,7 +1649,7 @@ impl Context {
.. ..
} = additional } = additional
{ {
self.register_instance_attrs(&mut ctx, rec)?; self.register_instance_attrs(&mut ctx, rec, call)?;
} }
param_t param_t
.map(|t| self.intersection(t, additional.typ())) .map(|t| self.intersection(t, additional.typ()))
@ -1710,7 +1718,7 @@ impl Context {
.. ..
}) = gen.base_or_sup() }) = gen.base_or_sup()
{ {
self.register_instance_attrs(&mut ctx, req)?; self.register_instance_attrs(&mut ctx, req, call)?;
} }
self.register_gen_mono_type(ident, gen, ctx, Const) self.register_gen_mono_type(ident, gen, ctx, Const)
} else { } else {
@ -1744,7 +1752,7 @@ impl Context {
None None
}; };
if let Some(additional) = additional { if let Some(additional) = additional {
self.register_instance_attrs(&mut ctx, additional)?; self.register_instance_attrs(&mut ctx, additional, call)?;
} }
for sup in super_classes.into_iter() { for sup in super_classes.into_iter() {
if let Some(sup_ctx) = self.get_nominal_type_ctx(&sup) { if let Some(sup_ctx) = self.get_nominal_type_ctx(&sup) {
@ -1802,14 +1810,38 @@ impl Context {
&self, &self,
ctx: &mut Context, ctx: &mut Context,
rec: &Dict<Field, Type>, rec: &Dict<Field, Type>,
call: Option<&ast::Call>,
) -> CompileResult<()> { ) -> CompileResult<()> {
let record = call.and_then(|call| {
if let Some(ast::Expr::Record(record)) = call
.args
.get_left_or_key("Base")
.or_else(|| call.args.get_left_or_key("Requirement"))
.or_else(|| call.args.get_left_or_key("Super"))
{
Some(record)
} else {
None
}
});
for (field, t) in rec.iter() { for (field, t) in rec.iter() {
let loc = record
.as_ref()
.and_then(|record| {
record
.keys()
.iter()
.find(|id| id.inspect() == &field.symbol)
.map(|name| self.absolutize(name.loc()))
})
.unwrap_or(AbsLocation::unknown());
let varname = VarName::from_str(field.symbol.clone()); let varname = VarName::from_str(field.symbol.clone());
let vi = VarInfo::instance_attr( let vi = VarInfo::instance_attr(
field.clone(), field.clone(),
t.clone(), t.clone(),
self.kind.clone(), self.kind.clone(),
ctx.name.clone(), ctx.name.clone(),
loc,
); );
// self.index().register(&vi); // self.index().register(&vi);
if let Some(_ent) = ctx.decls.insert(varname.clone(), vi) { if let Some(_ent) = ctx.decls.insert(varname.clone(), vi) {
@ -1825,7 +1857,12 @@ impl Context {
Ok(()) Ok(())
} }
fn gen_class_new_method(&self, gen: &GenTypeObj, ctx: &mut Context) -> CompileResult<()> { fn gen_class_new_method(
&self,
gen: &GenTypeObj,
call: Option<&ast::Call>,
ctx: &mut Context,
) -> CompileResult<()> {
let mut methods = Self::methods(None, self.cfg.clone(), self.shared.clone(), 2, self.level); let mut methods = Self::methods(None, self.cfg.clone(), self.shared.clone(), 2, self.level);
let new_t = if let Some(base) = gen.base_or_sup() { let new_t = if let Some(base) = gen.base_or_sup() {
match base { match base {
@ -1833,7 +1870,7 @@ impl Context {
t: Type::Record(rec), t: Type::Record(rec),
.. ..
} => { } => {
self.register_instance_attrs(ctx, rec)?; self.register_instance_attrs(ctx, rec, call)?;
} }
other => { other => {
methods.register_fixed_auto_impl( methods.register_fixed_auto_impl(

View file

@ -935,7 +935,9 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
Some(py_name), Some(py_name),
)?; )?;
if let Some(gen) = ty_obj { if let Some(gen) = ty_obj {
self.module.context.register_gen_type(&new_ident, gen)?; self.module
.context
.register_gen_type(&new_ident, gen, None)?;
} }
Ok(()) Ok(())
} }

View file

@ -393,7 +393,13 @@ impl VarInfo {
) )
} }
pub fn instance_attr(field: Field, t: Type, kind: ContextKind, namespace: Str) -> Self { pub fn instance_attr(
field: Field,
t: Type,
kind: ContextKind,
namespace: Str,
loc: AbsLocation,
) -> Self {
let muty = if field.is_const() { let muty = if field.is_const() {
Mutability::Const Mutability::Const
} else { } else {
@ -407,7 +413,7 @@ impl VarInfo {
None, None,
kind, kind,
None, None,
AbsLocation::unknown(), loc,
) )
} }