]> git.lizzy.rs Git - rust.git/commitdiff
More type safety for highlighting
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 26 Feb 2020 16:08:15 +0000 (17:08 +0100)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 26 Feb 2020 16:17:15 +0000 (17:17 +0100)
crates/ra_ide/src/lib.rs
crates/ra_ide/src/syntax_highlighting.rs
crates/ra_ide/src/syntax_highlighting/highlight_tag.rs [new file with mode: 0644]
crates/rust-analyzer/src/conv.rs
crates/rust-analyzer/src/main_loop/handlers.rs
crates/rust-analyzer/src/req.rs

index f31d3c29557091e863482c427aeb964248812ba4..d74d32453480f09e49500b7c59d087478d9241c3 100644 (file)
@@ -74,7 +74,7 @@
     runnables::{Runnable, RunnableKind, TestId},
     source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
     ssr::SsrError,
-    syntax_highlighting::{tags, HighlightedRange},
+    syntax_highlighting::{HighlightTag, HighlightedRange},
 };
 
 pub use hir::Documentation;
index 987476d2c97b1d1936f197a16ce40076cf1034bc..d422930bfa389965d18999685db8c0533ec4c48d 100644 (file)
@@ -1,5 +1,7 @@
 //! FIXME: write short doc here
 
+mod highlight_tag;
+
 use hir::{Name, Semantics};
 use ra_db::SourceDatabase;
 use ra_ide_db::{
 
 use crate::{references::classify_name_ref, FileId};
 
-pub mod tags {
-    pub const FIELD: &str = "field";
-    pub const FUNCTION: &str = "function";
-    pub const MODULE: &str = "module";
-    pub const CONSTANT: &str = "constant";
-    pub const MACRO: &str = "macro";
-
-    pub const VARIABLE: &str = "variable";
-    pub const VARIABLE_MUT: &str = "variable.mut";
-
-    pub const TYPE: &str = "type";
-    pub const TYPE_BUILTIN: &str = "type.builtin";
-    pub const TYPE_SELF: &str = "type.self";
-    pub const TYPE_PARAM: &str = "type.param";
-    pub const TYPE_LIFETIME: &str = "type.lifetime";
-
-    pub const LITERAL_BYTE: &str = "literal.byte";
-    pub const LITERAL_NUMERIC: &str = "literal.numeric";
-    pub const LITERAL_CHAR: &str = "literal.char";
-
-    pub const LITERAL_COMMENT: &str = "comment";
-    pub const LITERAL_STRING: &str = "string";
-    pub const LITERAL_ATTRIBUTE: &str = "attribute";
-
-    pub const KEYWORD: &str = "keyword";
-    pub const KEYWORD_UNSAFE: &str = "keyword.unsafe";
-    pub const KEYWORD_CONTROL: &str = "keyword.control";
-}
+pub use highlight_tag::HighlightTag;
 
 #[derive(Debug)]
 pub struct HighlightedRange {
     pub range: TextRange,
-    pub tag: &'static str,
+    pub tag: HighlightTag,
     pub binding_hash: Option<u64>,
 }
 
@@ -104,7 +79,7 @@ pub(crate) fn highlight(
                         if let Some(range) = highlight_macro(node) {
                             res.push(HighlightedRange {
                                 range,
-                                tag: tags::MACRO,
+                                tag: HighlightTag::MACRO,
                                 binding_hash: None,
                             });
                         }
@@ -175,7 +150,7 @@ fn highlight_token_tree(
     sema: &Semantics<RootDatabase>,
     bindings_shadow_count: &mut FxHashMap<Name, u32>,
     token: SyntaxToken,
-) -> Option<(&'static str, Option<u64>)> {
+) -> Option<(HighlightTag, Option<u64>)> {
     if token.parent().kind() != TOKEN_TREE {
         return None;
     }
@@ -196,7 +171,7 @@ fn highlight_node(
     sema: &Semantics<RootDatabase>,
     bindings_shadow_count: &mut FxHashMap<Name, u32>,
     node: SyntaxElement,
-) -> Option<(&'static str, Option<u64>)> {
+) -> Option<(HighlightTag, Option<u64>)> {
     let db = sema.db;
     let mut binding_hash = None;
     let tag = match node.kind() {
@@ -204,11 +179,11 @@ fn highlight_node(
             bindings_shadow_count.clear();
             return None;
         }
-        COMMENT => tags::LITERAL_COMMENT,
-        STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING,
-        ATTR => tags::LITERAL_ATTRIBUTE,
+        COMMENT => HighlightTag::LITERAL_COMMENT,
+        STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HighlightTag::LITERAL_STRING,
+        ATTR => HighlightTag::LITERAL_ATTRIBUTE,
         // Special-case field init shorthand
-        NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => tags::FIELD,
+        NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => HighlightTag::FIELD,
         NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => return None,
         NAME_REF => {
             let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap();
@@ -242,21 +217,21 @@ fn highlight_node(
 
             match name_kind {
                 Some(name_kind) => highlight_name(db, name_kind),
-                None => name.syntax().parent().map_or(tags::FUNCTION, |x| match x.kind() {
-                    STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => tags::TYPE,
-                    TYPE_PARAM => tags::TYPE_PARAM,
-                    RECORD_FIELD_DEF => tags::FIELD,
-                    _ => tags::FUNCTION,
+                None => name.syntax().parent().map_or(HighlightTag::FUNCTION, |x| match x.kind() {
+                    STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => HighlightTag::TYPE,
+                    TYPE_PARAM => HighlightTag::TYPE_PARAM,
+                    RECORD_FIELD_DEF => HighlightTag::FIELD,
+                    _ => HighlightTag::FUNCTION,
                 }),
             }
         }
-        INT_NUMBER | FLOAT_NUMBER => tags::LITERAL_NUMERIC,
-        BYTE => tags::LITERAL_BYTE,
-        CHAR => tags::LITERAL_CHAR,
-        LIFETIME => tags::TYPE_LIFETIME,
-        T![unsafe] => tags::KEYWORD_UNSAFE,
-        k if is_control_keyword(k) => tags::KEYWORD_CONTROL,
-        k if k.is_keyword() => tags::KEYWORD,
+        INT_NUMBER | FLOAT_NUMBER => HighlightTag::LITERAL_NUMERIC,
+        BYTE => HighlightTag::LITERAL_BYTE,
+        CHAR => HighlightTag::LITERAL_CHAR,
+        LIFETIME => HighlightTag::TYPE_LIFETIME,
+        T![unsafe] => HighlightTag::KEYWORD_UNSAFE,
+        k if is_control_keyword(k) => HighlightTag::KEYWORD_CONTROL,
+        k if k.is_keyword() => HighlightTag::KEYWORD,
 
         _ => return None,
     };
@@ -318,7 +293,7 @@ fn rainbowify(seed: u64) -> String {
         if ranges.is_empty() {
             buf.push_str(&text);
         } else {
-            let classes = ranges.iter().map(|x| x.tag).collect::<Vec<_>>().join(" ");
+            let classes = ranges.iter().map(|x| x.tag.to_string()).collect::<Vec<_>>().join(" ");
             let binding_hash = ranges.first().and_then(|x| x.binding_hash);
             let color = match (rainbow, binding_hash) {
                 (true, Some(hash)) => format!(
@@ -335,26 +310,26 @@ fn rainbowify(seed: u64) -> String {
     buf
 }
 
-fn highlight_name(db: &RootDatabase, def: NameDefinition) -> &'static str {
+fn highlight_name(db: &RootDatabase, def: NameDefinition) -> HighlightTag {
     match def {
-        NameDefinition::Macro(_) => tags::MACRO,
-        NameDefinition::StructField(_) => tags::FIELD,
-        NameDefinition::ModuleDef(hir::ModuleDef::Module(_)) => tags::MODULE,
-        NameDefinition::ModuleDef(hir::ModuleDef::Function(_)) => tags::FUNCTION,
-        NameDefinition::ModuleDef(hir::ModuleDef::Adt(_)) => tags::TYPE,
-        NameDefinition::ModuleDef(hir::ModuleDef::EnumVariant(_)) => tags::CONSTANT,
-        NameDefinition::ModuleDef(hir::ModuleDef::Const(_)) => tags::CONSTANT,
-        NameDefinition::ModuleDef(hir::ModuleDef::Static(_)) => tags::CONSTANT,
-        NameDefinition::ModuleDef(hir::ModuleDef::Trait(_)) => tags::TYPE,
-        NameDefinition::ModuleDef(hir::ModuleDef::TypeAlias(_)) => tags::TYPE,
-        NameDefinition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => tags::TYPE_BUILTIN,
-        NameDefinition::SelfType(_) => tags::TYPE_SELF,
-        NameDefinition::TypeParam(_) => tags::TYPE_PARAM,
+        NameDefinition::Macro(_) => HighlightTag::MACRO,
+        NameDefinition::StructField(_) => HighlightTag::FIELD,
+        NameDefinition::ModuleDef(hir::ModuleDef::Module(_)) => HighlightTag::MODULE,
+        NameDefinition::ModuleDef(hir::ModuleDef::Function(_)) => HighlightTag::FUNCTION,
+        NameDefinition::ModuleDef(hir::ModuleDef::Adt(_)) => HighlightTag::TYPE,
+        NameDefinition::ModuleDef(hir::ModuleDef::EnumVariant(_)) => HighlightTag::CONSTANT,
+        NameDefinition::ModuleDef(hir::ModuleDef::Const(_)) => HighlightTag::CONSTANT,
+        NameDefinition::ModuleDef(hir::ModuleDef::Static(_)) => HighlightTag::CONSTANT,
+        NameDefinition::ModuleDef(hir::ModuleDef::Trait(_)) => HighlightTag::TYPE,
+        NameDefinition::ModuleDef(hir::ModuleDef::TypeAlias(_)) => HighlightTag::TYPE,
+        NameDefinition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => HighlightTag::TYPE_BUILTIN,
+        NameDefinition::SelfType(_) => HighlightTag::TYPE_SELF,
+        NameDefinition::TypeParam(_) => HighlightTag::TYPE_PARAM,
         NameDefinition::Local(local) => {
             if local.is_mut(db) || local.ty(db).is_mutable_reference() {
-                tags::VARIABLE_MUT
+                HighlightTag::VARIABLE_MUT
             } else {
-                tags::VARIABLE
+                HighlightTag::VARIABLE
             }
         }
     }
@@ -523,6 +498,6 @@ struct Foo {
             })
             .unwrap();
 
-        assert_eq!(highlights[0].tag, "field");
+        assert_eq!(&highlights[0].tag.to_string(), "field");
     }
 }
diff --git a/crates/ra_ide/src/syntax_highlighting/highlight_tag.rs b/crates/ra_ide/src/syntax_highlighting/highlight_tag.rs
new file mode 100644 (file)
index 0000000..af1ac07
--- /dev/null
@@ -0,0 +1,43 @@
+//! Defines token tags we use for syntax highlighting.
+//! A tag is not unlike a CSS class.
+
+use std::fmt;
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct HighlightTag(&'static str);
+
+impl fmt::Display for HighlightTag {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.0, f)
+    }
+}
+
+#[rustfmt::skip]
+impl HighlightTag {
+    pub const FIELD: HighlightTag              = HighlightTag("field");
+    pub const FUNCTION: HighlightTag           = HighlightTag("function");
+    pub const MODULE: HighlightTag             = HighlightTag("module");
+    pub const CONSTANT: HighlightTag           = HighlightTag("constant");
+    pub const MACRO: HighlightTag              = HighlightTag("macro");
+
+    pub const VARIABLE: HighlightTag           = HighlightTag("variable");
+    pub const VARIABLE_MUT: HighlightTag       = HighlightTag("variable.mut");
+
+    pub const TYPE: HighlightTag               = HighlightTag("type");
+    pub const TYPE_BUILTIN: HighlightTag       = HighlightTag("type.builtin");
+    pub const TYPE_SELF: HighlightTag          = HighlightTag("type.self");
+    pub const TYPE_PARAM: HighlightTag         = HighlightTag("type.param");
+    pub const TYPE_LIFETIME: HighlightTag      = HighlightTag("type.lifetime");
+
+    pub const LITERAL_BYTE: HighlightTag       = HighlightTag("literal.byte");
+    pub const LITERAL_NUMERIC: HighlightTag    = HighlightTag("literal.numeric");
+    pub const LITERAL_CHAR: HighlightTag       = HighlightTag("literal.char");
+
+    pub const LITERAL_COMMENT: HighlightTag    = HighlightTag("comment");
+    pub const LITERAL_STRING: HighlightTag     = HighlightTag("string");
+    pub const LITERAL_ATTRIBUTE: HighlightTag  = HighlightTag("attribute");
+
+    pub const KEYWORD: HighlightTag            = HighlightTag("keyword");
+    pub const KEYWORD_UNSAFE: HighlightTag     = HighlightTag("keyword.unsafe");
+    pub const KEYWORD_CONTROL: HighlightTag    = HighlightTag("keyword.control");
+}
index 5fcb46b6174b2d839588f007cc8100e9a6ab386e..5e5610a1e021d5b0a7b07807861dd3caf4248fe1 100644 (file)
@@ -9,8 +9,8 @@
     WorkspaceEdit,
 };
 use ra_ide::{
-    tags, translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
-    FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex,
+    translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
+    FileRange, FileSystemEdit, Fold, FoldKind, HighlightTag, InsertTextFormat, LineCol, LineIndex,
     NavigationTarget, RangeInfo, ReferenceAccess, Severity, SourceChange, SourceFileEdit,
 };
 use ra_syntax::{SyntaxKind, TextRange, TextUnit};
@@ -303,51 +303,51 @@ fn conv_with(self, ctx: &FoldConvCtx) -> lsp_types::FoldingRange {
     }
 }
 
-impl Conv for &'static str {
+impl Conv for HighlightTag {
     type Output = (SemanticTokenType, Vec<SemanticTokenModifier>);
 
     fn conv(self) -> (SemanticTokenType, Vec<SemanticTokenModifier>) {
         let token_type: SemanticTokenType = match self {
-            tags::FIELD => SemanticTokenType::MEMBER,
-            tags::FUNCTION => SemanticTokenType::FUNCTION,
-            tags::MODULE => SemanticTokenType::NAMESPACE,
-            tags::CONSTANT => {
+            HighlightTag::FIELD => SemanticTokenType::MEMBER,
+            HighlightTag::FUNCTION => SemanticTokenType::FUNCTION,
+            HighlightTag::MODULE => SemanticTokenType::NAMESPACE,
+            HighlightTag::CONSTANT => {
                 return (
                     SemanticTokenType::VARIABLE,
                     vec![SemanticTokenModifier::STATIC, SemanticTokenModifier::READONLY],
                 )
             }
-            tags::MACRO => SemanticTokenType::MACRO,
+            HighlightTag::MACRO => SemanticTokenType::MACRO,
 
-            tags::VARIABLE => {
+            HighlightTag::VARIABLE => {
                 return (SemanticTokenType::VARIABLE, vec![SemanticTokenModifier::READONLY])
             }
-            tags::VARIABLE_MUT => SemanticTokenType::VARIABLE,
+            HighlightTag::VARIABLE_MUT => SemanticTokenType::VARIABLE,
 
-            tags::TYPE => SemanticTokenType::TYPE,
-            tags::TYPE_BUILTIN => SemanticTokenType::TYPE,
-            tags::TYPE_SELF => {
+            HighlightTag::TYPE => SemanticTokenType::TYPE,
+            HighlightTag::TYPE_BUILTIN => SemanticTokenType::TYPE,
+            HighlightTag::TYPE_SELF => {
                 return (SemanticTokenType::TYPE, vec![SemanticTokenModifier::REFERENCE])
             }
-            tags::TYPE_PARAM => SemanticTokenType::TYPE_PARAMETER,
-            tags::TYPE_LIFETIME => {
+            HighlightTag::TYPE_PARAM => SemanticTokenType::TYPE_PARAMETER,
+            HighlightTag::TYPE_LIFETIME => {
                 return (SemanticTokenType::LABEL, vec![SemanticTokenModifier::REFERENCE])
             }
 
-            tags::LITERAL_BYTE => SemanticTokenType::NUMBER,
-            tags::LITERAL_NUMERIC => SemanticTokenType::NUMBER,
-            tags::LITERAL_CHAR => SemanticTokenType::NUMBER,
+            HighlightTag::LITERAL_BYTE => SemanticTokenType::NUMBER,
+            HighlightTag::LITERAL_NUMERIC => SemanticTokenType::NUMBER,
+            HighlightTag::LITERAL_CHAR => SemanticTokenType::NUMBER,
 
-            tags::LITERAL_COMMENT => {
+            HighlightTag::LITERAL_COMMENT => {
                 return (SemanticTokenType::COMMENT, vec![SemanticTokenModifier::DOCUMENTATION])
             }
 
-            tags::LITERAL_STRING => SemanticTokenType::STRING,
-            tags::LITERAL_ATTRIBUTE => SemanticTokenType::KEYWORD,
+            HighlightTag::LITERAL_STRING => SemanticTokenType::STRING,
+            HighlightTag::LITERAL_ATTRIBUTE => SemanticTokenType::KEYWORD,
 
-            tags::KEYWORD => SemanticTokenType::KEYWORD,
-            tags::KEYWORD_UNSAFE => SemanticTokenType::KEYWORD,
-            tags::KEYWORD_CONTROL => SemanticTokenType::KEYWORD,
+            HighlightTag::KEYWORD => SemanticTokenType::KEYWORD,
+            HighlightTag::KEYWORD_UNSAFE => SemanticTokenType::KEYWORD,
+            HighlightTag::KEYWORD_CONTROL => SemanticTokenType::KEYWORD,
             unknown => panic!("Unknown semantic token: {}", unknown),
         };
 
index 267edd578a3fe428039b15990db7c1c6e51a1952..e9f1c4f4b50454b3bbe21b579c8bf6c1507d7b60 100644 (file)
@@ -954,7 +954,7 @@ fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>>
         .into_iter()
         .map(|h| Decoration {
             range: h.range.conv_with(&line_index),
-            tag: h.tag,
+            tag: h.tag.to_string(),
             binding_hash: h.binding_hash.map(|x| x.to_string()),
         })
         .collect();
index 642ac41ac4012fd4461316f2f431b526126965f3..fd6aef5971968831a6a01d171fb2ac6706536138 100644 (file)
@@ -112,7 +112,7 @@ pub struct PublishDecorationsParams {
 #[serde(rename_all = "camelCase")]
 pub struct Decoration {
     pub range: Range,
-    pub tag: &'static str,
+    pub tag: String,
     pub binding_hash: Option<String>,
 }