From 2b3baa85032f86b9b50416f1a91e20cf1695d8de Mon Sep 17 00:00:00 2001 From: lhvy Date: Thu, 30 Sep 2021 23:40:17 +1000 Subject: [PATCH] Give defaultLibrary semantic token modifier to items from standard library --- .../ide/src/syntax_highlighting/highlight.rs | 44 ++++++++++++----- crates/ide/src/syntax_highlighting/tags.rs | 16 +++--- .../test_data/highlight_assoc_functions.html | 8 +-- .../test_data/highlight_default_library.html | 49 +++++++++++++++++++ .../test_data/highlight_doctest.html | 4 +- .../test_data/highlight_extern_crate.html | 4 +- .../test_data/highlighting.html | 8 +-- crates/ide/src/syntax_highlighting/tests.rs | 17 +++++++ crates/ide_db/src/helpers/famous_defs.rs | 24 +++++++++ crates/rust-analyzer/src/semantic_tokens.rs | 19 +++---- crates/rust-analyzer/src/to_proto.rs | 23 ++++----- 11 files changed, 167 insertions(+), 49 deletions(-) create mode 100644 crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index dba0636930..ef6d51f721 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -3,7 +3,7 @@ use hir::{AsAssocItem, HasVisibility, Semantics}; use ide_db::{ defs::{Definition, NameClass, NameRefClass}, - helpers::try_resolve_derive_input_at, + helpers::{try_resolve_derive_input_at, FamousDefs}, RootDatabase, SymbolKind, }; use rustc_hash::FxHashMap; @@ -25,7 +25,6 @@ pub(super) fn element( syntactic_name_ref_highlighting: bool, element: SyntaxElement, ) -> Option<(Highlight, Option)> { - let db = sema.db; let mut binding_hash = None; let highlight: Highlight = match element.kind() { FN => { @@ -79,10 +78,10 @@ pub(super) fn element( match NameClass::classify_lifetime(sema, &lifetime) { Some(NameClass::Definition(def)) => { - highlight_def(db, krate, def) | HlMod::Definition + highlight_def(sema, krate, def) | HlMod::Definition } None => match NameRefClass::classify_lifetime(sema, &lifetime) { - Some(NameRefClass::Definition(def)) => highlight_def(db, krate, def), + Some(NameRefClass::Definition(def)) => highlight_def(sema, krate, def), _ => SymbolKind::LifetimeParam.into(), }, _ => Highlight::from(SymbolKind::LifetimeParam) | HlMod::Definition, @@ -93,7 +92,7 @@ pub(super) fn element( element.ancestors().nth(2).and_then(ast::Attr::cast).zip(element.as_token()) { match try_resolve_derive_input_at(sema, &attr, token) { - Some(makro) => highlight_def(sema.db, krate, Definition::Macro(makro)), + Some(makro) => highlight_def(sema, krate, Definition::Macro(makro)), None => HlTag::None.into(), } } else { @@ -275,7 +274,7 @@ fn highlight_name_ref( } }; - let mut h = highlight_def(db, krate, def); + let mut h = highlight_def(sema, krate, def); match def { Definition::Local(local) @@ -334,7 +333,7 @@ fn highlight_name( }; match name_kind { Some(NameClass::Definition(def)) => { - let mut h = highlight_def(db, krate, def) | HlMod::Definition; + let mut h = highlight_def(sema, krate, def) | HlMod::Definition; if let Definition::ModuleDef(hir::ModuleDef::Trait(trait_)) = &def { if trait_.is_unsafe(db) { h |= HlMod::Unsafe; @@ -342,7 +341,7 @@ fn highlight_name( } h } - Some(NameClass::ConstReference(def)) => highlight_def(db, krate, def), + Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def), Some(NameClass::PatFieldShorthand { field_ref, .. }) => { let mut h = HlTag::Symbol(SymbolKind::Field).into(); if let hir::VariantDef::Union(_) = field_ref.parent_def(db) { @@ -366,7 +365,12 @@ fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 { hash((name, shadow_count)) } -fn highlight_def(db: &RootDatabase, krate: Option, def: Definition) -> Highlight { +fn highlight_def( + sema: &Semantics, + krate: Option, + def: Definition, +) -> Highlight { + let db = sema.db; let mut h = match def { Definition::Macro(_) => Highlight::new(HlTag::Symbol(SymbolKind::Macro)), Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)), @@ -504,7 +508,14 @@ fn highlight_def(db: &RootDatabase, krate: Option, def: Definition) Definition::Label(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)), }; - let is_from_other_crate = def.module(db).map(hir::Module::krate) != krate; + let famous_defs = FamousDefs(&sema, krate); + let def_crate = def.module(db).map(hir::Module::krate).or_else(|| match def { + Definition::ModuleDef(hir::ModuleDef::Module(module)) => Some(module.krate()), + _ => None, + }); + let is_from_other_crate = def_crate != krate; + let is_from_builtin_crate = + def_crate.map_or(false, |it| famous_defs.builtin_crates().contains(&it)); let is_builtin_type = matches!(def, Definition::ModuleDef(hir::ModuleDef::BuiltinType(_))); let is_public = def.visibility(db) == Some(hir::Visibility::Public); @@ -514,6 +525,10 @@ fn highlight_def(db: &RootDatabase, krate: Option, def: Definition) _ => {} } + if is_from_builtin_crate { + h |= HlMod::DefaultLibrary; + } + h } @@ -546,7 +561,10 @@ fn highlight_method_call( h |= HlMod::Trait; } - let is_from_other_crate = Some(func.module(sema.db).krate()) != krate; + let famous_defs = FamousDefs(&sema, krate); + let def_crate = func.module(sema.db).krate(); + let is_from_other_crate = Some(def_crate) != krate; + let is_from_builtin_crate = famous_defs.builtin_crates().contains(&def_crate); let is_public = func.visibility(sema.db) == hir::Visibility::Public; if is_from_other_crate { @@ -555,6 +573,10 @@ fn highlight_method_call( h |= HlMod::Public; } + if is_from_builtin_crate { + h |= HlMod::DefaultLibrary; + } + if let Some(self_param) = func.self_param(sema.db) { match self_param.access(sema.db) { hir::Access::Shared => h |= HlMod::Reference, diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index dc5dfec116..0f9a99efac 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -55,6 +55,8 @@ pub enum HlMod { Consuming, /// Used with keywords like `if` and `break`. ControlFlow, + /// Used for items from built-in crates (std, core, alloc, test and proc_macro). + DefaultLibrary, /// `foo` in `fn foo(x: i32)` is a definition, `foo` in `foo(90 + 2)` is /// not. Definition, @@ -187,42 +189,44 @@ impl fmt::Display for HlTag { impl HlMod { const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[ HlMod::Associated, + HlMod::Async, HlMod::Attribute, HlMod::Callable, HlMod::Consuming, HlMod::ControlFlow, + HlMod::DefaultLibrary, HlMod::Definition, HlMod::Documentation, HlMod::Injected, HlMod::IntraDocLink, + HlMod::Library, HlMod::Mutable, + HlMod::Public, HlMod::Reference, HlMod::Static, HlMod::Trait, - HlMod::Async, - HlMod::Library, - HlMod::Public, HlMod::Unsafe, ]; fn as_str(self) -> &'static str { match self { HlMod::Associated => "associated", + HlMod::Async => "async", HlMod::Attribute => "attribute", HlMod::Callable => "callable", HlMod::Consuming => "consuming", HlMod::ControlFlow => "control", + HlMod::DefaultLibrary => "default_library", HlMod::Definition => "declaration", HlMod::Documentation => "documentation", HlMod::Injected => "injected", HlMod::IntraDocLink => "intra_doc_link", + HlMod::Library => "library", HlMod::Mutable => "mutable", + HlMod::Public => "public", HlMod::Reference => "reference", HlMod::Static => "static", HlMod::Trait => "trait", - HlMod::Async => "async", - HlMod::Library => "library", - HlMod::Public => "public", HlMod::Unsafe => "unsafe", } } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 0d0c21cb0c..bf3f1616ac 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html @@ -45,8 +45,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd struct foo {} impl foo { - pub fn is_static() {} - pub fn is_not_static(&self) {} + pub fn is_static() {} + pub fn is_not_static(&self) {} } trait t { @@ -55,7 +55,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd } impl t for foo { - pub fn is_static() {} - pub fn is_not_static(&self) {} + pub fn is_static() {} + pub fn is_not_static(&self) {} } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html new file mode 100644 index 0000000000..33d3196cdb --- /dev/null +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html @@ -0,0 +1,49 @@ + + +
use core::iter;
+
+fn main() {
+    let foo = Some(92);
+    let nums = iter::repeat(foo.unwrap());
+}
+
\ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index f54af2d92e..d9e1a05a03 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -75,7 +75,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// # #![allow(unused_mut)] /// let mut foo: Foo = Foo::new(); /// ``` - pub const fn new() -> Foo { + pub const fn new() -> Foo { Foo { bar: true } } @@ -109,7 +109,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// ```sh /// echo 1 /// ``` - pub fn foo(&self) -> bool { + pub fn foo(&self) -> bool { true } } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index 9c01832e75..92cfa0d0a8 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html @@ -40,6 +40,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } -
extern crate std;
-extern crate alloc as abc;
+
extern crate std;
+extern crate alloc as abc;
 
\ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 16760c24de..7918a96275 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -241,12 +241,12 @@ proc_macros::mirror! { } } -async fn learn_and_sing() { - let song = learn_song().await; - sing_song(song).await; +async fn learn_and_sing() { + let song = learn_song().await; + sing_song(song).await; } -async fn async_main() { +async fn async_main() { let f1 = learn_and_sing(); let f2 = dance(); futures::join!(f1, f2); diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 9fc730e007..1f1e517777 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -734,6 +734,23 @@ fn test_extern_crate() { ); } +#[test] +fn test_default_library() { + check_highlighting( + r#" + //- minicore: option, iterators + use core::iter; + + fn main() { + let foo = Some(92); + let nums = iter::repeat(foo.unwrap()); + } + "#, + expect_file!["./test_data/highlight_default_library.html"], + false, + ); +} + #[test] fn test_associated_function() { check_highlighting( diff --git a/crates/ide_db/src/helpers/famous_defs.rs b/crates/ide_db/src/helpers/famous_defs.rs index 7c59bc28d7..65992f8b4f 100644 --- a/crates/ide_db/src/helpers/famous_defs.rs +++ b/crates/ide_db/src/helpers/famous_defs.rs @@ -68,6 +68,30 @@ impl FamousDefs<'_, '_> { self.find_trait("core:ops:Deref") } + pub fn alloc(&self) -> Option { + self.find_crate("alloc") + } + + pub fn test(&self) -> Option { + self.find_crate("test") + } + + pub fn proc_macro(&self) -> Option { + self.find_crate("proc_macro") + } + + pub fn builtin_crates(&self) -> Vec { + IntoIterator::into_iter([ + self.std(), + self.core(), + self.alloc(), + self.test(), + self.proc_macro(), + ]) + .filter_map(|it| it) + .collect() + } + fn find_trait(&self, path: &str) -> Option { match self.find_def(path)? { hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it), diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index f2ed98f2a4..ad2b3b93e3 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs @@ -87,20 +87,21 @@ macro_rules! define_semantic_token_modifiers { } define_semantic_token_modifiers![ - (CONSTANT, "constant"), - (CONTROL_FLOW, "controlFlow"), - (INJECTED, "injected"), - (MUTABLE, "mutable"), - (CONSUMING, "consuming"), (ASYNC, "async"), - (LIBRARY, "library"), - (PUBLIC, "public"), - (UNSAFE, "unsafe"), (ATTRIBUTE_MODIFIER, "attribute"), - (TRAIT_MODIFIER, "trait"), (CALLABLE, "callable"), + (CONSTANT, "constant"), + (CONSUMING, "consuming"), + (CONTROL_FLOW, "controlFlow"), + (DEFAULT_LIBRARY, "defaultLibrary"), + (INJECTED, "injected"), (INTRA_DOC_LINK, "intraDocLink"), + (LIBRARY, "library"), + (MUTABLE, "mutable"), + (PUBLIC, "public"), (REFERENCE, "reference"), + (TRAIT_MODIFIER, "trait"), + (UNSAFE, "unsafe"), ]; #[derive(Default)] diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 277476981f..834990de55 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -529,23 +529,24 @@ fn semantic_token_type_and_modifiers( for modifier in highlight.mods.iter() { let modifier = match modifier { + HlMod::Associated => continue, + HlMod::Async => semantic_tokens::ASYNC, HlMod::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER, + HlMod::Callable => semantic_tokens::CALLABLE, + HlMod::Consuming => semantic_tokens::CONSUMING, + HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW, + HlMod::DefaultLibrary => semantic_tokens::DEFAULT_LIBRARY, HlMod::Definition => lsp_types::SemanticTokenModifier::DECLARATION, HlMod::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION, HlMod::Injected => semantic_tokens::INJECTED, - HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW, - HlMod::Mutable => semantic_tokens::MUTABLE, - HlMod::Reference => semantic_tokens::REFERENCE, - HlMod::Consuming => semantic_tokens::CONSUMING, - HlMod::Async => semantic_tokens::ASYNC, - HlMod::Library => semantic_tokens::LIBRARY, - HlMod::Public => semantic_tokens::PUBLIC, - HlMod::Unsafe => semantic_tokens::UNSAFE, - HlMod::Callable => semantic_tokens::CALLABLE, - HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK, + HlMod::Library => semantic_tokens::LIBRARY, + HlMod::Mutable => semantic_tokens::MUTABLE, + HlMod::Public => semantic_tokens::PUBLIC, + HlMod::Reference => semantic_tokens::REFERENCE, + HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, HlMod::Trait => semantic_tokens::TRAIT_MODIFIER, - HlMod::Associated => continue, + HlMod::Unsafe => semantic_tokens::UNSAFE, }; mods |= modifier; }