aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/handlers/add_turbo_fish.rs2
-rw-r--r--crates/ra_assists/src/utils.rs2
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/semantics.rs25
-rw-r--r--crates/ra_ide/src/display/short_label.rs12
-rw-r--r--crates/ra_ide/src/goto_definition.rs36
-rw-r--r--crates/ra_ide/src/hover.rs57
-rw-r--r--crates/ra_ide/src/references.rs4
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs2
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs17
-rw-r--r--crates/ra_ide/test_data/highlight_extern_crate.html40
-rw-r--r--crates/ra_ide_db/src/defs.rs90
-rw-r--r--crates/ra_ide_db/src/imports_locator.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs2
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs2
-rw-r--r--crates/rust-analyzer/src/main_loop.rs10
16 files changed, 243 insertions, 64 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_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 54d5678d1..0de6fdf3f 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -257,7 +257,7 @@ pub use prelude::*;
257 .find(|dep| &dep.name.to_string() == std_crate)? 257 .find(|dep| &dep.name.to_string() == std_crate)?
258 .krate; 258 .krate;
259 259
260 let mut module = std_crate.root_module(db)?; 260 let mut module = std_crate.root_module(db);
261 for segment in path { 261 for segment in path {
262 module = module.children(db).find_map(|child| { 262 module = module.children(db).find_map(|child| {
263 let name = child.name(db)?; 263 let name = child.name(db)?;
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 27cdabea0..44456e49e 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -83,9 +83,9 @@ impl Crate {
83 .collect() 83 .collect()
84 } 84 }
85 85
86 pub fn root_module(self, db: &dyn HirDatabase) -> Option<Module> { 86 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
87 let module_id = db.crate_def_map(self.id).root; 87 let module_id = db.crate_def_map(self.id).root;
88 Some(Module::new(self, module_id)) 88 Module::new(self, module_id)
89 } 89 }
90 90
91 pub fn root_file(self, db: &dyn HirDatabase) -> FileId { 91 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
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};
11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; 11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, name::AsName, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use 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};
30use resolver::TypeNs; 30use 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..010c34705 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
50impl ShortLabel for ast::SourceFile {
51 fn short_label(&self) -> Option<String> {
52 None
53 }
54}
55
50impl ShortLabel for ast::TypeAlias { 56impl 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 ")
@@ -55,7 +61,11 @@ impl ShortLabel for ast::TypeAlias {
55 61
56impl ShortLabel for ast::Const { 62impl ShortLabel for ast::Const {
57 fn short_label(&self) -> Option<String> { 63 fn short_label(&self) -> Option<String> {
58 short_label_from_ty(self, self.ty(), "const ") 64 let mut new_buf = short_label_from_ty(self, self.ty(), "const ")?;
65 if let Some(expr) = self.body() {
66 format_to!(new_buf, " = {}", expr.syntax());
67 }
68 Some(new_buf)
59 } 69 }
60} 70}
61 71
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index 4e3f428fa..45389fd23 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -1,6 +1,6 @@
1use hir::Semantics; 1use hir::Semantics;
2use ra_ide_db::{ 2use 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};
6use ra_syntax::{ 6use 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 },
@@ -86,8 +83,7 @@ pub(crate) fn reference_definition(
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 {
89 let def = def.definition(); 86 let def = def.definition(sema.db);
90
91 return match def.try_to_nav(sema.db) { 87 return match def.try_to_nav(sema.db) {
92 Some(nav) => ReferenceResult::Exact(nav), 88 Some(nav) => ReferenceResult::Exact(nav),
93 None => ReferenceResult::Approximate(Vec::new()), 89 None => ReferenceResult::Approximate(Vec::new()),
@@ -134,6 +130,32 @@ mod tests {
134 } 130 }
135 131
136 #[test] 132 #[test]
133 fn goto_def_for_extern_crate() {
134 check(
135 r#"
136 //- /main.rs
137 extern crate std<|>;
138 //- /std/lib.rs
139 // empty
140 //^ file
141 "#,
142 )
143 }
144
145 #[test]
146 fn goto_def_for_renamed_extern_crate() {
147 check(
148 r#"
149 //- /main.rs
150 extern crate std as abc<|>;
151 //- /std/lib.rs
152 // empty
153 //^ file
154 "#,
155 )
156 }
157
158 #[test]
137 fn goto_def_in_items() { 159 fn goto_def_in_items() {
138 check( 160 check(
139 r#" 161 r#"
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 385e3e64e..f66f62bfb 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).map(|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).map(|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),
@@ -587,16 +590,16 @@ fn main() {
587 #[test] 590 #[test]
588 fn hover_const_static() { 591 fn hover_const_static() {
589 check( 592 check(
590 r#"const foo<|>: u32 = 0;"#, 593 r#"const foo<|>: u32 = 123;"#,
591 expect![[r#" 594 expect![[r#"
592 *foo* 595 *foo*
593 ```rust 596 ```rust
594 const foo: u32 597 const foo: u32 = 123
595 ``` 598 ```
596 "#]], 599 "#]],
597 ); 600 );
598 check( 601 check(
599 r#"static foo<|>: u32 = 0;"#, 602 r#"static foo<|>: u32 = 456;"#,
600 expect![[r#" 603 expect![[r#"
601 *foo* 604 *foo*
602 ```rust 605 ```rust
@@ -831,7 +834,7 @@ fn main() {
831 expect![[r#" 834 expect![[r#"
832 *C* 835 *C*
833 ```rust 836 ```rust
834 const C: u32 837 const C: u32 = 1
835 ``` 838 ```
836 "#]], 839 "#]],
837 ) 840 )
@@ -1138,6 +1141,46 @@ fn bar() { fo<|>o(); }
1138 } 1141 }
1139 1142
1140 #[test] 1143 #[test]
1144 fn test_hover_extern_crate() {
1145 check(
1146 r#"
1147//- /main.rs
1148extern crate st<|>d;
1149//- /std/lib.rs
1150//! Standard library for this test
1151//!
1152//! Printed?
1153//! abc123
1154 "#,
1155 expect![[r#"
1156 *std*
1157 Standard library for this test
1158
1159 Printed?
1160 abc123
1161 "#]],
1162 );
1163 check(
1164 r#"
1165//- /main.rs
1166extern crate std as ab<|>c;
1167//- /std/lib.rs
1168//! Standard library for this test
1169//!
1170//! Printed?
1171//! abc123
1172 "#,
1173 expect![[r#"
1174 *abc*
1175 Standard library for this test
1176
1177 Printed?
1178 abc123
1179 "#]],
1180 );
1181 }
1182
1183 #[test]
1141 fn test_hover_mod_with_same_name_as_function() { 1184 fn test_hover_mod_with_same_name_as_function() {
1142 check( 1185 check(
1143 r#" 1186 r#"
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index cf456630a..453985de3 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 f71b804fe..6b7874460 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -495,6 +495,7 @@ fn highlight_element(
495 }; 495 };
496 496
497 match name_kind { 497 match name_kind {
498 Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(),
498 Some(NameClass::Definition(def)) => { 499 Some(NameClass::Definition(def)) => {
499 highlight_name(db, def, false) | HighlightModifier::Definition 500 highlight_name(db, def, false) | HighlightModifier::Definition
500 } 501 }
@@ -522,6 +523,7 @@ fn highlight_element(
522 let possibly_unsafe = is_possibly_unsafe(&name_ref); 523 let possibly_unsafe = is_possibly_unsafe(&name_ref);
523 match classify_name_ref(sema, &name_ref) { 524 match classify_name_ref(sema, &name_ref) {
524 Some(name_kind) => match name_kind { 525 Some(name_kind) => match name_kind {
526 NameRefClass::ExternCrate(_) => HighlightTag::Module.into(),
525 NameRefClass::Definition(def) => { 527 NameRefClass::Definition(def) => {
526 if let Definition::Local(local) = &def { 528 if let Definition::Local(local) = &def {
527 if let Some(name) = local.name(db) { 529 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 730efff0d..09062c38e 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -391,6 +391,23 @@ macro_rules! noop {
391 ); 391 );
392} 392}
393 393
394#[test]
395fn test_extern_crate() {
396 check_highlighting(
397 r#"
398 //- /main.rs
399 extern crate std;
400 extern crate alloc as abc;
401 //- /std/lib.rs
402 pub struct S;
403 //- /alloc/lib.rs
404 pub struct A
405 "#,
406 expect_file!["crates/ra_ide/test_data/highlight_extern_crate.html"],
407 false,
408 );
409}
410
394/// Highlights the code given by the `ra_fixture` argument, renders the 411/// Highlights the code given by the `ra_fixture` argument, renders the
395/// result as HTML, and compares it with the HTML file given as `snapshot`. 412/// result as HTML, and compares it with the HTML file given as `snapshot`.
396/// Note that the `snapshot` file is overwritten by the rendered HTML. 413/// 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>
3body { margin: 0; }
4pre { 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..9bb95277d 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
8use hir::{ 8use 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};
12use ra_prof::profile; 12use ra_prof::profile;
13use ra_syntax::{ 13use ra_syntax::{
@@ -80,6 +80,7 @@ impl Definition {
80 80
81#[derive(Debug)] 81#[derive(Debug)]
82pub enum NameClass { 82pub 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,16 +91,18 @@ pub enum NameClass {
90} 91}
91 92
92impl NameClass { 93impl 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) -> Definition {
102 match self { 104 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 }
@@ -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,13 +228,15 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option
220 228
221#[derive(Debug)] 229#[derive(Debug)]
222pub enum NameRefClass { 230pub 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
227impl NameRefClass { 236impl NameRefClass {
228 pub fn definition(self) -> Definition { 237 pub fn definition(self, db: &dyn HirDatabase) -> Definition {
229 match self { 238 match self {
239 NameRefClass::ExternCrate(krate) => Definition::ModuleDef(krate.root_module(db).into()),
230 NameRefClass::Definition(def) => def, 240 NameRefClass::Definition(def) => def,
231 NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local), 241 NameRefClass::FieldShorthand { local, field: _ } => Definition::Local(local),
232 } 242 }
@@ -307,9 +317,15 @@ pub fn classify_name_ref(
307 } 317 }
308 } 318 }
309 319
310 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 320 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
311 let resolved = sema.resolve_path(&path)?; 321 if let Some(resolved) = sema.resolve_path(&path) {
312 Some(NameRefClass::Definition(resolved.into())) 322 return Some(NameRefClass::Definition(resolved.into()));
323 }
324 }
325
326 let extern_crate = ast::ExternCrate::cast(parent)?;
327 let resolved = sema.resolve_extern_crate(&extern_crate)?;
328 Some(NameRefClass::ExternCrate(resolved))
313} 329}
314 330
315impl From<PathResolution> for Definition { 331impl 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}
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 721d41a58..0d386841e 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -72,7 +72,7 @@ impl AnalysisStatsCmd {
72 shuffle(&mut rng, &mut krates); 72 shuffle(&mut rng, &mut krates);
73 } 73 }
74 for krate in krates { 74 for krate in krates {
75 let module = krate.root_module(db).expect("crate without root module"); 75 let module = krate.root_module(db);
76 let file_id = module.definition_source(db).file_id; 76 let file_id = module.definition_source(db).file_id;
77 let file_id = file_id.original_file(db); 77 let file_id = file_id.original_file(db);
78 let source_root = db.file_source_root(file_id); 78 let source_root = db.file_source_root(file_id);
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 4ac8c8772..f17fc5dfe 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -28,7 +28,7 @@ pub fn diagnostics(
28 let mut work = Vec::new(); 28 let mut work = Vec::new();
29 let krates = Crate::all(db); 29 let krates = Crate::all(db);
30 for krate in krates { 30 for krate in krates {
31 let module = krate.root_module(db).expect("crate without root module"); 31 let module = krate.root_module(db);
32 let file_id = module.definition_source(db).file_id; 32 let file_id = module.definition_source(db).file_id;
33 let file_id = file_id.original_file(db); 33 let file_id = file_id.original_file(db);
34 let source_root = db.file_source_root(file_id); 34 let source_root = db.file_source_root(file_id);
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 438e965e0..0ac6434dd 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -337,6 +337,16 @@ impl GlobalState {
337 fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { 337 fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> {
338 self.register_request(&req, request_received); 338 self.register_request(&req, request_received);
339 339
340 if self.status == Status::Loading && req.method != "shutdown" {
341 self.respond(lsp_server::Response::new_err(
342 req.id,
343 // FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion)
344 lsp_server::ErrorCode::ContentModified as i32,
345 "Rust Analyzer is still loading...".to_owned(),
346 ));
347 return Ok(());
348 }
349
340 RequestDispatcher { req: Some(req), global_state: self } 350 RequestDispatcher { req: Some(req), global_state: self }
341 .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))? 351 .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))?
342 .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? 352 .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))?