about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/handlers/add_turbo_fish.rs4
-rw-r--r--crates/assists/src/handlers/expand_glob_import.rs4
-rw-r--r--crates/ide/src/doc_links.rs6
-rw-r--r--crates/ide/src/goto_definition.rs8
-rw-r--r--crates/ide/src/hover.rs6
-rw-r--r--crates/ide/src/references.rs6
-rw-r--r--crates/ide/src/references/rename.rs6
-rw-r--r--crates/ide/src/syntax_highlighting.rs10
-rw-r--r--crates/ide_db/src/defs.rs377
-rw-r--r--crates/ide_db/src/imports_locator.rs4
-rw-r--r--crates/ide_db/src/search.rs12
11 files changed, 228 insertions, 215 deletions
diff --git a/crates/assists/src/handlers/add_turbo_fish.rs b/crates/assists/src/handlers/add_turbo_fish.rs
index f4f997d8e19..e3d84d6986a 100644
--- a/crates/assists/src/handlers/add_turbo_fish.rs
+++ b/crates/assists/src/handlers/add_turbo_fish.rs
@@ -1,4 +1,4 @@
-use ide_db::defs::{classify_name_ref, Definition, NameRefClass};
+use ide_db::defs::{Definition, NameRefClass};
 use syntax::{ast, AstNode, SyntaxKind, T};
 use test_utils::mark;
 
@@ -39,7 +39,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
         return None;
     }
     let name_ref = ast::NameRef::cast(ident.parent())?;
-    let def = match classify_name_ref(&ctx.sema, &name_ref)? {
+    let def = match NameRefClass::classify(&ctx.sema, &name_ref)? {
         NameRefClass::Definition(def) => def,
         NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None,
     };
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs
index d1adff972e2..316a58d883a 100644
--- a/crates/assists/src/handlers/expand_glob_import.rs
+++ b/crates/assists/src/handlers/expand_glob_import.rs
@@ -1,7 +1,7 @@
 use either::Either;
 use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef};
 use ide_db::{
-    defs::{classify_name_ref, Definition, NameRefClass},
+    defs::{Definition, NameRefClass},
     search::SearchScope,
 };
 use syntax::{
@@ -217,7 +217,7 @@ fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>
             .flatten()
             .filter_map(|n| Some(n.descendants().filter_map(ast::NameRef::cast)))
             .flatten()
-            .filter_map(|r| match classify_name_ref(&ctx.sema, &r)? {
+            .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
                 NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)),
                 NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)),
                 _ => None,
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index db3f911c82f..d9dc63b33cc 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -14,7 +14,7 @@ use hir::{
     ModuleDef,
 };
 use ide_db::{
-    defs::{classify_name, classify_name_ref, Definition},
+    defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
 };
 use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
@@ -232,8 +232,8 @@ pub(crate) fn external_docs(
     let node = token.parent();
     let definition = match_ast! {
         match node {
-            ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition(sema.db)),
-            ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition(sema.db)),
+            ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
+            ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.referenced_or_defined(sema.db)),
             _ => None,
         }
     };
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 582bf4837d5..a87e31019df 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1,6 +1,6 @@
 use hir::Semantics;
 use ide_db::{
-    defs::{classify_name, classify_name_ref},
+    defs::{NameClass, NameRefClass},
     symbol_index, RootDatabase,
 };
 use syntax::{
@@ -40,7 +40,7 @@ pub(crate) fn goto_definition(
                 reference_definition(&sema, &name_ref).to_vec()
             },
             ast::Name(name) => {
-                let def = classify_name(&sema, &name)?.definition(sema.db);
+                let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db);
                 let nav = def.try_to_nav(sema.db)?;
                 vec![nav]
             },
@@ -81,9 +81,9 @@ pub(crate) fn reference_definition(
     sema: &Semantics<RootDatabase>,
     name_ref: &ast::NameRef,
 ) -> ReferenceResult {
-    let name_kind = classify_name_ref(sema, name_ref);
+    let name_kind = NameRefClass::classify(sema, name_ref);
     if let Some(def) = name_kind {
-        let def = def.definition(sema.db);
+        let def = def.referenced(sema.db);
         return match def.try_to_nav(sema.db) {
             Some(nav) => ReferenceResult::Exact(nav),
             None => ReferenceResult::Approximate(Vec::new()),
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 632eaf0a0d1..845333e2aec 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -4,7 +4,7 @@ use hir::{
     Module, ModuleDef, ModuleSource, Semantics,
 };
 use ide_db::{
-    defs::{classify_name, classify_name_ref, Definition},
+    defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
 };
 use itertools::Itertools;
@@ -107,8 +107,8 @@ pub(crate) fn hover(
     let node = token.parent();
     let definition = match_ast! {
         match node {
-            ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition(sema.db)),
-            ast::Name(name) => classify_name(&sema, &name).and_then(|d| d.into_definition(sema.db)),
+            ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)),
+            ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
             _ => None,
         }
     };
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 88e2f2db3fd..67ec257a8e9 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -13,7 +13,7 @@ pub(crate) mod rename;
 
 use hir::Semantics;
 use ide_db::{
-    defs::{classify_name, classify_name_ref, Definition},
+    defs::{Definition, NameClass, NameRefClass},
     search::SearchScope,
     RootDatabase,
 };
@@ -132,13 +132,13 @@ fn find_name(
     opt_name: Option<ast::Name>,
 ) -> Option<RangeInfo<Definition>> {
     if let Some(name) = opt_name {
-        let def = classify_name(sema, &name)?.definition(sema.db);
+        let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db);
         let range = name.syntax().text_range();
         return Some(RangeInfo::new(range, def));
     }
     let name_ref =
         sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?;
-    let def = classify_name_ref(sema, &name_ref)?.definition(sema.db);
+    let def = NameRefClass::classify(sema, &name_ref)?.referenced(sema.db);
     let range = name_ref.syntax().text_range();
     Some(RangeInfo::new(range, def))
 }
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index f9a11e43d8d..35aafc49d74 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -3,7 +3,7 @@
 use base_db::SourceDatabaseExt;
 use hir::{Module, ModuleDef, ModuleSource, Semantics};
 use ide_db::{
-    defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
+    defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
 };
 
@@ -88,13 +88,13 @@ fn find_module_at_offset(
     let module = match_ast! {
         match (ident.parent()) {
             ast::NameRef(name_ref) => {
-                match classify_name_ref(sema, &name_ref)? {
+                match NameRefClass::classify(sema, &name_ref)? {
                     NameRefClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module,
                     _ => return None,
                 }
             },
             ast::Name(name) => {
-                match classify_name(&sema, &name)? {
+                match NameClass::classify(&sema, &name)? {
                     NameClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module,
                     _ => return None,
                 }
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 527888306be..b35c031627f 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -8,7 +8,7 @@ mod tests;
 
 use hir::{Local, Name, Semantics, VariantDef};
 use ide_db::{
-    defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
+    defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
 };
 use rustc_hash::FxHashMap;
@@ -443,7 +443,7 @@ fn highlight_element(
         // Highlight definitions depending on the "type" of the definition.
         NAME => {
             let name = element.into_node().and_then(ast::Name::cast).unwrap();
-            let name_kind = classify_name(sema, &name);
+            let name_kind = NameClass::classify(sema, &name);
 
             if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind {
                 if let Some(name) = local.name(db) {
@@ -459,9 +459,9 @@ fn highlight_element(
                     highlight_def(db, def) | HighlightModifier::Definition
                 }
                 Some(NameClass::ConstReference(def)) => highlight_def(db, def),
-                Some(NameClass::FieldShorthand { field, .. }) => {
+                Some(NameClass::PatFieldShorthand { field_ref, .. }) => {
                     let mut h = HighlightTag::Field.into();
-                    if let Definition::Field(field) = field {
+                    if let Definition::Field(field) = field_ref {
                         if let VariantDef::Union(_) = field.parent_def(db) {
                             h |= HighlightModifier::Unsafe;
                         }
@@ -480,7 +480,7 @@ fn highlight_element(
         NAME_REF => {
             let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
             highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
-                match classify_name_ref(sema, &name_ref) {
+                match NameRefClass::classify(sema, &name_ref) {
                     Some(name_kind) => match name_kind {
                         NameRefClass::ExternCrate(_) => HighlightTag::Module.into(),
                         NameRefClass::Definition(def) => {
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index f8c7aa491ea..201a3d6fa00 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -81,146 +81,152 @@ impl Definition {
 pub enum NameClass {
     ExternCrate(Crate),
     Definition(Definition),
-    /// `None` in `if let None = Some(82) {}`
+    /// `None` in `if let None = Some(82) {}`.
     ConstReference(Definition),
-    FieldShorthand {
-        local: Local,
-        field: Definition,
+    /// `field` in `if let Foo { field } = foo`.
+    PatFieldShorthand {
+        local_def: Local,
+        field_ref: Definition,
     },
 }
 
 impl NameClass {
-    pub fn into_definition(self, db: &dyn HirDatabase) -> Option<Definition> {
-        Some(match self {
+    /// `Definition` defined by this name.
+    pub fn defined(self, db: &dyn HirDatabase) -> Option<Definition> {
+        let res = match self {
             NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
             NameClass::Definition(it) => it,
             NameClass::ConstReference(_) => return None,
-            NameClass::FieldShorthand { local, field: _ } => Definition::Local(local),
-        })
+            NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
+                Definition::Local(local_def)
+            }
+        };
+        Some(res)
     }
 
-    pub fn definition(self, db: &dyn HirDatabase) -> Definition {
+    /// `Definition` referenced or defined by this name.
+    pub fn referenced_or_defined(self, db: &dyn HirDatabase) -> Definition {
         match self {
             NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
             NameClass::Definition(it) | NameClass::ConstReference(it) => it,
-            NameClass::FieldShorthand { local: _, field } => field,
+            NameClass::PatFieldShorthand { local_def: _, field_ref } => field_ref,
         }
     }
-}
 
-pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
-    let _p = profile::span("classify_name");
+    pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
+        let _p = profile::span("classify_name");
 
-    let parent = name.syntax().parent()?;
+        let parent = name.syntax().parent()?;
 
-    if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) {
-        if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) {
-            return Some(NameClass::ConstReference(Definition::ModuleDef(def)));
+        if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) {
+            if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) {
+                return Some(NameClass::ConstReference(Definition::ModuleDef(def)));
+            }
         }
-    }
 
-    match_ast! {
-        match parent {
-            ast::Rename(it) => {
-                if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) {
-                    let path = use_tree.path()?;
-                    let path_segment = path.segment()?;
-                    let name_ref_class = path_segment
-                        .name_ref()
-                        // The rename might be from a `self` token, so fallback to the name higher
-                        // in the use tree.
-                        .or_else(||{
-                            if path_segment.self_token().is_none() {
-                                return None;
-                            }
+        match_ast! {
+            match parent {
+                ast::Rename(it) => {
+                    if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) {
+                        let path = use_tree.path()?;
+                        let path_segment = path.segment()?;
+                        let name_ref_class = path_segment
+                            .name_ref()
+                            // The rename might be from a `self` token, so fallback to the name higher
+                            // in the use tree.
+                            .or_else(||{
+                                if path_segment.self_token().is_none() {
+                                    return None;
+                                }
 
-                            let use_tree = use_tree
-                                .syntax()
-                                .parent()
-                                .as_ref()
-                                // Skip over UseTreeList
-                                .and_then(SyntaxNode::parent)
-                                .and_then(ast::UseTree::cast)?;
-                            let path = use_tree.path()?;
-                            let path_segment = path.segment()?;
-                            path_segment.name_ref()
-                        })
-                        .and_then(|name_ref| classify_name_ref(sema, &name_ref))?;
+                                let use_tree = use_tree
+                                    .syntax()
+                                    .parent()
+                                    .as_ref()
+                                    // Skip over UseTreeList
+                                    .and_then(SyntaxNode::parent)
+                                    .and_then(ast::UseTree::cast)?;
+                                let path = use_tree.path()?;
+                                let path_segment = path.segment()?;
+                                path_segment.name_ref()
+                            })
+                            .and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?;
 
-                    Some(NameClass::Definition(name_ref_class.definition(sema.db)))
-                } else {
-                    let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
-                    let resolved = sema.resolve_extern_crate(&extern_crate)?;
-                    Some(NameClass::ExternCrate(resolved))
-                }
-            },
-            ast::IdentPat(it) => {
-                let local = sema.to_def(&it)?;
+                        Some(NameClass::Definition(name_ref_class.referenced(sema.db)))
+                    } else {
+                        let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
+                        let resolved = sema.resolve_extern_crate(&extern_crate)?;
+                        Some(NameClass::ExternCrate(resolved))
+                    }
+                },
+                ast::IdentPat(it) => {
+                    let local = sema.to_def(&it)?;
 
-                if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) {
-                    if record_pat_field.name_ref().is_none() {
-                        if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
-                            let field = Definition::Field(field);
-                            return Some(NameClass::FieldShorthand { local, field });
+                    if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) {
+                        if record_pat_field.name_ref().is_none() {
+                            if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
+                                let field = Definition::Field(field);
+                                return Some(NameClass::PatFieldShorthand { local_def: local, field_ref: field });
+                            }
                         }
                     }
-                }
 
-                Some(NameClass::Definition(Definition::Local(local)))
-            },
-            ast::RecordField(it) => {
-                let field: hir::Field = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::Field(field)))
-            },
-            ast::Module(it) => {
-                let def = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Struct(it) => {
-                let def: hir::Struct = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Union(it) => {
-                let def: hir::Union = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Enum(it) => {
-                let def: hir::Enum = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Trait(it) => {
-                let def: hir::Trait = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Static(it) => {
-                let def: hir::Static = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Variant(it) => {
-                let def: hir::EnumVariant = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Fn(it) => {
-                let def: hir::Function = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::Const(it) => {
-                let def: hir::Const = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::TypeAlias(it) => {
-                let def: hir::TypeAlias = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::ModuleDef(def.into())))
-            },
-            ast::MacroCall(it) => {
-                let def = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::Macro(def)))
-            },
-            ast::TypeParam(it) => {
-                let def = sema.to_def(&it)?;
-                Some(NameClass::Definition(Definition::TypeParam(def)))
-            },
-            _ => None,
+                    Some(NameClass::Definition(Definition::Local(local)))
+                },
+                ast::RecordField(it) => {
+                    let field: hir::Field = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::Field(field)))
+                },
+                ast::Module(it) => {
+                    let def = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Struct(it) => {
+                    let def: hir::Struct = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Union(it) => {
+                    let def: hir::Union = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Enum(it) => {
+                    let def: hir::Enum = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Trait(it) => {
+                    let def: hir::Trait = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Static(it) => {
+                    let def: hir::Static = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Variant(it) => {
+                    let def: hir::EnumVariant = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Fn(it) => {
+                    let def: hir::Function = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::Const(it) => {
+                    let def: hir::Const = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::TypeAlias(it) => {
+                    let def: hir::TypeAlias = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                },
+                ast::MacroCall(it) => {
+                    let def = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::Macro(def)))
+                },
+                ast::TypeParam(it) => {
+                    let def = sema.to_def(&it)?;
+                    Some(NameClass::Definition(Definition::TypeParam(def)))
+                },
+                _ => None,
+            }
         }
     }
 }
@@ -229,102 +235,109 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option
 pub enum NameRefClass {
     ExternCrate(Crate),
     Definition(Definition),
-    FieldShorthand { local: Local, field: Definition },
+    FieldShorthand { local_ref: Local, field_ref: Definition },
 }
 
 impl NameRefClass {
-    pub fn definition(self, db: &dyn HirDatabase) -> Definition {
+    /// `Definition`, which this name refers to.
+    pub fn referenced(self, db: &dyn HirDatabase) -> Definition {
         match self {
             NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
             NameRefClass::Definition(def) => def,
-            NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local),
+            NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
+                // FIXME: this is inherently ambiguous -- this name refers to
+                // two different defs....
+                Definition::Local(local_ref)
+            }
         }
     }
-}
 
-// Note: we don't have unit-tests for this rather important function.
-// It is primarily exercised via goto definition tests in `ide`.
-pub fn classify_name_ref(
-    sema: &Semantics<RootDatabase>,
-    name_ref: &ast::NameRef,
-) -> Option<NameRefClass> {
-    let _p = profile::span("classify_name_ref");
+    // Note: we don't have unit-tests for this rather important function.
+    // It is primarily exercised via goto definition tests in `ide`.
+    pub fn classify(
+        sema: &Semantics<RootDatabase>,
+        name_ref: &ast::NameRef,
+    ) -> Option<NameRefClass> {
+        let _p = profile::span("classify_name_ref");
 
-    let parent = name_ref.syntax().parent()?;
+        let parent = name_ref.syntax().parent()?;
 
-    if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
-        if let Some(func) = sema.resolve_method_call(&method_call) {
-            return Some(NameRefClass::Definition(Definition::ModuleDef(func.into())));
+        if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
+            if let Some(func) = sema.resolve_method_call(&method_call) {
+                return Some(NameRefClass::Definition(Definition::ModuleDef(func.into())));
+            }
         }
-    }
 
-    if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
-        if let Some(field) = sema.resolve_field(&field_expr) {
-            return Some(NameRefClass::Definition(Definition::Field(field)));
+        if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
+            if let Some(field) = sema.resolve_field(&field_expr) {
+                return Some(NameRefClass::Definition(Definition::Field(field)));
+            }
         }
-    }
 
-    if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) {
-        if let Some((field, local)) = sema.resolve_record_field(&record_field) {
-            let field = Definition::Field(field);
-            let res = match local {
-                None => NameRefClass::Definition(field),
-                Some(local) => NameRefClass::FieldShorthand { field, local },
-            };
-            return Some(res);
+        if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) {
+            if let Some((field, local)) = sema.resolve_record_field(&record_field) {
+                let field = Definition::Field(field);
+                let res = match local {
+                    None => NameRefClass::Definition(field),
+                    Some(local) => {
+                        NameRefClass::FieldShorthand { field_ref: field, local_ref: local }
+                    }
+                };
+                return Some(res);
+            }
         }
-    }
 
-    if let Some(record_pat_field) = ast::RecordPatField::cast(parent.clone()) {
-        if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
-            let field = Definition::Field(field);
-            return Some(NameRefClass::Definition(field));
+        if let Some(record_pat_field) = ast::RecordPatField::cast(parent.clone()) {
+            if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
+                let field = Definition::Field(field);
+                return Some(NameRefClass::Definition(field));
+            }
         }
-    }
 
-    if ast::AssocTypeArg::cast(parent.clone()).is_some() {
-        // `Trait<Assoc = Ty>`
-        //        ^^^^^
-        let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
-        let resolved = sema.resolve_path(&path)?;
-        if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
-            if let Some(ty) = tr
-                .items(sema.db)
-                .iter()
-                .filter_map(|assoc| match assoc {
-                    hir::AssocItem::TypeAlias(it) => Some(*it),
-                    _ => None,
-                })
-                .find(|alias| alias.name(sema.db).to_string() == **name_ref.text())
-            {
-                return Some(NameRefClass::Definition(Definition::ModuleDef(
-                    ModuleDef::TypeAlias(ty),
-                )));
+        if ast::AssocTypeArg::cast(parent.clone()).is_some() {
+            // `Trait<Assoc = Ty>`
+            //        ^^^^^
+            let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
+            let resolved = sema.resolve_path(&path)?;
+            if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
+                if let Some(ty) = tr
+                    .items(sema.db)
+                    .iter()
+                    .filter_map(|assoc| match assoc {
+                        hir::AssocItem::TypeAlias(it) => Some(*it),
+                        _ => None,
+                    })
+                    .find(|alias| alias.name(sema.db).to_string() == **name_ref.text())
+                {
+                    return Some(NameRefClass::Definition(Definition::ModuleDef(
+                        ModuleDef::TypeAlias(ty),
+                    )));
+                }
             }
         }
-    }
 
-    if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
-        if let Some(path) = macro_call.path() {
-            if path.qualifier().is_none() {
-                // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment
-                // paths are handled below (allowing `log<|>::info!` to resolve to the log crate).
-                if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
-                    return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
+        if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
+            if let Some(path) = macro_call.path() {
+                if path.qualifier().is_none() {
+                    // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment
+                    // paths are handled below (allowing `log<|>::info!` to resolve to the log crate).
+                    if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
+                        return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
+                    }
                 }
             }
         }
-    }
 
-    if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
-        if let Some(resolved) = sema.resolve_path(&path) {
-            return Some(NameRefClass::Definition(resolved.into()));
+        if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
+            if let Some(resolved) = sema.resolve_path(&path) {
+                return Some(NameRefClass::Definition(resolved.into()));
+            }
         }
-    }
 
-    let extern_crate = ast::ExternCrate::cast(parent)?;
-    let resolved = sema.resolve_extern_crate(&extern_crate)?;
-    Some(NameRefClass::ExternCrate(resolved))
+        let extern_crate = ast::ExternCrate::cast(parent)?;
+        let resolved = sema.resolve_extern_crate(&extern_crate)?;
+        Some(NameRefClass::ExternCrate(resolved))
+    }
 }
 
 impl From<PathResolution> for Definition {
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs
index ed67e355314..df74be00bb2 100644
--- a/crates/ide_db/src/imports_locator.rs
+++ b/crates/ide_db/src/imports_locator.rs
@@ -5,7 +5,7 @@ use hir::{Crate, MacroDef, ModuleDef, Semantics};
 use syntax::{ast, AstNode, SyntaxKind::NAME};
 
 use crate::{
-    defs::{classify_name, Definition},
+    defs::{Definition, NameClass},
     symbol_index::{self, FileSymbol, Query},
     RootDatabase,
 };
@@ -60,5 +60,5 @@ fn get_name_definition<'a>(
         candidate_node
     };
     let name = ast::Name::cast(candidate_name_node)?;
-    classify_name(sema, &name)?.into_definition(sema.db)
+    NameClass::classify(sema, &name)?.defined(sema.db)
 }
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 8e3dcd99c4b..a243352406e 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -14,7 +14,7 @@ use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
 
 use crate::defs::NameClass;
 use crate::{
-    defs::{classify_name, classify_name_ref, Definition, NameRefClass},
+    defs::{Definition, NameRefClass},
     RootDatabase,
 };
 
@@ -276,7 +276,7 @@ impl<'a> FindUsages<'a> {
         name_ref: &ast::NameRef,
         sink: &mut dyn FnMut(Reference) -> bool,
     ) -> bool {
-        match classify_name_ref(self.sema, &name_ref) {
+        match NameRefClass::classify(self.sema, &name_ref) {
             Some(NameRefClass::Definition(def)) if &def == self.def => {
                 let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
                 {
@@ -292,7 +292,7 @@ impl<'a> FindUsages<'a> {
                 };
                 sink(reference)
             }
-            Some(NameRefClass::FieldShorthand { local, field }) => {
+            Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => {
                 let reference = match self.def {
                     Definition::Field(_) if &field == self.def => Reference {
                         file_range: self.sema.original_range(name_ref.syntax()),
@@ -313,10 +313,10 @@ impl<'a> FindUsages<'a> {
     }
 
     fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool {
-        match classify_name(self.sema, name) {
-            Some(NameClass::FieldShorthand { local: _, field }) => {
+        match NameClass::classify(self.sema, name) {
+            Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) => {
                 let reference = match self.def {
-                    Definition::Field(_) if &field == self.def => Reference {
+                    Definition::Field(_) if &field_ref == self.def => Reference {
                         file_range: self.sema.original_range(name.syntax()),
                         kind: ReferenceKind::FieldShorthandForField,
                         // FIXME: mutable patterns should have `Write` access