diff options
author | Paul Daniel Faria <[email protected]> | 2020-08-08 19:14:18 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-08-08 19:14:18 +0100 |
commit | 6cde0b1aa0f6b8623c6b81b2396f4a0345891233 (patch) | |
tree | 9d558ee8eeace0aadf241c190248d008e362d17f /crates | |
parent | a69f19a6a5899bdfb6fc498371650bf54263deff (diff) |
Add support for extern crate
This adds syntax highlighting, hover and goto def
functionality for extern crate
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/handlers/add_turbo_fish.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 25 | ||||
-rw-r--r-- | crates/ra_ide/src/display/short_label.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 37 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 49 | ||||
-rw-r--r-- | crates/ra_ide/src/references.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide/test_data/highlight_extern_crate.html | 40 | ||||
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 100 | ||||
-rw-r--r-- | crates/ra_ide_db/src/imports_locator.rs | 2 |
11 files changed, 225 insertions, 59 deletions
diff --git a/crates/ra_assists/src/handlers/add_turbo_fish.rs b/crates/ra_assists/src/handlers/add_turbo_fish.rs index 0c565e89a..537322a72 100644 --- a/crates/ra_assists/src/handlers/add_turbo_fish.rs +++ b/crates/ra_assists/src/handlers/add_turbo_fish.rs | |||
@@ -41,7 +41,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
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 classify_name_ref(&ctx.sema, &name_ref)? { |
43 | NameRefClass::Definition(def) => def, | 43 | NameRefClass::Definition(def) => def, |
44 | NameRefClass::FieldShorthand { .. } => return None, | 44 | NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, |
45 | }; | 45 | }; |
46 | let fun = match def { | 46 | let fun = match def { |
47 | Definition::ModuleDef(hir::ModuleDef::Function(it)) => it, | 47 | Definition::ModuleDef(hir::ModuleDef::Function(it)) => it, |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 307b336f2..e392130ab 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -8,7 +8,7 @@ use hir_def::{ | |||
8 | resolver::{self, HasResolver, Resolver}, | 8 | resolver::{self, HasResolver, Resolver}, |
9 | AsMacroCall, FunctionId, TraitId, VariantId, | 9 | AsMacroCall, FunctionId, TraitId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; | 11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, name::AsName, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{FileId, FileRange}; | 14 | use ra_db::{FileId, FileRange}; |
@@ -24,8 +24,8 @@ use crate::{ | |||
24 | diagnostics::Diagnostic, | 24 | diagnostics::Diagnostic, |
25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, |
27 | AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, | 27 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, |
28 | ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, | 28 | Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, |
29 | }; | 29 | }; |
30 | use resolver::TypeNs; | 30 | use resolver::TypeNs; |
31 | 31 | ||
@@ -228,6 +228,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
228 | self.imp.resolve_path(path) | 228 | self.imp.resolve_path(path) |
229 | } | 229 | } |
230 | 230 | ||
231 | pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { | ||
232 | self.imp.resolve_extern_crate(extern_crate) | ||
233 | } | ||
234 | |||
231 | pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> { | 235 | pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> { |
232 | self.imp.resolve_variant(record_lit).map(VariantDef::from) | 236 | self.imp.resolve_variant(record_lit).map(VariantDef::from) |
233 | } | 237 | } |
@@ -443,6 +447,17 @@ impl<'db> SemanticsImpl<'db> { | |||
443 | self.analyze(path.syntax()).resolve_path(self.db, path) | 447 | self.analyze(path.syntax()).resolve_path(self.db, path) |
444 | } | 448 | } |
445 | 449 | ||
450 | fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { | ||
451 | let krate = self.scope(extern_crate.syntax()).krate()?; | ||
452 | krate.dependencies(self.db).into_iter().find_map(|dep| { | ||
453 | if dep.name == extern_crate.name_ref()?.as_name() { | ||
454 | Some(dep.krate) | ||
455 | } else { | ||
456 | None | ||
457 | } | ||
458 | }) | ||
459 | } | ||
460 | |||
446 | fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { | 461 | fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { |
447 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) | 462 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) |
448 | } | 463 | } |
@@ -612,6 +627,10 @@ impl<'a> SemanticsScope<'a> { | |||
612 | Some(Module { id: self.resolver.module()? }) | 627 | Some(Module { id: self.resolver.module()? }) |
613 | } | 628 | } |
614 | 629 | ||
630 | pub fn krate(&self) -> Option<Crate> { | ||
631 | Some(Crate { id: self.resolver.krate()? }) | ||
632 | } | ||
633 | |||
615 | /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type | 634 | /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type |
616 | // FIXME: rename to visible_traits to not repeat scope? | 635 | // FIXME: rename to visible_traits to not repeat scope? |
617 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { | 636 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { |
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index 0fdf8e9a5..b5ff9fa2d 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs | |||
@@ -47,6 +47,12 @@ impl ShortLabel for ast::Module { | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | impl ShortLabel for ast::SourceFile { | ||
51 | fn short_label(&self) -> Option<String> { | ||
52 | None | ||
53 | } | ||
54 | } | ||
55 | |||
50 | impl ShortLabel for ast::TypeAlias { | 56 | impl ShortLabel for ast::TypeAlias { |
51 | fn short_label(&self) -> Option<String> { | 57 | fn short_label(&self) -> Option<String> { |
52 | short_label_from_node(self, "type ") | 58 | short_label_from_node(self, "type ") |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 4e3f428fa..b44b6fe22 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use hir::Semantics; | 1 | use hir::Semantics; |
2 | use ra_ide_db::{ | 2 | use ra_ide_db::{ |
3 | defs::{classify_name, classify_name_ref, NameClass}, | 3 | defs::{classify_name, classify_name_ref}, |
4 | symbol_index, RootDatabase, | 4 | symbol_index, RootDatabase, |
5 | }; | 5 | }; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -40,10 +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 = match classify_name(&sema, &name)? { | 43 | let def = classify_name(&sema, &name)?.definition(sema.db)?; |
44 | NameClass::Definition(def) | NameClass::ConstReference(def) => def, | ||
45 | NameClass::FieldShorthand { local: _, field } => field, | ||
46 | }; | ||
47 | let nav = def.try_to_nav(sema.db)?; | 44 | let nav = def.try_to_nav(sema.db)?; |
48 | vec![nav] | 45 | vec![nav] |
49 | }, | 46 | }, |
@@ -85,9 +82,7 @@ pub(crate) fn reference_definition( | |||
85 | name_ref: &ast::NameRef, | 82 | name_ref: &ast::NameRef, |
86 | ) -> ReferenceResult { | 83 | ) -> ReferenceResult { |
87 | let name_kind = classify_name_ref(sema, name_ref); | 84 | let name_kind = classify_name_ref(sema, name_ref); |
88 | if let Some(def) = name_kind { | 85 | if let Some(def) = name_kind.and_then(|def| def.definition(sema.db)) { |
89 | let def = def.definition(); | ||
90 | |||
91 | return match def.try_to_nav(sema.db) { | 86 | return match def.try_to_nav(sema.db) { |
92 | Some(nav) => ReferenceResult::Exact(nav), | 87 | Some(nav) => ReferenceResult::Exact(nav), |
93 | None => ReferenceResult::Approximate(Vec::new()), | 88 | None => ReferenceResult::Approximate(Vec::new()), |
@@ -134,6 +129,32 @@ mod tests { | |||
134 | } | 129 | } |
135 | 130 | ||
136 | #[test] | 131 | #[test] |
132 | fn goto_def_for_extern_crate() { | ||
133 | check( | ||
134 | r#" | ||
135 | //- /main.rs | ||
136 | extern crate std<|>; | ||
137 | //- /std/lib.rs | ||
138 | // empty | ||
139 | //^ file | ||
140 | "#, | ||
141 | ) | ||
142 | } | ||
143 | |||
144 | #[test] | ||
145 | fn goto_def_for_renamed_extern_crate() { | ||
146 | check( | ||
147 | r#" | ||
148 | //- /main.rs | ||
149 | extern crate std as abc<|>; | ||
150 | //- /std/lib.rs | ||
151 | // empty | ||
152 | //^ file | ||
153 | "#, | ||
154 | ) | ||
155 | } | ||
156 | |||
157 | #[test] | ||
137 | fn goto_def_in_items() { | 158 | fn goto_def_in_items() { |
138 | check( | 159 | check( |
139 | r#" | 160 | r#" |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index aa48cb412..a632ea6a2 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -85,8 +85,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
85 | let node = token.parent(); | 85 | let node = token.parent(); |
86 | let definition = match_ast! { | 86 | let definition = match_ast! { |
87 | match node { | 87 | match node { |
88 | ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition()), | 88 | ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).and_then(|d| d.definition(sema.db)), |
89 | ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition()), | 89 | ast::Name(name) => classify_name(&sema, &name).and_then(|d| d.definition(sema.db)), |
90 | _ => None, | 90 | _ => None, |
91 | } | 91 | } |
92 | }; | 92 | }; |
@@ -304,7 +304,10 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
304 | let docs = Documentation::from_ast(&it).map(Into::into); | 304 | let docs = Documentation::from_ast(&it).map(Into::into); |
305 | hover_markup(docs, it.short_label(), mod_path) | 305 | hover_markup(docs, it.short_label(), mod_path) |
306 | } | 306 | } |
307 | _ => None, | 307 | ModuleSource::SourceFile(it) => { |
308 | let docs = Documentation::from_ast(&it).map(Into::into); | ||
309 | hover_markup(docs, it.short_label(), mod_path) | ||
310 | } | ||
308 | }, | 311 | }, |
309 | ModuleDef::Function(it) => from_def_source(db, it, mod_path), | 312 | ModuleDef::Function(it) => from_def_source(db, it, mod_path), |
310 | ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), | 313 | ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), |
@@ -1107,6 +1110,46 @@ fn bar() { fo<|>o(); } | |||
1107 | } | 1110 | } |
1108 | 1111 | ||
1109 | #[test] | 1112 | #[test] |
1113 | fn test_hover_extern_crate() { | ||
1114 | check( | ||
1115 | r#" | ||
1116 | //- /main.rs | ||
1117 | extern crate st<|>d; | ||
1118 | //- /std/lib.rs | ||
1119 | //! Standard library for this test | ||
1120 | //! | ||
1121 | //! Printed? | ||
1122 | //! abc123 | ||
1123 | "#, | ||
1124 | expect![[r#" | ||
1125 | *std* | ||
1126 | Standard library for this test | ||
1127 | |||
1128 | Printed? | ||
1129 | abc123 | ||
1130 | "#]], | ||
1131 | ); | ||
1132 | check( | ||
1133 | r#" | ||
1134 | //- /main.rs | ||
1135 | extern crate std as ab<|>c; | ||
1136 | //- /std/lib.rs | ||
1137 | //! Standard library for this test | ||
1138 | //! | ||
1139 | //! Printed? | ||
1140 | //! abc123 | ||
1141 | "#, | ||
1142 | expect![[r#" | ||
1143 | *abc* | ||
1144 | Standard library for this test | ||
1145 | |||
1146 | Printed? | ||
1147 | abc123 | ||
1148 | "#]], | ||
1149 | ); | ||
1150 | } | ||
1151 | |||
1152 | #[test] | ||
1110 | fn test_hover_mod_with_same_name_as_function() { | 1153 | fn test_hover_mod_with_same_name_as_function() { |
1111 | check( | 1154 | check( |
1112 | r#" | 1155 | r#" |
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index cf456630a..9dd228b9c 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -130,13 +130,13 @@ fn find_name( | |||
130 | opt_name: Option<ast::Name>, | 130 | opt_name: Option<ast::Name>, |
131 | ) -> Option<RangeInfo<Definition>> { | 131 | ) -> Option<RangeInfo<Definition>> { |
132 | if let Some(name) = opt_name { | 132 | if let Some(name) = opt_name { |
133 | let def = classify_name(sema, &name)?.definition(); | 133 | let def = classify_name(sema, &name)?.definition(sema.db)?; |
134 | let range = name.syntax().text_range(); | 134 | let range = name.syntax().text_range(); |
135 | return Some(RangeInfo::new(range, def)); | 135 | return Some(RangeInfo::new(range, def)); |
136 | } | 136 | } |
137 | let name_ref = | 137 | let name_ref = |
138 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; | 138 | sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; |
139 | let def = classify_name_ref(sema, &name_ref)?.definition(); | 139 | let def = classify_name_ref(sema, &name_ref)?.definition(sema.db)?; |
140 | let range = name_ref.syntax().text_range(); | 140 | let range = name_ref.syntax().text_range(); |
141 | Some(RangeInfo::new(range, def)) | 141 | Some(RangeInfo::new(range, def)) |
142 | } | 142 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 89efe71da..ec442bcd8 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -483,6 +483,7 @@ fn highlight_element( | |||
483 | }; | 483 | }; |
484 | 484 | ||
485 | match name_kind { | 485 | match name_kind { |
486 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), | ||
486 | Some(NameClass::Definition(def)) => { | 487 | Some(NameClass::Definition(def)) => { |
487 | highlight_name(db, def) | HighlightModifier::Definition | 488 | highlight_name(db, def) | HighlightModifier::Definition |
488 | } | 489 | } |
@@ -500,6 +501,7 @@ fn highlight_element( | |||
500 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 501 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
501 | match classify_name_ref(sema, &name_ref) { | 502 | match classify_name_ref(sema, &name_ref) { |
502 | Some(name_kind) => match name_kind { | 503 | Some(name_kind) => match name_kind { |
504 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), | ||
503 | NameRefClass::Definition(def) => { | 505 | NameRefClass::Definition(def) => { |
504 | if let Definition::Local(local) = &def { | 506 | if let Definition::Local(local) = &def { |
505 | if let Some(name) = local.name(db) { | 507 | if let Some(name) = local.name(db) { |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index b9b358022..b8d60bdc6 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -380,6 +380,23 @@ macro_rules! noop { | |||
380 | ); | 380 | ); |
381 | } | 381 | } |
382 | 382 | ||
383 | #[test] | ||
384 | fn test_extern_crate() { | ||
385 | check_highlighting( | ||
386 | r#" | ||
387 | //- /main.rs | ||
388 | extern crate std; | ||
389 | extern crate alloc as abc; | ||
390 | //- /std/lib.rs | ||
391 | pub struct S; | ||
392 | //- /alloc/lib.rs | ||
393 | pub struct A | ||
394 | "#, | ||
395 | expect_file!["crates/ra_ide/test_data/highlight_extern_crate.html"], | ||
396 | false, | ||
397 | ); | ||
398 | } | ||
399 | |||
383 | /// Highlights the code given by the `ra_fixture` argument, renders the | 400 | /// Highlights the code given by the `ra_fixture` argument, renders the |
384 | /// result as HTML, and compares it with the HTML file given as `snapshot`. | 401 | /// result as HTML, and compares it with the HTML file given as `snapshot`. |
385 | /// Note that the `snapshot` file is overwritten by the rendered HTML. | 402 | /// Note that the `snapshot` file is overwritten by the rendered HTML. |
diff --git a/crates/ra_ide/test_data/highlight_extern_crate.html b/crates/ra_ide/test_data/highlight_extern_crate.html new file mode 100644 index 000000000..800d894c7 --- /dev/null +++ b/crates/ra_ide/test_data/highlight_extern_crate.html | |||
@@ -0,0 +1,40 @@ | |||
1 | |||
2 | <style> | ||
3 | body { margin: 0; } | ||
4 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } | ||
5 | |||
6 | .lifetime { color: #DFAF8F; font-style: italic; } | ||
7 | .comment { color: #7F9F7F; } | ||
8 | .documentation { color: #629755; } | ||
9 | .injected { opacity: 0.65 ; } | ||
10 | .struct, .enum { color: #7CB8BB; } | ||
11 | .enum_variant { color: #BDE0F3; } | ||
12 | .string_literal { color: #CC9393; } | ||
13 | .field { color: #94BFF3; } | ||
14 | .function { color: #93E0E3; } | ||
15 | .function.unsafe { color: #BC8383; } | ||
16 | .operator.unsafe { color: #BC8383; } | ||
17 | .parameter { color: #94BFF3; } | ||
18 | .text { color: #DCDCCC; } | ||
19 | .type { color: #7CB8BB; } | ||
20 | .builtin_type { color: #8CD0D3; } | ||
21 | .type_param { color: #DFAF8F; } | ||
22 | .attribute { color: #94BFF3; } | ||
23 | .numeric_literal { color: #BFEBBF; } | ||
24 | .bool_literal { color: #BFE6EB; } | ||
25 | .macro { color: #94BFF3; } | ||
26 | .module { color: #AFD8AF; } | ||
27 | .value_param { color: #DCDCCC; } | ||
28 | .variable { color: #DCDCCC; } | ||
29 | .format_specifier { color: #CC696B; } | ||
30 | .mutable { text-decoration: underline; } | ||
31 | .escape_sequence { color: #94BFF3; } | ||
32 | .keyword { color: #F0DFAF; font-weight: bold; } | ||
33 | .keyword.unsafe { color: #BC8383; font-weight: bold; } | ||
34 | .control { font-style: italic; } | ||
35 | |||
36 | .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } | ||
37 | </style> | ||
38 | <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">std</span><span class="punctuation">;</span> | ||
39 | <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module">alloc</span> <span class="keyword">as</span> <span class="module">abc</span><span class="punctuation">;</span> | ||
40 | </code></pre> \ No newline at end of file | ||
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index b51000b03..e2a4f2983 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -6,8 +6,8 @@ | |||
6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). | 6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). |
7 | 7 | ||
8 | use hir::{ | 8 | use hir::{ |
9 | Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution, | 9 | db::HirDatabase, Crate, Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, |
10 | Semantics, TypeParam, Visibility, | 10 | Name, PathResolution, Semantics, TypeParam, Visibility, |
11 | }; | 11 | }; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
@@ -80,6 +80,7 @@ impl Definition { | |||
80 | 80 | ||
81 | #[derive(Debug)] | 81 | #[derive(Debug)] |
82 | pub enum NameClass { | 82 | pub enum NameClass { |
83 | ExternCrate(Crate), | ||
83 | Definition(Definition), | 84 | Definition(Definition), |
84 | /// `None` in `if let None = Some(82) {}` | 85 | /// `None` in `if let None = Some(82) {}` |
85 | ConstReference(Definition), | 86 | ConstReference(Definition), |
@@ -90,19 +91,21 @@ pub enum NameClass { | |||
90 | } | 91 | } |
91 | 92 | ||
92 | impl NameClass { | 93 | impl NameClass { |
93 | pub fn into_definition(self) -> Option<Definition> { | 94 | pub fn into_definition(self, db: &dyn HirDatabase) -> Option<Definition> { |
94 | match self { | 95 | Some(match self { |
95 | NameClass::Definition(it) => Some(it), | 96 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db)?.into()), |
96 | NameClass::ConstReference(_) => None, | 97 | NameClass::Definition(it) => it, |
97 | NameClass::FieldShorthand { local, field: _ } => Some(Definition::Local(local)), | 98 | NameClass::ConstReference(_) => return None, |
98 | } | 99 | NameClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
100 | }) | ||
99 | } | 101 | } |
100 | 102 | ||
101 | pub fn definition(self) -> Definition { | 103 | pub fn definition(self, db: &dyn HirDatabase) -> Option<Definition> { |
102 | match self { | 104 | Some(match self { |
105 | NameClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db)?.into()), | ||
103 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, | 106 | NameClass::Definition(it) | NameClass::ConstReference(it) => it, |
104 | NameClass::FieldShorthand { local: _, field } => field, | 107 | NameClass::FieldShorthand { local: _, field } => field, |
105 | } | 108 | }) |
106 | } | 109 | } |
107 | } | 110 | } |
108 | 111 | ||
@@ -120,32 +123,37 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
120 | match_ast! { | 123 | match_ast! { |
121 | match parent { | 124 | match parent { |
122 | ast::Rename(it) => { | 125 | ast::Rename(it) => { |
123 | let use_tree = it.syntax().parent().and_then(ast::UseTree::cast)?; | 126 | if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) { |
124 | let path = use_tree.path()?; | 127 | let path = use_tree.path()?; |
125 | let path_segment = path.segment()?; | 128 | let path_segment = path.segment()?; |
126 | let name_ref_class = path_segment | 129 | let name_ref_class = path_segment |
127 | .name_ref() | 130 | .name_ref() |
128 | // The rename might be from a `self` token, so fallback to the name higher | 131 | // The rename might be from a `self` token, so fallback to the name higher |
129 | // in the use tree. | 132 | // in the use tree. |
130 | .or_else(||{ | 133 | .or_else(||{ |
131 | if path_segment.self_token().is_none() { | 134 | if path_segment.self_token().is_none() { |
132 | return None; | 135 | return None; |
133 | } | 136 | } |
134 | 137 | ||
135 | let use_tree = use_tree | 138 | let use_tree = use_tree |
136 | .syntax() | 139 | .syntax() |
137 | .parent() | 140 | .parent() |
138 | .as_ref() | 141 | .as_ref() |
139 | // Skip over UseTreeList | 142 | // Skip over UseTreeList |
140 | .and_then(SyntaxNode::parent) | 143 | .and_then(SyntaxNode::parent) |
141 | .and_then(ast::UseTree::cast)?; | 144 | .and_then(ast::UseTree::cast)?; |
142 | let path = use_tree.path()?; | 145 | let path = use_tree.path()?; |
143 | let path_segment = path.segment()?; | 146 | let path_segment = path.segment()?; |
144 | path_segment.name_ref() | 147 | path_segment.name_ref() |
145 | }) | 148 | }) |
146 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; | 149 | .and_then(|name_ref| classify_name_ref(sema, &name_ref))?; |
147 | 150 | ||
148 | Some(NameClass::Definition(name_ref_class.definition())) | 151 | Some(NameClass::Definition(name_ref_class.definition(sema.db)?)) |
152 | } else { | ||
153 | let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?; | ||
154 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | ||
155 | Some(NameClass::ExternCrate(resolved)) | ||
156 | } | ||
149 | }, | 157 | }, |
150 | ast::IdentPat(it) => { | 158 | ast::IdentPat(it) => { |
151 | let local = sema.to_def(&it)?; | 159 | let local = sema.to_def(&it)?; |
@@ -220,16 +228,20 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option | |||
220 | 228 | ||
221 | #[derive(Debug)] | 229 | #[derive(Debug)] |
222 | pub enum NameRefClass { | 230 | pub enum NameRefClass { |
231 | ExternCrate(Crate), | ||
223 | Definition(Definition), | 232 | Definition(Definition), |
224 | FieldShorthand { local: Local, field: Definition }, | 233 | FieldShorthand { local: Local, field: Definition }, |
225 | } | 234 | } |
226 | 235 | ||
227 | impl NameRefClass { | 236 | impl NameRefClass { |
228 | pub fn definition(self) -> Definition { | 237 | pub fn definition(self, db: &dyn HirDatabase) -> Option<Definition> { |
229 | match self { | 238 | Some(match self { |
239 | NameRefClass::ExternCrate(krate) => { | ||
240 | Definition::ModuleDef(krate.root_module(db)?.into()) | ||
241 | } | ||
230 | NameRefClass::Definition(def) => def, | 242 | NameRefClass::Definition(def) => def, |
231 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), | 243 | NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), |
232 | } | 244 | }) |
233 | } | 245 | } |
234 | } | 246 | } |
235 | 247 | ||
@@ -307,9 +319,15 @@ pub fn classify_name_ref( | |||
307 | } | 319 | } |
308 | } | 320 | } |
309 | 321 | ||
310 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 322 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { |
311 | let resolved = sema.resolve_path(&path)?; | 323 | if let Some(resolved) = sema.resolve_path(&path) { |
312 | Some(NameRefClass::Definition(resolved.into())) | 324 | return Some(NameRefClass::Definition(resolved.into())); |
325 | } | ||
326 | } | ||
327 | |||
328 | let extern_crate = ast::ExternCrate::cast(parent)?; | ||
329 | let resolved = sema.resolve_extern_crate(&extern_crate)?; | ||
330 | Some(NameRefClass::ExternCrate(resolved)) | ||
313 | } | 331 | } |
314 | 332 | ||
315 | impl From<PathResolution> for Definition { | 333 | impl From<PathResolution> for Definition { |
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs index 1fba71ff8..9e040973b 100644 --- a/crates/ra_ide_db/src/imports_locator.rs +++ b/crates/ra_ide_db/src/imports_locator.rs | |||
@@ -61,5 +61,5 @@ fn get_name_definition<'a>( | |||
61 | candidate_node | 61 | candidate_node |
62 | }; | 62 | }; |
63 | let name = ast::Name::cast(candidate_name_node)?; | 63 | let name = ast::Name::cast(candidate_name_node)?; |
64 | classify_name(sema, &name)?.into_definition() | 64 | classify_name(sema, &name)?.into_definition(sema.db) |
65 | } | 65 | } |