aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-08-08 19:14:18 +0100
committerPaul Daniel Faria <[email protected]>2020-08-08 19:14:18 +0100
commit6cde0b1aa0f6b8623c6b81b2396f4a0345891233 (patch)
tree9d558ee8eeace0aadf241c190248d008e362d17f /crates/ra_ide/src
parenta69f19a6a5899bdfb6fc498371650bf54263deff (diff)
Add support for extern crate
This adds syntax highlighting, hover and goto def functionality for extern crate
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/display/short_label.rs6
-rw-r--r--crates/ra_ide/src/goto_definition.rs37
-rw-r--r--crates/ra_ide/src/hover.rs49
-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
6 files changed, 102 insertions, 13 deletions
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
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 ")
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 @@
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 },
@@ -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
1117extern 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
1135extern 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]
384fn 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.