From e424545c0f5cbaf135c52764169ea20df7d07d35 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 20:12:23 +0100 Subject: Rudimentary name resolution for local items --- crates/ra_hir_def/src/body/lower.rs | 32 +++++--- crates/ra_hir_def/src/item_scope.rs | 8 +- crates/ra_hir_def/src/nameres/collector.rs | 2 +- crates/ra_hir_def/src/resolver.rs | 103 +++++++++++++++++-------- crates/ra_hir_ty/src/tests/simple.rs | 12 +-- crates/ra_ide/src/completion/complete_scope.rs | 37 +++++++++ 6 files changed, 145 insertions(+), 49 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 754924050..5323af097 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -494,45 +494,57 @@ where fn collect_block_items(&mut self, block: &ast::Block) { let container = ContainerId::DefWithBodyId(self.def); for item in block.items() { - let def: ModuleDefId = match item { + let (def, name): (ModuleDefId, Option) = match item { ast::ModuleItem::FnDef(def) => { let ast_id = self.expander.ast_id(&def); - FunctionLoc { container: container.into(), ast_id }.intern(self.db).into() + ( + FunctionLoc { container: container.into(), ast_id }.intern(self.db).into(), + def.name(), + ) } ast::ModuleItem::TypeAliasDef(def) => { let ast_id = self.expander.ast_id(&def); - TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into() + ( + TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into(), + def.name(), + ) } ast::ModuleItem::ConstDef(def) => { let ast_id = self.expander.ast_id(&def); - ConstLoc { container: container.into(), ast_id }.intern(self.db).into() + ( + ConstLoc { container: container.into(), ast_id }.intern(self.db).into(), + def.name(), + ) } ast::ModuleItem::StaticDef(def) => { let ast_id = self.expander.ast_id(&def); - StaticLoc { container, ast_id }.intern(self.db).into() + (StaticLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::StructDef(def) => { let ast_id = self.expander.ast_id(&def); - StructLoc { container, ast_id }.intern(self.db).into() + (StructLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::EnumDef(def) => { let ast_id = self.expander.ast_id(&def); - EnumLoc { container, ast_id }.intern(self.db).into() + (EnumLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::UnionDef(def) => { let ast_id = self.expander.ast_id(&def); - UnionLoc { container, ast_id }.intern(self.db).into() + (UnionLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::TraitDef(def) => { let ast_id = self.expander.ast_id(&def); - TraitLoc { container, ast_id }.intern(self.db).into() + (TraitLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::ImplBlock(_) | ast::ModuleItem::UseItem(_) | ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::Module(_) => continue, }; - self.body.item_scope.define_def(def) + self.body.item_scope.define_def(def); + if let Some(name) = name { + self.body.item_scope.push_res(name.as_name(), def.into()); + } } } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index e8ddcc3c2..b0288ee8d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -51,6 +51,12 @@ impl ItemScope { self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def)) } + pub fn entries_without_primitives<'a>( + &'a self, + ) -> impl Iterator + 'a { + self.visible.iter().map(|(n, def)| (n, *def)) + } + pub fn declarations(&self) -> impl Iterator + '_ { self.defs.iter().copied() } @@ -118,7 +124,7 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res(&mut self, name: Name, def: &PerNs) -> bool { + pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { let mut changed = false; let existing = self.visible.entry(name.clone()).or_default(); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 4f1fd4801..b9f40d3dd 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -446,7 +446,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), res); + changed |= scope.push_res(name.clone(), *res); } if !changed { diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index e70049617..cf3c33d78 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -10,6 +10,7 @@ use rustc_hash::FxHashSet; use crate::{ body::scope::{ExprScopes, ScopeId}, + body::Body, builtin_type::BuiltinType, db::DefDatabase, expr::{ExprId, PatId}, @@ -55,6 +56,8 @@ enum Scope { AdtScope(AdtId), /// Local bindings ExprScope(ExprScope), + /// Temporary hack to support local items. + LocalItemsScope(Arc), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -149,7 +152,13 @@ impl Resolver { for scope in self.scopes.iter().rev() { match scope { Scope::ExprScope(_) => continue, - Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, + Scope::GenericParams { .. } + | Scope::ImplBlockScope(_) + | Scope::LocalItemsScope(_) + if skip_to_mod => + { + continue + } Scope::GenericParams { params, def } => { if let Some(local_id) = params.find_by_name(first_name) { @@ -179,25 +188,35 @@ impl Resolver { &path, BuiltinShadowMode::Other, ); - let res = match module_def.take_types()? { - ModuleDefId::AdtId(it) => TypeNs::AdtId(it), - ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), - - ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), - ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), - - ModuleDefId::TraitId(it) => TypeNs::TraitId(it), - - ModuleDefId::FunctionId(_) - | ModuleDefId::ConstId(_) - | ModuleDefId::StaticId(_) - | ModuleDefId::ModuleId(_) => return None, - }; + let res = to_type_ns(module_def)?; return Some((res, idx)); } + Scope::LocalItemsScope(body) => { + let def = body.item_scope.get(first_name, BuiltinShadowMode::Other); + if let Some(res) = to_type_ns(def) { + return Some((res, None)); + } + } } } - None + return None; + fn to_type_ns(per_ns: PerNs) -> Option { + let res = match per_ns.take_types()? { + ModuleDefId::AdtId(it) => TypeNs::AdtId(it), + ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), + + ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), + ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), + + ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + + ModuleDefId::FunctionId(_) + | ModuleDefId::ConstId(_) + | ModuleDefId::StaticId(_) + | ModuleDefId::ModuleId(_) => return None, + }; + Some(res) + } } pub fn resolve_path_in_type_ns_fully( @@ -227,6 +246,7 @@ impl Resolver { | Scope::ExprScope(_) | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) + | Scope::LocalItemsScope(_) if skip_to_mod => { continue @@ -276,20 +296,7 @@ impl Resolver { ); return match idx { None => { - let value = match module_def.take_values()? { - ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), - ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), - ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), - ModuleDefId::ConstId(it) => ValueNs::ConstId(it), - ModuleDefId::StaticId(it) => ValueNs::StaticId(it), - - ModuleDefId::AdtId(AdtId::EnumId(_)) - | ModuleDefId::AdtId(AdtId::UnionId(_)) - | ModuleDefId::TraitId(_) - | ModuleDefId::TypeAliasId(_) - | ModuleDefId::BuiltinType(_) - | ModuleDefId::ModuleId(_) => return None, - }; + let value = to_value_ns(module_def)?; Some(ResolveValueResult::ValueNs(value)) } Some(idx) => { @@ -309,9 +316,33 @@ impl Resolver { } }; } + Scope::LocalItemsScope(body) => { + let def = body.item_scope.get(first_name, BuiltinShadowMode::Other); + if let Some(res) = to_value_ns(def) { + return Some(ResolveValueResult::ValueNs(res)); + } + } } } - None + return None; + + fn to_value_ns(per_ns: PerNs) -> Option { + let res = match per_ns.take_values()? { + ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), + ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), + ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), + ModuleDefId::ConstId(it) => ValueNs::ConstId(it), + ModuleDefId::StaticId(it) => ValueNs::StaticId(it), + + ModuleDefId::AdtId(AdtId::EnumId(_)) + | ModuleDefId::AdtId(AdtId::UnionId(_)) + | ModuleDefId::TraitId(_) + | ModuleDefId::TypeAliasId(_) + | ModuleDefId::BuiltinType(_) + | ModuleDefId::ModuleId(_) => return None, + }; + Some(res) + } } pub fn resolve_path_in_value_ns_fully( @@ -429,6 +460,11 @@ impl Scope { }); } } + Scope::LocalItemsScope(body) => { + body.item_scope.entries_without_primitives().for_each(|(name, def)| { + f(name.clone(), ScopeDef::PerNs(def)); + }) + } Scope::GenericParams { params, def } => { for (local_id, param) in params.types.iter() { f( @@ -464,6 +500,7 @@ pub fn resolver_for_scope( scope_id: Option, ) -> Resolver { let mut r = owner.resolver(db); + r = r.push_local_items_scope(db.body(owner)); let scopes = db.expr_scopes(owner); let scope_chain = scopes.scope_chain(scope_id).collect::>(); for scope in scope_chain.into_iter().rev() { @@ -499,6 +536,10 @@ impl Resolver { self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) } + fn push_local_items_scope(self, body: Arc) -> Resolver { + self.push_scope(Scope::LocalItemsScope(body)) + } + fn push_expr_scope( self, owner: DefWithBodyId, diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 6fe647a5e..3e5e163e3 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs @@ -1512,8 +1512,8 @@ fn test() { [49; 50) '0': u32 [80; 83) '101': u32 [95; 213) '{ ...NST; }': () - [138; 139) 'x': {unknown} - [142; 153) 'LOCAL_CONST': {unknown} + [138; 139) 'x': u32 + [142; 153) 'LOCAL_CONST': u32 [163; 164) 'z': u32 [167; 179) 'GLOBAL_CONST': u32 [189; 191) 'id': u32 @@ -1541,10 +1541,10 @@ fn test() { [29; 32) '101': u32 [70; 73) '101': u32 [85; 280) '{ ...MUT; }': () - [173; 174) 'x': {unknown} - [177; 189) 'LOCAL_STATIC': {unknown} - [199; 200) 'y': {unknown} - [203; 219) 'LOCAL_...IC_MUT': {unknown} + [173; 174) 'x': u32 + [177; 189) 'LOCAL_STATIC': u32 + [199; 200) 'y': u32 + [203; 219) 'LOCAL_...IC_MUT': u32 [229; 230) 'z': u32 [233; 246) 'GLOBAL_STATIC': u32 [256; 257) 'w': u32 diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index d5739b58a..458d7525e 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs @@ -873,4 +873,41 @@ mod tests { "### ); } + + #[test] + fn completes_local_item() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + fn main() { + return f<|>; + fn frobnicate() {} + } + " + ), + @r###" + [ + CompletionItem { + label: "frobnicate()", + source_range: [23; 24), + delete: [23; 24), + insert: "frobnicate()$0", + kind: Function, + lookup: "frobnicate", + detail: "fn frobnicate()", + }, + CompletionItem { + label: "main()", + source_range: [23; 24), + delete: [23; 24), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ) + } } -- cgit v1.2.3