diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-10-15 16:39:35 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-10-15 16:39:35 +0100 |
commit | d8c6e192f7b35c57e7ff9d167ab10db8a8cd90b4 (patch) | |
tree | 460a055c661b2c44ffef28b920f1a59bdbfd5017 /crates | |
parent | 7fadc78ebb43b0eb9b6ccf314e29bdd23717542f (diff) | |
parent | c5868a48795c899d43fde773091f0b133bee0a59 (diff) |
Merge #6243
6243: Clarify classification API r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/handlers/add_turbo_fish.rs | 4 | ||||
-rw-r--r-- | crates/assists/src/handlers/expand_glob_import.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/doc_links.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/goto_definition.rs | 8 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/references.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/references/rename.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting.rs | 10 | ||||
-rw-r--r-- | crates/ide_db/src/defs.rs | 377 | ||||
-rw-r--r-- | crates/ide_db/src/imports_locator.rs | 4 | ||||
-rw-r--r-- | crates/ide_db/src/search.rs | 12 |
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 f4f997d8e..e3d84d698 100644 --- a/crates/assists/src/handlers/add_turbo_fish.rs +++ b/crates/assists/src/handlers/add_turbo_fish.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ide_db::defs::{classify_name_ref, Definition, NameRefClass}; | 1 | use ide_db::defs::{Definition, NameRefClass}; |
2 | use syntax::{ast, AstNode, SyntaxKind, T}; | 2 | use syntax::{ast, AstNode, SyntaxKind, T}; |
3 | use test_utils::mark; | 3 | use test_utils::mark; |
4 | 4 | ||
@@ -39,7 +39,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
39 | return None; | 39 | return None; |
40 | } | 40 | } |
41 | let name_ref = ast::NameRef::cast(ident.parent())?; | 41 | let name_ref = ast::NameRef::cast(ident.parent())?; |
42 | let def = match classify_name_ref(&ctx.sema, &name_ref)? { | 42 | let def = match NameRefClass::classify(&ctx.sema, &name_ref)? { |
43 | NameRefClass::Definition(def) => def, | 43 | NameRefClass::Definition(def) => def, |
44 | NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, | 44 | NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, |
45 | }; | 45 | }; |
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index d1adff972..316a58d88 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; | 2 | use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; |
3 | use ide_db::{ | 3 | use ide_db::{ |
4 | defs::{classify_name_ref, Definition, NameRefClass}, | 4 | defs::{Definition, NameRefClass}, |
5 | search::SearchScope, | 5 | search::SearchScope, |
6 | }; | 6 | }; |
7 | use syntax::{ | 7 | use syntax::{ |
@@ -217,7 +217,7 @@ fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def> | |||
217 | .flatten() | 217 | .flatten() |
218 | .filter_map(|n| Some(n.descendants().filter_map(ast::NameRef::cast))) | 218 | .filter_map(|n| Some(n.descendants().filter_map(ast::NameRef::cast))) |
219 | .flatten() | 219 | .flatten() |
220 | .filter_map(|r| match classify_name_ref(&ctx.sema, &r)? { | 220 | .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? { |
221 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), | 221 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), |
222 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), | 222 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), |
223 | _ => None, | 223 | _ => None, |
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index db3f911c8..d9dc63b33 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -14,7 +14,7 @@ use hir::{ | |||
14 | ModuleDef, | 14 | ModuleDef, |
15 | }; | 15 | }; |
16 | use ide_db::{ | 16 | use ide_db::{ |
17 | defs::{classify_name, classify_name_ref, Definition}, | 17 | defs::{Definition, NameClass, NameRefClass}, |
18 | RootDatabase, | 18 | RootDatabase, |
19 | }; | 19 | }; |
20 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 20 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
@@ -232,8 +232,8 @@ pub(crate) fn external_docs( | |||
232 | let node = token.parent(); | 232 | let node = token.parent(); |
233 | let definition = match_ast! { | 233 | let definition = match_ast! { |
234 | match node { | 234 | match node { |
235 | ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition(sema.db)), | 235 | ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), |
236 | ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition(sema.db)), | 236 | ast::Name(name) => NameClass::classify(&sema, &name).map(|d| d.referenced_or_defined(sema.db)), |
237 | _ => None, | 237 | _ => None, |
238 | } | 238 | } |
239 | }; | 239 | }; |
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 582bf4837..a87e31019 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use hir::Semantics; | 1 | use hir::Semantics; |
2 | use ide_db::{ | 2 | use ide_db::{ |
3 | defs::{classify_name, classify_name_ref}, | 3 | defs::{NameClass, NameRefClass}, |
4 | symbol_index, RootDatabase, | 4 | symbol_index, RootDatabase, |
5 | }; | 5 | }; |
6 | use syntax::{ | 6 | use syntax::{ |
@@ -40,7 +40,7 @@ pub(crate) fn goto_definition( | |||
40 | reference_definition(&sema, &name_ref).to_vec() | 40 | reference_definition(&sema, &name_ref).to_vec() |
41 | }, | 41 | }, |
42 | ast::Name(name) => { | 42 | ast::Name(name) => { |
43 | let def = classify_name(&sema, &name)?.definition(sema.db); | 43 | let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db); |
44 | let nav = def.try_to_nav(sema.db)?; | 44 | let nav = def.try_to_nav(sema.db)?; |
45 | vec![nav] | 45 | vec![nav] |
46 | }, | 46 | }, |
@@ -81,9 +81,9 @@ pub(crate) fn reference_definition( | |||
81 | sema: &Semantics<RootDatabase>, | 81 | sema: &Semantics<RootDatabase>, |
82 | name_ref: &ast::NameRef, | 82 | name_ref: &ast::NameRef, |
83 | ) -> ReferenceResult { | 83 | ) -> ReferenceResult { |
84 | let name_kind = classify_name_ref(sema, name_ref); | 84 | let name_kind = NameRefClass::classify(sema, name_ref); |
85 | if let Some(def) = name_kind { | 85 | if let Some(def) = name_kind { |
86 | let def = def.definition(sema.db); | 86 | let def = def.referenced(sema.db); |
87 | return match def.try_to_nav(sema.db) { | 87 | return match def.try_to_nav(sema.db) { |
88 | Some(nav) => ReferenceResult::Exact(nav), | 88 | Some(nav) => ReferenceResult::Exact(nav), |
89 | None => ReferenceResult::Approximate(Vec::new()), | 89 | None => ReferenceResult::Approximate(Vec::new()), |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 632eaf0a0..845333e2a 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -4,7 +4,7 @@ use hir::{ | |||
4 | Module, ModuleDef, ModuleSource, Semantics, | 4 | Module, ModuleDef, ModuleSource, Semantics, |
5 | }; | 5 | }; |
6 | use ide_db::{ | 6 | use ide_db::{ |
7 | defs::{classify_name, classify_name_ref, Definition}, | 7 | defs::{Definition, NameClass, NameRefClass}, |
8 | RootDatabase, | 8 | RootDatabase, |
9 | }; | 9 | }; |
10 | use itertools::Itertools; | 10 | use itertools::Itertools; |
@@ -107,8 +107,8 @@ pub(crate) fn hover( | |||
107 | let node = token.parent(); | 107 | let node = token.parent(); |
108 | let definition = match_ast! { | 108 | let definition = match_ast! { |
109 | match node { | 109 | match node { |
110 | ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition(sema.db)), | 110 | ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)), |
111 | ast::Name(name) => classify_name(&sema, &name).and_then(|d| d.into_definition(sema.db)), | 111 | ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), |
112 | _ => None, | 112 | _ => None, |
113 | } | 113 | } |
114 | }; | 114 | }; |
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 88e2f2db3..67ec257a8 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -13,7 +13,7 @@ pub(crate) mod rename; | |||
13 | 13 | ||
14 | use hir::Semantics; | 14 | use hir::Semantics; |
15 | use ide_db::{ | 15 | use ide_db::{ |
16 | defs::{classify_name, classify_name_ref, Definition}, | 16 | defs::{Definition, NameClass, NameRefClass}, |
17 | search::SearchScope, | 17 | search::SearchScope, |
18 | RootDatabase, | 18 | RootDatabase, |
19 | }; | 19 | }; |
@@ -132,13 +132,13 @@ fn find_name( | |||
132 | opt_name: Option<ast::Name>, | 132 | opt_name: Option<ast::Name>, |
133 | ) -> Option<RangeInfo<Definition>> { | 133 | ) -> Option<RangeInfo<Definition>> { |
134 | if let Some(name) = opt_name { | 134 | if let Some(name) = opt_name { |
135 | let def = classify_name(sema, &name)?.definition(sema.db); | 135 | let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db); |
136 | let range = name.syntax().text_range(); | 136 | let range = name.syntax().text_range(); |
137 | return Some(RangeInfo::new(range, def)); | 137 | return Some(RangeInfo::new(range, def)); |
138 | } | 138 | } |
139 | let name_ref = | 139 | let name_ref = |
140 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; | 140 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; |
141 | let def = classify_name_ref(sema, &name_ref)?.definition(sema.db); | 141 | let def = NameRefClass::classify(sema, &name_ref)?.referenced(sema.db); |
142 | let range = name_ref.syntax().text_range(); | 142 | let range = name_ref.syntax().text_range(); |
143 | Some(RangeInfo::new(range, def)) | 143 | Some(RangeInfo::new(range, def)) |
144 | } | 144 | } |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index f9a11e43d..35aafc49d 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use base_db::SourceDatabaseExt; | 3 | use base_db::SourceDatabaseExt; |
4 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 4 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
5 | use ide_db::{ | 5 | use ide_db::{ |
6 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 6 | defs::{Definition, NameClass, NameRefClass}, |
7 | RootDatabase, | 7 | RootDatabase, |
8 | }; | 8 | }; |
9 | 9 | ||
@@ -88,13 +88,13 @@ fn find_module_at_offset( | |||
88 | let module = match_ast! { | 88 | let module = match_ast! { |
89 | match (ident.parent()) { | 89 | match (ident.parent()) { |
90 | ast::NameRef(name_ref) => { | 90 | ast::NameRef(name_ref) => { |
91 | match classify_name_ref(sema, &name_ref)? { | 91 | match NameRefClass::classify(sema, &name_ref)? { |
92 | NameRefClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module, | 92 | NameRefClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module, |
93 | _ => return None, | 93 | _ => return None, |
94 | } | 94 | } |
95 | }, | 95 | }, |
96 | ast::Name(name) => { | 96 | ast::Name(name) => { |
97 | match classify_name(&sema, &name)? { | 97 | match NameClass::classify(&sema, &name)? { |
98 | NameClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module, | 98 | NameClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module, |
99 | _ => return None, | 99 | _ => return None, |
100 | } | 100 | } |
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 527888306..b35c03162 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -8,7 +8,7 @@ mod tests; | |||
8 | 8 | ||
9 | use hir::{Local, Name, Semantics, VariantDef}; | 9 | use hir::{Local, Name, Semantics, VariantDef}; |
10 | use ide_db::{ | 10 | use ide_db::{ |
11 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 11 | defs::{Definition, NameClass, NameRefClass}, |
12 | RootDatabase, | 12 | RootDatabase, |
13 | }; | 13 | }; |
14 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
@@ -443,7 +443,7 @@ fn highlight_element( | |||
443 | // Highlight definitions depending on the "type" of the definition. | 443 | // Highlight definitions depending on the "type" of the definition. |
444 | NAME => { | 444 | NAME => { |
445 | let name = element.into_node().and_then(ast::Name::cast).unwrap(); | 445 | let name = element.into_node().and_then(ast::Name::cast).unwrap(); |
446 | let name_kind = classify_name(sema, &name); | 446 | let name_kind = NameClass::classify(sema, &name); |
447 | 447 | ||
448 | if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind { | 448 | if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind { |
449 | if let Some(name) = local.name(db) { | 449 | if let Some(name) = local.name(db) { |
@@ -459,9 +459,9 @@ fn highlight_element( | |||
459 | highlight_def(db, def) | HighlightModifier::Definition | 459 | highlight_def(db, def) | HighlightModifier::Definition |
460 | } | 460 | } |
461 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), | 461 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), |
462 | Some(NameClass::FieldShorthand { field, .. }) => { | 462 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { |
463 | let mut h = HighlightTag::Field.into(); | 463 | let mut h = HighlightTag::Field.into(); |
464 | if let Definition::Field(field) = field { | 464 | if let Definition::Field(field) = field_ref { |
465 | if let VariantDef::Union(_) = field.parent_def(db) { | 465 | if let VariantDef::Union(_) = field.parent_def(db) { |
466 | h |= HighlightModifier::Unsafe; | 466 | h |= HighlightModifier::Unsafe; |
467 | } | 467 | } |
@@ -480,7 +480,7 @@ fn highlight_element( | |||
480 | NAME_REF => { | 480 | NAME_REF => { |
481 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 481 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
482 | highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { | 482 | highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { |
483 | match classify_name_ref(sema, &name_ref) { | 483 | match NameRefClass::classify(sema, &name_ref) { |
484 | Some(name_kind) => match name_kind { | 484 | Some(name_kind) => match name_kind { |
485 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), | 485 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), |
486 | NameRefClass::Definition(def) => { | 486 | NameRefClass::Definition(def) => { |
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index f8c7aa491..201a3d6fa 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs | |||
@@ -81,146 +81,152 @@ impl Definition { | |||
81 | pub enum NameClass { | 81 | pub enum NameClass { |
82 | ExternCrate(Crate), | 82 | ExternCrate(Crate), |
83 | Definition(Definition), | 83 | Definition(Definition), |
84 | /// `None` in `if let None = Some(82) {}` | 84 | /// `None` in `if let None = Some(82) {}`. |
85 | ConstReference(Definition), | 85 | ConstReference(Definition), |
86 | FieldShorthand { | 86 | /// `field` in `if let Foo { field } = foo`. |
87 | local: Local, | 87 | PatFieldShorthand { |
88 | field: Definition, | 88 | local_def: Local, |
89 | field_ref: Definition, | ||
89 | }, | 90 | }, |
90 | } | 91 | } |
91 | 92 | ||
92 | impl NameClass { | 93 | impl NameClass { |
93 | pub fn into_definition(self, db: &dyn HirDatabase) -> Option<Definition> { | 94 | /// `Definition` defined by this name. |
94 | Some(match self { | 95 | pub fn defined(self, db: &dyn HirDatabase) -> Option<Definition> { |
96 | let res = match self { | ||
95 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | 97 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), |
96 | NameClass::Definition(it) => it, | 98 | NameClass::Definition(it) => it, |
97 | NameClass::ConstReference(_) => return None, | 99 | NameClass::ConstReference(_) => return None, |
98 | NameClass::FieldShorthand { local, field: _ } => Definition::Local(local), | 100 | NameClass::PatFieldShorthand { local_def, field_ref: _ } => { |
99 | }) | 101 | Definition::Local(local_def) |
102 | } | ||
103 | }; | ||
104 | Some(res) | ||
100 | } | 105 | } |
101 | 106 | ||
102 | pub fn definition(self, db: &dyn HirDatabase) -> Definition { | 107 | /// `Definition` referenced or defined by this name. |
108 | pub fn referenced_or_defined(self, db: &dyn HirDatabase) -> Definition { | ||
103 | match self { | 109 | match self { |
104 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | 110 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), |
105 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, | 111 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, |
106 | NameClass::FieldShorthand { local: _, field } => field, | 112 | NameClass::PatFieldShorthand { local_def: _, field_ref } => field_ref, |
107 | } | 113 | } |
108 | } | 114 | } |
109 | } | ||
110 | 115 | ||
111 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { | 116 | pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { |
112 | let _p = profile::span("classify_name"); | 117 | let _p = profile::span("classify_name"); |
113 | 118 | ||
114 | let parent = name.syntax().parent()?; | 119 | let parent = name.syntax().parent()?; |
115 | 120 | ||
116 | if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) { | 121 | if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) { |
117 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { | 122 | if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { |
118 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); | 123 | return Some(NameClass::ConstReference(Definition::ModuleDef(def))); |
124 | } | ||
119 | } | 125 | } |
120 | } | ||
121 | 126 | ||
122 | match_ast! { | 127 | match_ast! { |
123 | match parent { | 128 | match parent { |
124 | ast::Rename(it) => { | 129 | ast::Rename(it) => { |
125 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { | 130 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { |
126 | let path = use_tree.path()?; | 131 | let path = use_tree.path()?; |
127 | let path_segment = path.segment()?; | 132 | let path_segment = path.segment()?; |
128 | let name_ref_class = path_segment | 133 | let name_ref_class = path_segment |
129 | .name_ref() | 134 | .name_ref() |
130 | // The rename might be from a `self` token, so fallback to the name higher | 135 | // The rename might be from a `self` token, so fallback to the name higher |
131 | // in the use tree. | 136 | // in the use tree. |
132 | .or_else(||{ | 137 | .or_else(||{ |
133 | if path_segment.self_token().is_none() { | 138 | if path_segment.self_token().is_none() { |
134 | return None; | 139 | return None; |
135 | } | 140 | } |
136 | 141 | ||
137 | let use_tree = use_tree | 142 | let use_tree = use_tree |
138 | .syntax() | 143 | .syntax() |
139 | .parent() | 144 | .parent() |
140 | .as_ref() | 145 | .as_ref() |
141 | // Skip over UseTreeList | 146 | // Skip over UseTreeList |
142 | .and_then(SyntaxNode::parent) | 147 | .and_then(SyntaxNode::parent) |
143 | .and_then(ast::UseTree::cast)?; | 148 | .and_then(ast::UseTree::cast)?; |
144 | let path = use_tree.path()?; | 149 | let path = use_tree.path()?; |
145 | let path_segment = path.segment()?; | 150 | let path_segment = path.segment()?; |
146 | path_segment.name_ref() | 151 | path_segment.name_ref() |
147 | }) | 152 | }) |
148 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; | 153 | .and_then(|name_ref| NameRefClass::classify(sema, &name_ref))?; |
149 | 154 | ||
150 | Some(NameClass::Definition(name_ref_class.definition(sema.db))) | 155 | Some(NameClass::Definition(name_ref_class.referenced(sema.db))) |
151 | } else { | 156 | } else { |
152 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; | 157 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; |
153 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | 158 | let resolved = sema.resolve_extern_crate(&extern_crate)?; |
154 | Some(NameClass::ExternCrate(resolved)) | 159 | Some(NameClass::ExternCrate(resolved)) |
155 | } | 160 | } |
156 | }, | 161 | }, |
157 | ast::IdentPat(it) => { | 162 | ast::IdentPat(it) => { |
158 | let local = sema.to_def(&it)?; | 163 | let local = sema.to_def(&it)?; |
159 | 164 | ||
160 | if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) { | 165 | if let Some(record_pat_field) = it.syntax().parent().and_then(ast::RecordPatField::cast) { |
161 | if record_pat_field.name_ref().is_none() { | 166 | if record_pat_field.name_ref().is_none() { |
162 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { | 167 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { |
163 | let field = Definition::Field(field); | 168 | let field = Definition::Field(field); |
164 | return Some(NameClass::FieldShorthand { local, field }); | 169 | return Some(NameClass::PatFieldShorthand { local_def: local, field_ref: field }); |
170 | } | ||
165 | } | 171 | } |
166 | } | 172 | } |
167 | } | ||
168 | 173 | ||
169 | Some(NameClass::Definition(Definition::Local(local))) | 174 | Some(NameClass::Definition(Definition::Local(local))) |
170 | }, | 175 | }, |
171 | ast::RecordField(it) => { | 176 | ast::RecordField(it) => { |
172 | let field: hir::Field = sema.to_def(&it)?; | 177 | let field: hir::Field = sema.to_def(&it)?; |
173 | Some(NameClass::Definition(Definition::Field(field))) | 178 | Some(NameClass::Definition(Definition::Field(field))) |
174 | }, | 179 | }, |
175 | ast::Module(it) => { | 180 | ast::Module(it) => { |
176 | let def = sema.to_def(&it)?; | 181 | let def = sema.to_def(&it)?; |
177 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 182 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
178 | }, | 183 | }, |
179 | ast::Struct(it) => { | 184 | ast::Struct(it) => { |
180 | let def: hir::Struct = sema.to_def(&it)?; | 185 | let def: hir::Struct = sema.to_def(&it)?; |
181 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 186 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
182 | }, | 187 | }, |
183 | ast::Union(it) => { | 188 | ast::Union(it) => { |
184 | let def: hir::Union = sema.to_def(&it)?; | 189 | let def: hir::Union = sema.to_def(&it)?; |
185 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 190 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
186 | }, | 191 | }, |
187 | ast::Enum(it) => { | 192 | ast::Enum(it) => { |
188 | let def: hir::Enum = sema.to_def(&it)?; | 193 | let def: hir::Enum = sema.to_def(&it)?; |
189 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 194 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
190 | }, | 195 | }, |
191 | ast::Trait(it) => { | 196 | ast::Trait(it) => { |
192 | let def: hir::Trait = sema.to_def(&it)?; | 197 | let def: hir::Trait = sema.to_def(&it)?; |
193 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 198 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
194 | }, | 199 | }, |
195 | ast::Static(it) => { | 200 | ast::Static(it) => { |
196 | let def: hir::Static = sema.to_def(&it)?; | 201 | let def: hir::Static = sema.to_def(&it)?; |
197 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 202 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
198 | }, | 203 | }, |
199 | ast::Variant(it) => { | 204 | ast::Variant(it) => { |
200 | let def: hir::EnumVariant = sema.to_def(&it)?; | 205 | let def: hir::EnumVariant = sema.to_def(&it)?; |
201 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 206 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
202 | }, | 207 | }, |
203 | ast::Fn(it) => { | 208 | ast::Fn(it) => { |
204 | let def: hir::Function = sema.to_def(&it)?; | 209 | let def: hir::Function = sema.to_def(&it)?; |
205 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 210 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
206 | }, | 211 | }, |
207 | ast::Const(it) => { | 212 | ast::Const(it) => { |
208 | let def: hir::Const = sema.to_def(&it)?; | 213 | let def: hir::Const = sema.to_def(&it)?; |
209 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 214 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
210 | }, | 215 | }, |
211 | ast::TypeAlias(it) => { | 216 | ast::TypeAlias(it) => { |
212 | let def: hir::TypeAlias = sema.to_def(&it)?; | 217 | let def: hir::TypeAlias = sema.to_def(&it)?; |
213 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) | 218 | Some(NameClass::Definition(Definition::ModuleDef(def.into()))) |
214 | }, | 219 | }, |
215 | ast::MacroCall(it) => { | 220 | ast::MacroCall(it) => { |
216 | let def = sema.to_def(&it)?; | 221 | let def = sema.to_def(&it)?; |
217 | Some(NameClass::Definition(Definition::Macro(def))) | 222 | Some(NameClass::Definition(Definition::Macro(def))) |
218 | }, | 223 | }, |
219 | ast::TypeParam(it) => { | 224 | ast::TypeParam(it) => { |
220 | let def = sema.to_def(&it)?; | 225 | let def = sema.to_def(&it)?; |
221 | Some(NameClass::Definition(Definition::TypeParam(def))) | 226 | Some(NameClass::Definition(Definition::TypeParam(def))) |
222 | }, | 227 | }, |
223 | _ => None, | 228 | _ => None, |
229 | } | ||
224 | } | 230 | } |
225 | } | 231 | } |
226 | } | 232 | } |
@@ -229,102 +235,109 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
229 | pub enum NameRefClass { | 235 | pub enum NameRefClass { |
230 | ExternCrate(Crate), | 236 | ExternCrate(Crate), |
231 | Definition(Definition), | 237 | Definition(Definition), |
232 | FieldShorthand { local: Local, field: Definition }, | 238 | FieldShorthand { local_ref: Local, field_ref: Definition }, |
233 | } | 239 | } |
234 | 240 | ||
235 | impl NameRefClass { | 241 | impl NameRefClass { |
236 | pub fn definition(self, db: &dyn HirDatabase) -> Definition { | 242 | /// `Definition`, which this name refers to. |
243 | pub fn referenced(self, db: &dyn HirDatabase) -> Definition { | ||
237 | match self { | 244 | match self { |
238 | NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), | 245 | NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()), |
239 | NameRefClass::Definition(def) => def, | 246 | NameRefClass::Definition(def) => def, |
240 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), | 247 | NameRefClass::FieldShorthand { local_ref, field_ref: _ } => { |
248 | // FIXME: this is inherently ambiguous -- this name refers to | ||
249 | // two different defs.... | ||
250 | Definition::Local(local_ref) | ||
251 | } | ||
241 | } | 252 | } |
242 | } | 253 | } |
243 | } | ||
244 | 254 | ||
245 | // Note: we don't have unit-tests for this rather important function. | 255 | // Note: we don't have unit-tests for this rather important function. |
246 | // It is primarily exercised via goto definition tests in `ide`. | 256 | // It is primarily exercised via goto definition tests in `ide`. |
247 | pub fn classify_name_ref( | 257 | pub fn classify( |
248 | sema: &Semantics<RootDatabase>, | 258 | sema: &Semantics<RootDatabase>, |
249 | name_ref: &ast::NameRef, | 259 | name_ref: &ast::NameRef, |
250 | ) -> Option<NameRefClass> { | 260 | ) -> Option<NameRefClass> { |
251 | let _p = profile::span("classify_name_ref"); | 261 | let _p = profile::span("classify_name_ref"); |
252 | 262 | ||
253 | let parent = name_ref.syntax().parent()?; | 263 | let parent = name_ref.syntax().parent()?; |
254 | 264 | ||
255 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 265 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
256 | if let Some(func) = sema.resolve_method_call(&method_call) { | 266 | if let Some(func) = sema.resolve_method_call(&method_call) { |
257 | return Some(NameRefClass::Definition(Definition::ModuleDef(func.into()))); | 267 | return Some(NameRefClass::Definition(Definition::ModuleDef(func.into()))); |
268 | } | ||
258 | } | 269 | } |
259 | } | ||
260 | 270 | ||
261 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 271 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
262 | if let Some(field) = sema.resolve_field(&field_expr) { | 272 | if let Some(field) = sema.resolve_field(&field_expr) { |
263 | return Some(NameRefClass::Definition(Definition::Field(field))); | 273 | return Some(NameRefClass::Definition(Definition::Field(field))); |
274 | } | ||
264 | } | 275 | } |
265 | } | ||
266 | 276 | ||
267 | if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) { | 277 | if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) { |
268 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { | 278 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { |
269 | let field = Definition::Field(field); | 279 | let field = Definition::Field(field); |
270 | let res = match local { | 280 | let res = match local { |
271 | None => NameRefClass::Definition(field), | 281 | None => NameRefClass::Definition(field), |
272 | Some(local) => NameRefClass::FieldShorthand { field, local }, | 282 | Some(local) => { |
273 | }; | 283 | NameRefClass::FieldShorthand { field_ref: field, local_ref: local } |
274 | return Some(res); | 284 | } |
285 | }; | ||
286 | return Some(res); | ||
287 | } | ||
275 | } | 288 | } |
276 | } | ||
277 | 289 | ||
278 | if let Some(record_pat_field) = ast::RecordPatField::cast(parent.clone()) { | 290 | if let Some(record_pat_field) = ast::RecordPatField::cast(parent.clone()) { |
279 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { | 291 | if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) { |
280 | let field = Definition::Field(field); | 292 | let field = Definition::Field(field); |
281 | return Some(NameRefClass::Definition(field)); | 293 | return Some(NameRefClass::Definition(field)); |
294 | } | ||
282 | } | 295 | } |
283 | } | ||
284 | 296 | ||
285 | if ast::AssocTypeArg::cast(parent.clone()).is_some() { | 297 | if ast::AssocTypeArg::cast(parent.clone()).is_some() { |
286 | // `Trait<Assoc = Ty>` | 298 | // `Trait<Assoc = Ty>` |
287 | // ^^^^^ | 299 | // ^^^^^ |
288 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 300 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
289 | let resolved = sema.resolve_path(&path)?; | 301 | let resolved = sema.resolve_path(&path)?; |
290 | if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved { | 302 | if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved { |
291 | if let Some(ty) = tr | 303 | if let Some(ty) = tr |
292 | .items(sema.db) | 304 | .items(sema.db) |
293 | .iter() | 305 | .iter() |
294 | .filter_map(|assoc| match assoc { | 306 | .filter_map(|assoc| match assoc { |
295 | hir::AssocItem::TypeAlias(it) => Some(*it), | 307 | hir::AssocItem::TypeAlias(it) => Some(*it), |
296 | _ => None, | 308 | _ => None, |
297 | }) | 309 | }) |
298 | .find(|alias| alias.name(sema.db).to_string() == **name_ref.text()) | 310 | .find(|alias| alias.name(sema.db).to_string() == **name_ref.text()) |
299 | { | 311 | { |
300 | return Some(NameRefClass::Definition(Definition::ModuleDef( | 312 | return Some(NameRefClass::Definition(Definition::ModuleDef( |
301 | ModuleDef::TypeAlias(ty), | 313 | ModuleDef::TypeAlias(ty), |
302 | ))); | 314 | ))); |
315 | } | ||
303 | } | 316 | } |
304 | } | 317 | } |
305 | } | ||
306 | 318 | ||
307 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 319 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
308 | if let Some(path) = macro_call.path() { | 320 | if let Some(path) = macro_call.path() { |
309 | if path.qualifier().is_none() { | 321 | if path.qualifier().is_none() { |
310 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment | 322 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment |
311 | // paths are handled below (allowing `log<|>::info!` to resolve to the log crate). | 323 | // paths are handled below (allowing `log<|>::info!` to resolve to the log crate). |
312 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 324 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
313 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); | 325 | return Some(NameRefClass::Definition(Definition::Macro(macro_def))); |
326 | } | ||
314 | } | 327 | } |
315 | } | 328 | } |
316 | } | 329 | } |
317 | } | ||
318 | 330 | ||
319 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { | 331 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { |
320 | if let Some(resolved) = sema.resolve_path(&path) { | 332 | if let Some(resolved) = sema.resolve_path(&path) { |
321 | return Some(NameRefClass::Definition(resolved.into())); | 333 | return Some(NameRefClass::Definition(resolved.into())); |
334 | } | ||
322 | } | 335 | } |
323 | } | ||
324 | 336 | ||
325 | let extern_crate = ast::ExternCrate::cast(parent)?; | 337 | let extern_crate = ast::ExternCrate::cast(parent)?; |
326 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | 338 | let resolved = sema.resolve_extern_crate(&extern_crate)?; |
327 | Some(NameRefClass::ExternCrate(resolved)) | 339 | Some(NameRefClass::ExternCrate(resolved)) |
340 | } | ||
328 | } | 341 | } |
329 | 342 | ||
330 | impl From<PathResolution> for Definition { | 343 | impl From<PathResolution> for Definition { |
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs index ed67e3553..df74be00b 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}; | |||
5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; | 5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | defs::{classify_name, Definition}, | 8 | defs::{Definition, NameClass}, |
9 | symbol_index::{self, FileSymbol, Query}, | 9 | symbol_index::{self, FileSymbol, Query}, |
10 | RootDatabase, | 10 | RootDatabase, |
11 | }; | 11 | }; |
@@ -60,5 +60,5 @@ fn get_name_definition<'a>( | |||
60 | candidate_node | 60 | candidate_node |
61 | }; | 61 | }; |
62 | let name = ast::Name::cast(candidate_name_node)?; | 62 | let name = ast::Name::cast(candidate_name_node)?; |
63 | classify_name(sema, &name)?.into_definition(sema.db) | 63 | NameClass::classify(sema, &name)?.defined(sema.db) |
64 | } | 64 | } |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 8e3dcd99c..a24335240 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}; | |||
14 | 14 | ||
15 | use crate::defs::NameClass; | 15 | use crate::defs::NameClass; |
16 | use crate::{ | 16 | use crate::{ |
17 | defs::{classify_name, classify_name_ref, Definition, NameRefClass}, | 17 | defs::{Definition, NameRefClass}, |
18 | RootDatabase, | 18 | RootDatabase, |
19 | }; | 19 | }; |
20 | 20 | ||
@@ -276,7 +276,7 @@ impl<'a> FindUsages<'a> { | |||
276 | name_ref: &ast::NameRef, | 276 | name_ref: &ast::NameRef, |
277 | sink: &mut dyn FnMut(Reference) -> bool, | 277 | sink: &mut dyn FnMut(Reference) -> bool, |
278 | ) -> bool { | 278 | ) -> bool { |
279 | match classify_name_ref(self.sema, &name_ref) { | 279 | match NameRefClass::classify(self.sema, &name_ref) { |
280 | Some(NameRefClass::Definition(def)) if &def == self.def => { | 280 | Some(NameRefClass::Definition(def)) if &def == self.def => { |
281 | let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) | 281 | let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) |
282 | { | 282 | { |
@@ -292,7 +292,7 @@ impl<'a> FindUsages<'a> { | |||
292 | }; | 292 | }; |
293 | sink(reference) | 293 | sink(reference) |
294 | } | 294 | } |
295 | Some(NameRefClass::FieldShorthand { local, field }) => { | 295 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { |
296 | let reference = match self.def { | 296 | let reference = match self.def { |
297 | Definition::Field(_) if &field == self.def => Reference { | 297 | Definition::Field(_) if &field == self.def => Reference { |
298 | file_range: self.sema.original_range(name_ref.syntax()), | 298 | file_range: self.sema.original_range(name_ref.syntax()), |
@@ -313,10 +313,10 @@ impl<'a> FindUsages<'a> { | |||
313 | } | 313 | } |
314 | 314 | ||
315 | fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool { | 315 | fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool { |
316 | match classify_name(self.sema, name) { | 316 | match NameClass::classify(self.sema, name) { |
317 | Some(NameClass::FieldShorthand { local: _, field }) => { | 317 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) => { |
318 | let reference = match self.def { | 318 | let reference = match self.def { |
319 | Definition::Field(_) if &field == self.def => Reference { | 319 | Definition::Field(_) if &field_ref == self.def => Reference { |
320 | file_range: self.sema.original_range(name.syntax()), | 320 | file_range: self.sema.original_range(name.syntax()), |
321 | kind: ReferenceKind::FieldShorthandForField, | 321 | kind: ReferenceKind::FieldShorthandForField, |
322 | // FIXME: mutable patterns should have `Write` access | 322 | // FIXME: mutable patterns should have `Write` access |