1
1
mirror of https://github.com/oxalica/nil.git synced 2024-11-22 19:49:20 +03:00

Allow NameDef to have multiple source locations

This commit is contained in:
oxalica 2022-09-04 04:49:42 +08:00
parent 92c5603498
commit 5937aa53c0
5 changed files with 64 additions and 41 deletions

View File

@ -41,10 +41,12 @@ impl LivenessCheckResult {
let source_map = db.source_map(file);
let root = db.parse(file).syntax_node();
let mut diags = Vec::new();
diags.extend(self.name_defs.iter().map(|&def| {
let ptr = source_map.name_def_node(def).unwrap();
Diagnostic::new(ptr.text_range(), DiagnosticKind::UnusedBinding)
}));
diags.extend(
self.name_defs
.iter()
.flat_map(|&def| source_map.name_def_nodes(def))
.map(|ptr| Diagnostic::new(ptr.text_range(), DiagnosticKind::UnusedBinding)),
);
diags.extend(self.withs.iter().map(|&expr| {
let ptr = source_map.expr_node(expr).unwrap();
let node = ast::With::cast(ptr.to_node(&root)).unwrap();

View File

@ -53,7 +53,7 @@ impl LowerCtx<'_> {
fn alloc_name_def(&mut self, name: SmolStr, kind: NameDefKind, ptr: AstPtr) -> NameDefId {
let id = self.module.name_defs.alloc(NameDef { name, kind });
self.source_map.name_def_map.insert(ptr.clone(), id);
self.source_map.name_def_map_rev.insert(id, ptr);
self.source_map.name_def_map_rev.insert(id, vec![ptr]);
id
}

View File

@ -161,7 +161,7 @@ pub struct ModuleSourceMap {
expr_map: HashMap<AstPtr, ExprId>,
expr_map_rev: HashMap<ExprId, AstPtr>,
name_def_map: HashMap<AstPtr, NameDefId>,
name_def_map_rev: ArenaMap<NameDefId, AstPtr>,
name_def_map_rev: ArenaMap<NameDefId, Vec<AstPtr>>,
}
impl ModuleSourceMap {
@ -177,8 +177,12 @@ impl ModuleSourceMap {
self.name_def_map.get(&node).copied()
}
pub fn name_def_node(&self, def_id: NameDefId) -> Option<AstPtr> {
self.name_def_map_rev.get(def_id).cloned()
pub fn name_def_nodes(&self, def_id: NameDefId) -> impl Iterator<Item = AstPtr> + '_ {
self.name_def_map_rev
.get(def_id)
.into_iter()
.flatten()
.cloned()
}
}

View File

@ -331,7 +331,12 @@ mod tests {
let mut poses = defs
.iter()
.map(|(_, def)| {
source_map.name_def_node(*def).unwrap().text_range().start()
source_map
.name_def_nodes(*def)
.next()
.unwrap()
.text_range()
.start()
})
.collect::<Vec<_>>();
poses.sort_unstable();
@ -349,8 +354,7 @@ mod tests {
fn check_resolve(fixture: &str) {
let (db, f) = TestDB::from_fixture(fixture).unwrap();
let file_id = f[0].file_id;
assert!((1..=2).contains(&f.markers().len()));
let expect = f.markers().get(1).map(|p| p.pos);
let expect = f.markers()[1..].iter().map(|p| p.pos).collect::<Vec<_>>();
// Inherit(Attr(Name)) or Expr(Ref(Name))
let ptr = db
@ -369,23 +373,30 @@ mod tests {
let source_map = db.source_map(file_id);
let name_res = db.name_resolution(file_id);
let expr_id = source_map.expr_map[&ptr];
let got = name_res.get(expr_id).map(|ret| match ret {
&ResolveResult::NameDef(def) => source_map
.name_def_node(def)
.unwrap()
.to_node(&parse.syntax_node())
.text_range()
.start(),
ResolveResult::WithExprs(expr) => source_map
// Test the innermost one.
.expr_node(expr[0])
.unwrap()
.to_node(&parse.syntax_node())
.text_range()
.start(),
// Same pos for builtin names.
ResolveResult::Builtin(_) => f[0].pos,
});
let got = name_res
.get(expr_id)
.map(|ret| {
match ret {
&ResolveResult::NameDef(def) => source_map
.name_def_nodes(def)
.map(|ptr| ptr.to_node(&parse.syntax_node()).text_range().start())
.collect(),
ResolveResult::WithExprs(exprs) => exprs
.iter()
.map(|&e| {
source_map
.expr_node(e)
.unwrap()
.to_node(&parse.syntax_node())
.text_range()
.start()
})
.collect(),
// Return the input pos to indicate builtin names.
ResolveResult::Builtin(_) => vec![f[0].pos],
}
})
.unwrap_or_default();
assert_eq!(got, expect);
}
@ -411,7 +422,7 @@ mod tests {
check_resolve(r"a: with b; $1c: $0c");
check_resolve(r"a: $1with b; c: $0x");
check_resolve(r"$1x: with a; with b; $0x");
check_resolve(r"x: with a; $1with b; $0y");
check_resolve(r"x: $2with a; $1with b; $0y");
}
#[test]

View File

@ -47,18 +47,24 @@ pub(crate) fn goto_definition(
let name_res = db.name_resolution(file_id);
match name_res.get(expr_id)? {
&ResolveResult::NameDef(def) => {
let name_node = source_map.name_def_node(def)?.to_node(&parse.syntax_node());
let full_node = name_node.ancestors().find(|n| {
matches!(
n.kind(),
SyntaxKind::LAMBDA | SyntaxKind::ATTR_PATH_VALUE | SyntaxKind::INHERIT
)
})?;
Some(vec![NavigationTarget {
file_id,
focus_range: name_node.text_range(),
full_range: full_node.text_range(),
}])
let targets = source_map
.name_def_nodes(def)
.filter_map(|ptr| {
let name_node = ptr.to_node(&parse.syntax_node());
let full_node = name_node.ancestors().find(|n| {
matches!(
n.kind(),
SyntaxKind::LAMBDA | SyntaxKind::ATTR_PATH_VALUE | SyntaxKind::INHERIT
)
})?;
Some(NavigationTarget {
file_id,
focus_range: name_node.text_range(),
full_range: full_node.text_range(),
})
})
.collect();
Some(targets)
}
ResolveResult::WithExprs(withs) => {
let targets = withs