]> git.lizzy.rs Git - rust.git/commitdiff
Rudimentary name resolution for local items
authorAleksey Kladov <aleksey.kladov@gmail.com>
Sun, 22 Dec 2019 19:12:23 +0000 (20:12 +0100)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Sun, 22 Dec 2019 21:41:21 +0000 (22:41 +0100)
crates/ra_hir_def/src/body/lower.rs
crates/ra_hir_def/src/item_scope.rs
crates/ra_hir_def/src/nameres/collector.rs
crates/ra_hir_def/src/resolver.rs
crates/ra_hir_ty/src/tests/simple.rs
crates/ra_ide/src/completion/complete_scope.rs

index 7549240505800ad92013dab160612297e22ff8f8..5323af097236c71c9319fc98dbf702517d340871 100644 (file)
@@ -494,45 +494,57 @@ fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
     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<ast::Name>) = 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());
+            }
         }
     }
 
index e8ddcc3c27436d4643bb9d5912c8018964350ebf..b0288ee8dbec834beafc46d6742f60c95d42842a 100644 (file)
@@ -51,6 +51,12 @@ pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
         self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def))
     }
 
+    pub fn entries_without_primitives<'a>(
+        &'a self,
+    ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
+        self.visible.iter().map(|(n, def)| (n, *def))
+    }
+
     pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
         self.defs.iter().copied()
     }
@@ -118,7 +124,7 @@ pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
         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();
 
index 4f1fd480181ea1c239ce3b7053650bca97fb61dc..b9f40d3dd996a6f5a8771715bb1e4aa258ec6c26 100644 (file)
@@ -446,7 +446,7 @@ fn update_recursive(
         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 {
index e70049617dda5e32eb5a29ca16d935643e2a3e56..cf3c33d7888ecc3811ee5adec06749c4fd750884 100644 (file)
@@ -10,6 +10,7 @@
 
 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<Body>),
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -149,7 +152,13 @@ pub fn resolve_path_in_type_ns(
         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 @@ pub fn resolve_path_in_type_ns(
                         &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<TypeNs> {
+            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 @@ pub fn resolve_path_in_value_ns(
                 | Scope::ExprScope(_)
                 | Scope::GenericParams { .. }
                 | Scope::ImplBlockScope(_)
+                | Scope::LocalItemsScope(_)
                     if skip_to_mod =>
                 {
                     continue
@@ -276,20 +296,7 @@ pub fn resolve_path_in_value_ns(
                     );
                     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 @@ pub fn resolve_path_in_value_ns(
                         }
                     };
                 }
+                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<ValueNs> {
+            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 @@ fn process_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)
                     });
                 }
             }
+            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<ScopeId>,
 ) -> 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::<Vec<_>>();
     for scope in scope_chain.into_iter().rev() {
@@ -499,6 +536,10 @@ fn push_module_scope(
         self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
     }
 
+    fn push_local_items_scope(self, body: Arc<Body>) -> Resolver {
+        self.push_scope(Scope::LocalItemsScope(body))
+    }
+
     fn push_expr_scope(
         self,
         owner: DefWithBodyId,
index 6fe647a5e3cd8c9fcc15a1b645a5d5e8c4183df0..3e5e163e3486c55c8896cf5ae0035b4691dd0952 100644 (file)
@@ -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
index d5739b58a6d759741360c196397b18821c332fc5..458d7525ec9f6d93977da9dc1ef2927750a87bc3 100644 (file)
@@ -873,4 +873,41 @@ fn main() {
         "###
         );
     }
+
+    #[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()",
+            },
+        ]
+        "###
+        )
+    }
 }