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:
parent
92c5603498
commit
5937aa53c0
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user