mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 04:09:05 +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());
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<_>>();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue