mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
fix(els): rename not working
This commit is contained in:
parent
2fdf5224b5
commit
c514d0d83d
9 changed files with 108 additions and 17 deletions
|
@ -702,6 +702,13 @@ impl<'a> HIRVisitor<'a> {
|
|||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ use lsp_types::{
|
|||
WorkspaceEdit,
|
||||
};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::_log;
|
||||
use crate::server::{ELSResult, RedirectableStdout, Server};
|
||||
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 pos = params.text_document_position.position;
|
||||
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
|
||||
.get_visitor(&uri)
|
||||
.and_then(|visitor| visitor.get_info(&tok))
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
.C = Class { .a = Int }
|
||||
.C.
|
||||
func self = self
|
||||
aplus self, x = self.a + x
|
||||
|
|
|
@ -216,6 +216,19 @@ fn test_rename() -> Result<(), Box<dyn std::error::Error>> {
|
|||
for (_, change) in edit.changes.unwrap() {
|
||||
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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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_shared__");
|
||||
// For public APIs, mangling is not performed because `hasattr`, etc. cannot be used.
|
||||
// For automatically generated variables, there is no possibility of conflict.
|
||||
if vis.is_private() && !name.starts_with('%') {
|
||||
if is_attr {
|
||||
return Str::from(format!("::{name}"));
|
||||
}
|
||||
let line_mangling = match (def_line, def_col) {
|
||||
(0, 0) => "".to_string(),
|
||||
(0, _) => format!("_C{def_col}"),
|
||||
|
@ -115,6 +124,7 @@ fn escape_ident(ident: Identifier) -> Str {
|
|||
&ident.vi.vis.modifier,
|
||||
ident.vi.def_loc.loc.ln_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 {
|
||||
py_name
|
||||
|
@ -126,6 +136,7 @@ fn escape_ident(ident: Identifier) -> Str {
|
|||
vis,
|
||||
ident.vi.def_loc.loc.ln_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,
|
||||
vi.def_loc.loc.ln_begin().unwrap_or(0),
|
||||
vi.def_loc.loc.col_begin().unwrap_or(0),
|
||||
false,
|
||||
)
|
||||
.to_string()
|
||||
}
|
||||
|
@ -1430,6 +1442,7 @@ impl PyCodeGenerator {
|
|||
&VisibilityModifier::Public,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
@ -713,8 +713,18 @@ impl Context {
|
|||
self.pop();
|
||||
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();
|
||||
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() {
|
||||
Ok(ValueObj::None)
|
||||
} else {
|
||||
|
|
|
@ -1170,7 +1170,7 @@ impl Context {
|
|||
let t = Type::Mono(format!("{}{ident}", self.name).into());
|
||||
let class = GenTypeObj::class(t, None, None, false);
|
||||
let class = ValueObj::Type(TypeObj::Generated(class));
|
||||
self.register_gen_const(ident, class, false)
|
||||
self.register_gen_const(ident, class, Some(call), false)
|
||||
}
|
||||
"Trait" => {
|
||||
let ident = var.ident().unwrap();
|
||||
|
@ -1178,7 +1178,7 @@ impl Context {
|
|||
let trait_ =
|
||||
GenTypeObj::trait_(t, TypeObj::builtin_type(Type::Failure), None, false);
|
||||
let trait_ = ValueObj::Type(TypeObj::Generated(trait_));
|
||||
self.register_gen_const(ident, trait_, false)
|
||||
self.register_gen_const(ident, trait_, Some(call), false)
|
||||
}
|
||||
_ => Ok(()),
|
||||
},
|
||||
|
@ -1189,6 +1189,11 @@ impl Context {
|
|||
pub(crate) fn register_const_def(&mut self, def: &ast::Def) -> TyCheckResult<()> {
|
||||
let id = Some(def.body.id);
|
||||
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 {
|
||||
ast::Signature::Subr(sig) => {
|
||||
if sig.is_const() {
|
||||
|
@ -1226,6 +1231,7 @@ impl Context {
|
|||
self.register_gen_const(
|
||||
def.sig.ident().unwrap(),
|
||||
obj,
|
||||
call,
|
||||
def.def_kind().is_other(),
|
||||
)?;
|
||||
} else {
|
||||
|
@ -1266,7 +1272,7 @@ impl Context {
|
|||
}
|
||||
self.pop();
|
||||
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 {
|
||||
self.pre_define_var(sig, id)?;
|
||||
|
@ -1517,6 +1523,7 @@ impl Context {
|
|||
&mut self,
|
||||
ident: &Identifier,
|
||||
obj: ValueObj,
|
||||
call: Option<&ast::Call>,
|
||||
alias: bool,
|
||||
) -> CompileResult<()> {
|
||||
let vis = self.instantiate_vis_modifier(&ident.vis)?;
|
||||
|
@ -1538,7 +1545,7 @@ impl Context {
|
|||
let meta_t = gen.meta_type();
|
||||
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),
|
||||
},
|
||||
// TODO: not all value objects are comparable
|
||||
|
@ -1567,6 +1574,7 @@ impl Context {
|
|||
&mut self,
|
||||
ident: &Identifier,
|
||||
gen: GenTypeObj,
|
||||
call: Option<&ast::Call>,
|
||||
) -> CompileResult<()> {
|
||||
match gen {
|
||||
GenTypeObj::Class(_) => {
|
||||
|
@ -1579,7 +1587,7 @@ impl Context {
|
|||
2,
|
||||
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)
|
||||
} else {
|
||||
let params = gen
|
||||
|
@ -1599,7 +1607,7 @@ impl Context {
|
|||
2,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1641,7 +1649,7 @@ impl Context {
|
|||
..
|
||||
} = additional
|
||||
{
|
||||
self.register_instance_attrs(&mut ctx, rec)?;
|
||||
self.register_instance_attrs(&mut ctx, rec, call)?;
|
||||
}
|
||||
param_t
|
||||
.map(|t| self.intersection(t, additional.typ()))
|
||||
|
@ -1710,7 +1718,7 @@ impl Context {
|
|||
..
|
||||
}) = 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)
|
||||
} else {
|
||||
|
@ -1744,7 +1752,7 @@ impl Context {
|
|||
None
|
||||
};
|
||||
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() {
|
||||
if let Some(sup_ctx) = self.get_nominal_type_ctx(&sup) {
|
||||
|
@ -1802,14 +1810,38 @@ impl Context {
|
|||
&self,
|
||||
ctx: &mut Context,
|
||||
rec: &Dict<Field, Type>,
|
||||
call: Option<&ast::Call>,
|
||||
) -> 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() {
|
||||
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 vi = VarInfo::instance_attr(
|
||||
field.clone(),
|
||||
t.clone(),
|
||||
self.kind.clone(),
|
||||
ctx.name.clone(),
|
||||
loc,
|
||||
);
|
||||
// self.index().register(&vi);
|
||||
if let Some(_ent) = ctx.decls.insert(varname.clone(), vi) {
|
||||
|
@ -1825,7 +1857,12 @@ impl Context {
|
|||
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 new_t = if let Some(base) = gen.base_or_sup() {
|
||||
match base {
|
||||
|
@ -1833,7 +1870,7 @@ impl Context {
|
|||
t: Type::Record(rec),
|
||||
..
|
||||
} => {
|
||||
self.register_instance_attrs(ctx, rec)?;
|
||||
self.register_instance_attrs(ctx, rec, call)?;
|
||||
}
|
||||
other => {
|
||||
methods.register_fixed_auto_impl(
|
||||
|
|
|
@ -935,7 +935,9 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
Some(py_name),
|
||||
)?;
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
Mutability::Const
|
||||
} else {
|
||||
|
@ -407,7 +413,7 @@ impl VarInfo {
|
|||
None,
|
||||
kind,
|
||||
None,
|
||||
AbsLocation::unknown(),
|
||||
loc,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue