From 6cde0b1aa0f6b8623c6b81b2396f4a0345891233 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 8 Aug 2020 14:14:18 -0400 Subject: Add support for extern crate This adds syntax highlighting, hover and goto def functionality for extern crate --- crates/ra_ide/src/display/short_label.rs | 6 +++ crates/ra_ide/src/goto_definition.rs | 37 ++++++++++++---- crates/ra_ide/src/hover.rs | 49 ++++++++++++++++++++-- crates/ra_ide/src/references.rs | 4 +- crates/ra_ide/src/syntax_highlighting.rs | 2 + crates/ra_ide/src/syntax_highlighting/tests.rs | 17 ++++++++ .../ra_ide/test_data/highlight_extern_crate.html | 40 ++++++++++++++++++ 7 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 crates/ra_ide/test_data/highlight_extern_crate.html (limited to 'crates/ra_ide') 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 { } } +impl ShortLabel for ast::SourceFile { + fn short_label(&self) -> Option { + None + } +} + impl ShortLabel for ast::TypeAlias { fn short_label(&self) -> Option { 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 @@ use hir::Semantics; use ra_ide_db::{ - defs::{classify_name, classify_name_ref, NameClass}, + defs::{classify_name, classify_name_ref}, symbol_index, RootDatabase, }; use ra_syntax::{ @@ -40,10 +40,7 @@ pub(crate) fn goto_definition( reference_definition(&sema, &name_ref).to_vec() }, ast::Name(name) => { - let def = match classify_name(&sema, &name)? { - NameClass::Definition(def) | NameClass::ConstReference(def) => def, - NameClass::FieldShorthand { local: _, field } => field, - }; + let def = classify_name(&sema, &name)?.definition(sema.db)?; let nav = def.try_to_nav(sema.db)?; vec![nav] }, @@ -85,9 +82,7 @@ pub(crate) fn reference_definition( name_ref: &ast::NameRef, ) -> ReferenceResult { let name_kind = classify_name_ref(sema, name_ref); - if let Some(def) = name_kind { - let def = def.definition(); - + if let Some(def) = name_kind.and_then(|def| def.definition(sema.db)) { return match def.try_to_nav(sema.db) { Some(nav) => ReferenceResult::Exact(nav), None => ReferenceResult::Approximate(Vec::new()), @@ -133,6 +128,32 @@ mod tests { assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }); } + #[test] + fn goto_def_for_extern_crate() { + check( + r#" + //- /main.rs + extern crate std<|>; + //- /std/lib.rs + // empty + //^ file + "#, + ) + } + + #[test] + fn goto_def_for_renamed_extern_crate() { + check( + r#" + //- /main.rs + extern crate std as abc<|>; + //- /std/lib.rs + // empty + //^ file + "#, + ) + } + #[test] fn goto_def_in_items() { check( 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 classify_name_ref(&sema, &name_ref).map(|d| d.definition()), - ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition()), + ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).and_then(|d| d.definition(sema.db)), + ast::Name(name) => classify_name(&sema, &name).and_then(|d| d.definition(sema.db)), _ => None, } }; @@ -304,7 +304,10 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option { let docs = Documentation::from_ast(&it).map(Into::into); hover_markup(docs, it.short_label(), mod_path) } - _ => None, + ModuleSource::SourceFile(it) => { + let docs = Documentation::from_ast(&it).map(Into::into); + hover_markup(docs, it.short_label(), mod_path) + } }, ModuleDef::Function(it) => from_def_source(db, it, mod_path), ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path), @@ -1106,6 +1109,46 @@ fn bar() { fo<|>o(); } ); } + #[test] + fn test_hover_extern_crate() { + check( + r#" +//- /main.rs +extern crate st<|>d; +//- /std/lib.rs +//! Standard library for this test +//! +//! Printed? +//! abc123 + "#, + expect![[r#" + *std* + Standard library for this test + + Printed? + abc123 + "#]], + ); + check( + r#" +//- /main.rs +extern crate std as ab<|>c; +//- /std/lib.rs +//! Standard library for this test +//! +//! Printed? +//! abc123 + "#, + expect![[r#" + *abc* + Standard library for this test + + Printed? + abc123 + "#]], + ); + } + #[test] fn test_hover_mod_with_same_name_as_function() { check( 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( opt_name: Option, ) -> Option> { if let Some(name) = opt_name { - let def = classify_name(sema, &name)?.definition(); + let def = classify_name(sema, &name)?.definition(sema.db)?; let range = name.syntax().text_range(); return Some(RangeInfo::new(range, def)); } let name_ref = sema.find_node_at_offset_with_descend::(&syntax, position.offset)?; - let def = classify_name_ref(sema, &name_ref)?.definition(); + let def = classify_name_ref(sema, &name_ref)?.definition(sema.db)?; let range = name_ref.syntax().text_range(); Some(RangeInfo::new(range, def)) } 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( }; match name_kind { + Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), Some(NameClass::Definition(def)) => { highlight_name(db, def) | HighlightModifier::Definition } @@ -500,6 +501,7 @@ fn highlight_element( let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); match classify_name_ref(sema, &name_ref) { Some(name_kind) => match name_kind { + NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), NameRefClass::Definition(def) => { if let Definition::Local(local) = &def { 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 { ); } +#[test] +fn test_extern_crate() { + check_highlighting( + r#" + //- /main.rs + extern crate std; + extern crate alloc as abc; + //- /std/lib.rs + pub struct S; + //- /alloc/lib.rs + pub struct A + "#, + expect_file!["crates/ra_ide/test_data/highlight_extern_crate.html"], + false, + ); +} + /// Highlights the code given by the `ra_fixture` argument, renders the /// result as HTML, and compares it with the HTML file given as `snapshot`. /// 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 @@ + + +
extern crate std;
+extern crate alloc as abc;
+
\ No newline at end of file -- cgit v1.2.3