From 007032f8504be1274972e4f23afaf0bc431d92d5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 19:31:01 +0100 Subject: Refactor --- crates/ra_hir_def/src/item_scope.rs | 12 +++++++----- crates/ra_hir_def/src/nameres/path_resolution.rs | 9 ++++----- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f1adc3b58..08d788cc9 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -70,18 +70,20 @@ impl ItemScope { } /// Get a name from current module scope, legacy macros are not included - pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&PerNs> { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option { match shadow { - BuiltinShadowMode::Module => self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)), + BuiltinShadowMode::Module => { + self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)).copied() + } BuiltinShadowMode::Other => { - let item = self.visible.get(name); + let item = self.visible.get(name).copied(); if let Some(def) = item { if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { - return BUILTIN_SCOPE.get(name).or(item); + return BUILTIN_SCOPE.get(name).copied().or(item); } } - item.or_else(|| BUILTIN_SCOPE.get(name)) + item.or_else(|| BUILTIN_SCOPE.get(name).copied()) } } } diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 378d49455..9b85ae018 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -181,7 +181,7 @@ impl CrateDefMap { // Since it is a qualified path here, it should not contains legacy macros match self[module.local_id].scope.get(&segment, prefer_module(i)) { - Some(def) => *def, + Some(def) => def, _ => { log::debug!("path segment {:?} not found", segment); return ResolvePathResult::empty(ReachedFixedPoint::No); @@ -243,7 +243,7 @@ impl CrateDefMap { // - std prelude let from_legacy_macro = self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); - let from_scope = self[module].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); + let from_scope = self[module].scope.get(name, shadow).unwrap_or_else(PerNs::none); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name, shadow); @@ -256,8 +256,7 @@ impl CrateDefMap { name: &Name, shadow: BuiltinShadowMode, ) -> PerNs { - let from_crate_root = - self[self.root].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); + let from_crate_root = self[self.root].scope.get(name, shadow).unwrap_or_else(PerNs::none); let from_extern_prelude = self.resolve_name_in_extern_prelude(name); from_crate_root.or(from_extern_prelude) @@ -278,7 +277,7 @@ impl CrateDefMap { keep = db.crate_def_map(prelude.krate); &keep }; - def_map[prelude.local_id].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none) + def_map[prelude.local_id].scope.get(name, shadow).unwrap_or_else(PerNs::none) } else { PerNs::none() } -- cgit v1.2.3 From 7c405c01567e814f18ebf8bdc6aa1f8f694919f0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 19:32:35 +0100 Subject: Simplify --- crates/ra_hir_def/src/item_scope.rs | 19 +++++++++++++------ crates/ra_hir_def/src/nameres/path_resolution.rs | 14 ++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 08d788cc9..e8ddcc3c2 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -70,20 +70,27 @@ impl ItemScope { } /// Get a name from current module scope, legacy macros are not included - pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> PerNs { match shadow { - BuiltinShadowMode::Module => { - self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)).copied() - } + BuiltinShadowMode::Module => self + .visible + .get(name) + .or_else(|| BUILTIN_SCOPE.get(name)) + .copied() + .unwrap_or_else(PerNs::none), BuiltinShadowMode::Other => { let item = self.visible.get(name).copied(); if let Some(def) = item { if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { - return BUILTIN_SCOPE.get(name).copied().or(item); + return BUILTIN_SCOPE + .get(name) + .copied() + .or(item) + .unwrap_or_else(PerNs::none); } } - item.or_else(|| BUILTIN_SCOPE.get(name).copied()) + item.or_else(|| BUILTIN_SCOPE.get(name).copied()).unwrap_or_else(PerNs::none) } } } diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 9b85ae018..695014c7b 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -180,13 +180,7 @@ impl CrateDefMap { } // Since it is a qualified path here, it should not contains legacy macros - match self[module.local_id].scope.get(&segment, prefer_module(i)) { - Some(def) => def, - _ => { - log::debug!("path segment {:?} not found", segment); - return ResolvePathResult::empty(ReachedFixedPoint::No); - } - } + self[module.local_id].scope.get(&segment, prefer_module(i)) } ModuleDefId::AdtId(AdtId::EnumId(e)) => { // enum variant @@ -243,7 +237,7 @@ impl CrateDefMap { // - std prelude let from_legacy_macro = self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); - let from_scope = self[module].scope.get(name, shadow).unwrap_or_else(PerNs::none); + let from_scope = self[module].scope.get(name, shadow); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name, shadow); @@ -256,7 +250,7 @@ impl CrateDefMap { name: &Name, shadow: BuiltinShadowMode, ) -> PerNs { - let from_crate_root = self[self.root].scope.get(name, shadow).unwrap_or_else(PerNs::none); + let from_crate_root = self[self.root].scope.get(name, shadow); let from_extern_prelude = self.resolve_name_in_extern_prelude(name); from_crate_root.or(from_extern_prelude) @@ -277,7 +271,7 @@ impl CrateDefMap { keep = db.crate_def_map(prelude.krate); &keep }; - def_map[prelude.local_id].scope.get(name, shadow).unwrap_or_else(PerNs::none) + def_map[prelude.local_id].scope.get(name, shadow) } else { PerNs::none() } -- cgit v1.2.3 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(-) (limited to 'crates') 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