From 5bf3e949e8470a138a61c806769e1a329761cab6 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 23 May 2019 19:42:42 +0200 Subject: Semantic highlighting spike Very simple approach: For each identifier, set the hash of the range where it's defined as its 'id' and use it in the VSCode extension to generate unique colors. Thus, the generated colors are per-file. They are also quite fragile, and I'm not entirely sure why. Looks like we need to make sure the same ranges aren't overwritten by a later request? --- .../src/snapshots/tests__highlighting.snap | 192 +++++++++++++++++++++ .../src/snapshots/tests__sematic_highlighting.snap | 87 ++++++++++ crates/ra_ide_api/src/syntax_highlighting.rs | 101 +++++++---- crates/ra_lsp_server/src/main_loop/handlers.rs | 6 +- crates/ra_lsp_server/src/req.rs | 1 + crates/ra_syntax/src/syntax_node.rs | 4 + 6 files changed, 355 insertions(+), 36 deletions(-) create mode 100644 crates/ra_ide_api/src/snapshots/tests__highlighting.snap create mode 100644 crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap (limited to 'crates') diff --git a/crates/ra_ide_api/src/snapshots/tests__highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__highlighting.snap new file mode 100644 index 000000000..208681f10 --- /dev/null +++ b/crates/ra_ide_api/src/snapshots/tests__highlighting.snap @@ -0,0 +1,192 @@ +--- +created: "2019-05-25T10:53:54.439877Z" +creator: insta@0.8.1 +source: crates/ra_ide_api/src/syntax_highlighting.rs +expression: result +--- +Ok( + [ + HighlightedRange { + range: [1; 24), + tag: "attribute", + id: None, + }, + HighlightedRange { + range: [25; 31), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [32; 35), + tag: "variable", + id: Some( + 461893210254723387, + ), + }, + HighlightedRange { + range: [42; 45), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [46; 47), + tag: "variable", + id: Some( + 8312289520117458465, + ), + }, + HighlightedRange { + range: [49; 52), + tag: "text", + id: None, + }, + HighlightedRange { + range: [58; 61), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [62; 63), + tag: "variable", + id: Some( + 4497542318236667727, + ), + }, + HighlightedRange { + range: [65; 68), + tag: "text", + id: None, + }, + HighlightedRange { + range: [73; 75), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [76; 79), + tag: "variable", + id: Some( + 4506850079084802999, + ), + }, + HighlightedRange { + range: [80; 81), + tag: "type", + id: None, + }, + HighlightedRange { + range: [80; 81), + tag: "variable", + id: Some( + 16968185728268100018, + ), + }, + HighlightedRange { + range: [88; 89), + tag: "type", + id: None, + }, + HighlightedRange { + range: [96; 110), + tag: "macro", + id: None, + }, + HighlightedRange { + range: [117; 127), + tag: "comment", + id: None, + }, + HighlightedRange { + range: [128; 130), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [131; 135), + tag: "variable", + id: Some( + 14467718814232352107, + ), + }, + HighlightedRange { + range: [145; 153), + tag: "macro", + id: None, + }, + HighlightedRange { + range: [154; 166), + tag: "string", + id: None, + }, + HighlightedRange { + range: [168; 170), + tag: "literal", + id: None, + }, + HighlightedRange { + range: [178; 181), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [182; 185), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [186; 189), + tag: "macro", + id: None, + }, + HighlightedRange { + range: [197; 200), + tag: "macro", + id: None, + }, + HighlightedRange { + range: [192; 195), + tag: "text", + id: None, + }, + HighlightedRange { + range: [208; 211), + tag: "macro", + id: None, + }, + HighlightedRange { + range: [212; 216), + tag: "macro", + id: None, + }, + HighlightedRange { + range: [226; 227), + tag: "literal", + id: None, + }, + HighlightedRange { + range: [232; 233), + tag: "literal", + id: None, + }, + HighlightedRange { + range: [242; 248), + tag: "keyword.unsafe", + id: None, + }, + HighlightedRange { + range: [251; 254), + tag: "text", + id: None, + }, + HighlightedRange { + range: [255; 262), + tag: "text", + id: None, + }, + HighlightedRange { + range: [263; 264), + tag: "literal", + id: None, + }, + ], +) diff --git a/crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap new file mode 100644 index 000000000..3b3fe32e9 --- /dev/null +++ b/crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap @@ -0,0 +1,87 @@ +--- +created: "2019-05-25T10:25:13.898113Z" +creator: insta@0.8.1 +source: crates/ra_ide_api/src/syntax_highlighting.rs +expression: result +--- +Ok( + [ + HighlightedRange { + range: [1; 3), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [4; 8), + tag: "variable", + id: Some( + 17119830160611610240, + ), + }, + HighlightedRange { + range: [17; 20), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [21; 26), + tag: "variable", + id: Some( + 2744494144922727377, + ), + }, + HighlightedRange { + range: [29; 36), + tag: "string", + id: None, + }, + HighlightedRange { + range: [42; 45), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [46; 47), + tag: "variable", + id: Some( + 10375904121795371996, + ), + }, + HighlightedRange { + range: [50; 55), + tag: "variable", + id: Some( + 2744494144922727377, + ), + }, + HighlightedRange { + range: [56; 65), + tag: "text", + id: None, + }, + HighlightedRange { + range: [73; 76), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [77; 78), + tag: "variable", + id: Some( + 8228548264153724449, + ), + }, + HighlightedRange { + range: [81; 86), + tag: "variable", + id: Some( + 2744494144922727377, + ), + }, + HighlightedRange { + range: [87; 96), + tag: "text", + id: None, + }, + ], +) diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 87e053364..da000c0c3 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -10,6 +10,7 @@ use crate::{FileId, db::RootDatabase}; pub struct HighlightedRange { pub range: TextRange, pub tag: &'static str, + pub id: Option, } fn is_control_keyword(kind: SyntaxKind) -> bool { @@ -32,6 +33,14 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec(x: T) -> u64 { + use std::{collections::hash_map::DefaultHasher, hash::Hasher}; + + let mut hasher = DefaultHasher::new(); + x.hash(&mut hasher); + hasher.finish() + } + // Visited nodes to handle highlighting priorities let mut highlighted: FxHashSet = FxHashSet::default(); let mut res = Vec::new(); @@ -39,52 +48,59 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "comment", - STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", - ATTR => "attribute", + let (tag, id) = match node.kind() { + COMMENT => ("comment", None), + STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => ("string", None), + ATTR => ("attribute", None), NAME_REF => { - if let Some(name_ref) = node.as_node().and_then(|n| ast::NameRef::cast(n)) { + if let Some(name_ref) = node.as_ast_node::() { use crate::name_ref_kind::{classify_name_ref, NameRefKind::*}; use hir::{ModuleDef, ImplItem}; // FIXME: try to reuse the SourceAnalyzers let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); match classify_name_ref(db, &analyzer, name_ref) { - Some(Method(_)) => "function", - Some(Macro(_)) => "macro", - Some(FieldAccess(_)) => "field", - Some(AssocItem(ImplItem::Method(_))) => "function", - Some(AssocItem(ImplItem::Const(_))) => "constant", - Some(AssocItem(ImplItem::TypeAlias(_))) => "type", - Some(Def(ModuleDef::Module(_))) => "module", - Some(Def(ModuleDef::Function(_))) => "function", - Some(Def(ModuleDef::Struct(_))) => "type", - Some(Def(ModuleDef::Union(_))) => "type", - Some(Def(ModuleDef::Enum(_))) => "type", - Some(Def(ModuleDef::EnumVariant(_))) => "constant", - Some(Def(ModuleDef::Const(_))) => "constant", - Some(Def(ModuleDef::Static(_))) => "constant", - Some(Def(ModuleDef::Trait(_))) => "type", - Some(Def(ModuleDef::TypeAlias(_))) => "type", - Some(SelfType(_)) => "type", - Some(Pat(_)) => "text", - Some(SelfParam(_)) => "type", - Some(GenericParam(_)) => "type", - None => "text", + Some(Method(_)) => ("function", None), + Some(Macro(_)) => ("macro", None), + Some(FieldAccess(_)) => ("field", None), + Some(AssocItem(ImplItem::Method(_))) => ("function", None), + Some(AssocItem(ImplItem::Const(_))) => ("constant", None), + Some(AssocItem(ImplItem::TypeAlias(_))) => ("type", None), + Some(Def(ModuleDef::Module(_))) => ("module", None), + Some(Def(ModuleDef::Function(_))) => ("function", None), + Some(Def(ModuleDef::Struct(_))) => ("type", None), + Some(Def(ModuleDef::Union(_))) => ("type", None), + Some(Def(ModuleDef::Enum(_))) => ("type", None), + Some(Def(ModuleDef::EnumVariant(_))) => ("constant", None), + Some(Def(ModuleDef::Const(_))) => ("constant", None), + Some(Def(ModuleDef::Static(_))) => ("constant", None), + Some(Def(ModuleDef::Trait(_))) => ("type", None), + Some(Def(ModuleDef::TypeAlias(_))) => ("type", None), + Some(SelfType(_)) => ("type", None), + Some(Pat(ptr)) => ("variable", Some(hash(ptr.syntax_node_ptr().range()))), + Some(SelfParam(_)) => ("type", None), + Some(GenericParam(_)) => ("type", None), + None => ("text", None), } } else { - "text" + ("text", None) } } - NAME => "function", - TYPE_ALIAS_DEF | TYPE_ARG | TYPE_PARAM => "type", - INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", - LIFETIME => "parameter", - T![unsafe] => "keyword.unsafe", - k if is_control_keyword(k) => "keyword.control", - k if k.is_keyword() => "keyword", + NAME => { + if let Some(name) = node.as_ast_node::() { + ("variable", Some(hash(name.syntax().range()))) + } else { + ("text", None) + } + } + TYPE_ALIAS_DEF | TYPE_ARG | TYPE_PARAM => ("type", None), + INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => ("literal", None), + LIFETIME => ("parameter", None), + T![unsafe] => ("keyword.unsafe", None), + k if is_control_keyword(k) => ("keyword.control", None), + k if k.is_keyword() => ("keyword", None), _ => { + // let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); if let Some(macro_call) = node.as_node().and_then(ast::MacroCall::cast) { if let Some(path) = macro_call.path() { if let Some(segment) = path.segment() { @@ -101,6 +117,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec Vec Result> { .analysis() .highlight(file_id)? .into_iter() - .map(|h| Decoration { range: h.range.conv_with(&line_index), tag: h.tag }) + .map(|h| Decoration { + range: h.range.conv_with(&line_index), + tag: h.tag, + id: h.id.map(|x| x.to_string()), + }) .collect(); Ok(res) } diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 6090eb7b9..cea0e6ce7 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs @@ -129,6 +129,7 @@ pub struct PublishDecorationsParams { pub struct Decoration { pub range: Range, pub tag: &'static str, + pub id: Option, } pub enum ParentModule {} diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs index 80054f529..89f92e0b7 100644 --- a/crates/ra_syntax/src/syntax_node.rs +++ b/crates/ra_syntax/src/syntax_node.rs @@ -523,6 +523,10 @@ impl<'a> SyntaxElement<'a> { } } + pub fn as_ast_node(&self) -> Option<&T> { + self.as_node().and_then(|x| ::cast(x)) + } + pub fn as_token(&self) -> Option> { match self { SyntaxElement::Node(_) => None, -- cgit v1.2.3 From ed89b0638b1dbf8f9a33d9a95e829e602142bb05 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 25 May 2019 12:56:52 +0200 Subject: Hash based on binding name and shadow counter --- .../src/snapshots/tests__highlighting.snap | 14 +-- .../src/snapshots/tests__rainbow_highlighting.snap | 128 +++++++++++++++++++++ .../src/snapshots/tests__sematic_highlighting.snap | 87 -------------- crates/ra_ide_api/src/syntax_highlighting.rs | 26 ++++- crates/ra_syntax/src/syntax_text.rs | 7 +- 5 files changed, 161 insertions(+), 101 deletions(-) create mode 100644 crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap delete mode 100644 crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap (limited to 'crates') diff --git a/crates/ra_ide_api/src/snapshots/tests__highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__highlighting.snap index 208681f10..e50003b3c 100644 --- a/crates/ra_ide_api/src/snapshots/tests__highlighting.snap +++ b/crates/ra_ide_api/src/snapshots/tests__highlighting.snap @@ -1,5 +1,5 @@ --- -created: "2019-05-25T10:53:54.439877Z" +created: "2019-05-25T11:24:53.486036Z" creator: insta@0.8.1 source: crates/ra_ide_api/src/syntax_highlighting.rs expression: result @@ -20,7 +20,7 @@ Ok( range: [32; 35), tag: "variable", id: Some( - 461893210254723387, + 8465336196764640996, ), }, HighlightedRange { @@ -32,7 +32,7 @@ Ok( range: [46; 47), tag: "variable", id: Some( - 8312289520117458465, + 176272420896316891, ), }, HighlightedRange { @@ -49,7 +49,7 @@ Ok( range: [62; 63), tag: "variable", id: Some( - 4497542318236667727, + 15061637676198917049, ), }, HighlightedRange { @@ -66,7 +66,7 @@ Ok( range: [76; 79), tag: "variable", id: Some( - 4506850079084802999, + 14077410872302487760, ), }, HighlightedRange { @@ -78,7 +78,7 @@ Ok( range: [80; 81), tag: "variable", id: Some( - 16968185728268100018, + 8379786015941272633, ), }, HighlightedRange { @@ -105,7 +105,7 @@ Ok( range: [131; 135), tag: "variable", id: Some( - 14467718814232352107, + 5766414492220109266, ), }, HighlightedRange { diff --git a/crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap new file mode 100644 index 000000000..84cd521a2 --- /dev/null +++ b/crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap @@ -0,0 +1,128 @@ +--- +created: "2019-05-25T11:21:56.117898Z" +creator: insta@0.8.1 +source: crates/ra_ide_api/src/syntax_highlighting.rs +expression: result +--- +Ok( + [ + HighlightedRange { + range: [1; 3), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [4; 8), + tag: "variable", + id: Some( + 5766414492220109266, + ), + }, + HighlightedRange { + range: [17; 20), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [21; 26), + tag: "variable", + id: Some( + 15975256018338854530, + ), + }, + HighlightedRange { + range: [29; 36), + tag: "string", + id: None, + }, + HighlightedRange { + range: [42; 45), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [46; 47), + tag: "variable", + id: Some( + 176272420896316891, + ), + }, + HighlightedRange { + range: [50; 55), + tag: "variable", + id: Some( + 15975256018338854530, + ), + }, + HighlightedRange { + range: [56; 65), + tag: "text", + id: None, + }, + HighlightedRange { + range: [73; 76), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [77; 78), + tag: "variable", + id: Some( + 15061637676198917049, + ), + }, + HighlightedRange { + range: [81; 86), + tag: "variable", + id: Some( + 15975256018338854530, + ), + }, + HighlightedRange { + range: [87; 96), + tag: "text", + id: None, + }, + HighlightedRange { + range: [105; 108), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [109; 110), + tag: "variable", + id: Some( + 1714508680417729339, + ), + }, + HighlightedRange { + range: [113; 134), + tag: "string", + id: None, + }, + HighlightedRange { + range: [140; 143), + tag: "keyword", + id: None, + }, + HighlightedRange { + range: [144; 145), + tag: "variable", + id: Some( + 15953336624848413466, + ), + }, + HighlightedRange { + range: [148; 149), + tag: "variable", + id: Some( + 1714508680417729339, + ), + }, + HighlightedRange { + range: [150; 159), + tag: "text", + id: None, + }, + ], +) diff --git a/crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap deleted file mode 100644 index 3b3fe32e9..000000000 --- a/crates/ra_ide_api/src/snapshots/tests__sematic_highlighting.snap +++ /dev/null @@ -1,87 +0,0 @@ ---- -created: "2019-05-25T10:25:13.898113Z" -creator: insta@0.8.1 -source: crates/ra_ide_api/src/syntax_highlighting.rs -expression: result ---- -Ok( - [ - HighlightedRange { - range: [1; 3), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [4; 8), - tag: "variable", - id: Some( - 17119830160611610240, - ), - }, - HighlightedRange { - range: [17; 20), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [21; 26), - tag: "variable", - id: Some( - 2744494144922727377, - ), - }, - HighlightedRange { - range: [29; 36), - tag: "string", - id: None, - }, - HighlightedRange { - range: [42; 45), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [46; 47), - tag: "variable", - id: Some( - 10375904121795371996, - ), - }, - HighlightedRange { - range: [50; 55), - tag: "variable", - id: Some( - 2744494144922727377, - ), - }, - HighlightedRange { - range: [56; 65), - tag: "text", - id: None, - }, - HighlightedRange { - range: [73; 76), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [77; 78), - tag: "variable", - id: Some( - 8228548264153724449, - ), - }, - HighlightedRange { - range: [81; 86), - tag: "variable", - id: Some( - 2744494144922727377, - ), - }, - HighlightedRange { - range: [87; 96), - tag: "text", - id: None, - }, - ], -) diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index da000c0c3..407fcda4a 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -1,6 +1,6 @@ -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashSet, FxHashMap}; -use ra_syntax::{ast, AstNode, TextRange, Direction, SyntaxKind, SyntaxKind::*, SyntaxElement, T}; +use ra_syntax::{ast, AstNode, TextRange, Direction, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxElement, T}; use ra_db::SourceDatabase; use ra_prof::profile; @@ -43,6 +43,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec = FxHashSet::default(); + let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); + let mut res = Vec::new(); for node in source_file.syntax().descendants_with_tokens() { if highlighted.contains(&node) { @@ -77,7 +79,11 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec ("type", None), Some(Def(ModuleDef::TypeAlias(_))) => ("type", None), Some(SelfType(_)) => ("type", None), - Some(Pat(ptr)) => ("variable", Some(hash(ptr.syntax_node_ptr().range()))), + Some(Pat(ptr)) => ("variable", Some(hash({ + let text = ptr.syntax_node_ptr().to_node(&source_file.syntax()).text().to_smol_string(); + let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); + (text, shadow_count) + }))), Some(SelfParam(_)) => ("type", None), Some(GenericParam(_)) => ("type", None), None => ("text", None), @@ -88,7 +94,12 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { if let Some(name) = node.as_ast_node::() { - ("variable", Some(hash(name.syntax().range()))) + ("variable", Some(hash({ + let text = name.syntax().text().to_smol_string(); + let shadow_count = bindings_shadow_count.entry(text.clone()).or_insert(1); + *shadow_count += 1; + (text, shadow_count) + }))) } else { ("text", None) } @@ -240,16 +251,19 @@ fn main() { } #[test] - fn test_sematic_highlighting() { + fn test_rainbow_highlighting() { let (analysis, file_id) = single_file( r#" fn main() { let hello = "hello"; let x = hello.to_string(); let y = hello.to_string(); + + let x = "other color please!"; + let y = x.to_string(); }"#, ); let result = analysis.highlight(file_id); - assert_debug_snapshot_matches!("sematic_highlighting", result); + assert_debug_snapshot_matches!("rainbow_highlighting", result); } } diff --git a/crates/ra_syntax/src/syntax_text.rs b/crates/ra_syntax/src/syntax_text.rs index b013164c4..bff1ed5a0 100644 --- a/crates/ra_syntax/src/syntax_text.rs +++ b/crates/ra_syntax/src/syntax_text.rs @@ -1,6 +1,6 @@ use std::{fmt, ops::{self, Bound}}; -use crate::{SyntaxNode, TextRange, TextUnit, SyntaxElement}; +use crate::{SmolStr, SyntaxNode, TextRange, TextUnit, SyntaxElement}; #[derive(Clone)] pub struct SyntaxText<'a> { @@ -34,6 +34,11 @@ impl<'a> SyntaxText<'a> { self.chunks().collect() } + pub fn to_smol_string(&self) -> SmolStr { + // TODO: `impl iter::FromIterator<&str> for SmolStr` + self.to_string().into() + } + pub fn contains(&self, c: char) -> bool { self.chunks().any(|it| it.contains(c)) } -- cgit v1.2.3 From 43d5a4965308ec4b594725c0bd02cb046bdb730c Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 25 May 2019 16:23:58 +0200 Subject: More clever highlighting, incl draft for structs --- crates/ra_cli/src/main.rs | 9 +- crates/ra_ide_api/Cargo.toml | 1 + crates/ra_ide_api/src/lib.rs | 2 +- crates/ra_ide_api/src/snapshots/highlighting.html | 24 +-- .../src/snapshots/rainbow_highlighting.html | 27 +++ .../src/snapshots/tests__highlighting.snap | 192 --------------------- .../src/snapshots/tests__rainbow_highlighting.snap | 128 -------------- crates/ra_ide_api/src/syntax_highlighting.rs | 185 ++++++++++++-------- crates/ra_syntax/src/syntax_node.rs | 4 - 9 files changed, 158 insertions(+), 414 deletions(-) create mode 100644 crates/ra_ide_api/src/snapshots/rainbow_highlighting.html delete mode 100644 crates/ra_ide_api/src/snapshots/tests__highlighting.snap delete mode 100644 crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap (limited to 'crates') diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index 93aba4c70..bdc7a76c6 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs @@ -16,7 +16,10 @@ fn main() -> Result<()> { .setting(clap::AppSettings::SubcommandRequiredElseHelp) .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) .subcommand(SubCommand::with_name("symbols")) - .subcommand(SubCommand::with_name("highlight")) + .subcommand( + SubCommand::with_name("highlight") + .arg(Arg::with_name("rainbow").short("r").long("rainbow")) + ) .subcommand( SubCommand::with_name("analysis-stats") .arg(Arg::with_name("verbose").short("v").long("verbose")) @@ -39,9 +42,9 @@ fn main() -> Result<()> { println!("{:?}", s); } } - ("highlight", _) => { + ("highlight", Some(matches)) => { let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); - let html = analysis.highlight_as_html(file_id).unwrap(); + let html = analysis.highlight_as_html(file_id, matches.is_present("rainbow")).unwrap(); println!("{}", html); } ("analysis-stats", Some(matches)) => { diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml index d399d5e2e..8939e9d79 100644 --- a/crates/ra_ide_api/Cargo.toml +++ b/crates/ra_ide_api/Cargo.toml @@ -15,6 +15,7 @@ rustc-hash = "1.0" parking_lot = "0.7.0" unicase = "2.2.0" superslice = "1.0.0" +rand = "0.6.5" jemallocator = { version = "0.1.9", optional = true } jemalloc-ctl = { version = "0.2.0", optional = true } diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index d3456d5b2..65a3b591a 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -464,7 +464,7 @@ impl Analysis { /// Computes syntax highlighting for the given file. pub fn highlight_as_html(&self, file_id: FileId) -> Cancelable { - self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id)) + self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, true)) } /// Computes completions at the given position. diff --git a/crates/ra_ide_api/src/snapshots/highlighting.html b/crates/ra_ide_api/src/snapshots/highlighting.html index bfc0a67b1..4f4ed62a1 100644 --- a/crates/ra_ide_api/src/snapshots/highlighting.html +++ b/crates/ra_ide_api/src/snapshots/highlighting.html @@ -1,10 +1,7 @@ -

-#[derive(Clone, Debug)]
+
#[derive(Clone, Debug)]
 struct Foo {
-    pub x: i32,
-    pub y: i32,
+    pub x: i32,
+    pub y: i32,
 }
 
 fn foo<T>() -> T {
@@ -36,10 +31,9 @@ pre {
 fn main() {
     println!("Hello, {}!", 92);
 
-    let mut vec = Vec::new();
+    let mut vec = Vec::new();
     if true {
-        vec.push(Foo { x: 0, y: 1 });
+        vec.push(Foo { x: 0, y: 1 });
     }
-    unsafe { vec.set_len(0); }
-}
-
\ No newline at end of file + unsafe { vec.set_len(0); } +}
\ No newline at end of file diff --git a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html new file mode 100644 index 000000000..729d129d0 --- /dev/null +++ b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html @@ -0,0 +1,27 @@ + + +
fn main() {
+    let hello = "hello";
+    let x = hello.to_string();
+    let y = hello.to_string();
+
+    let x = "other color please!";
+    let y = x.to_string();
+}
\ No newline at end of file diff --git a/crates/ra_ide_api/src/snapshots/tests__highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__highlighting.snap deleted file mode 100644 index e50003b3c..000000000 --- a/crates/ra_ide_api/src/snapshots/tests__highlighting.snap +++ /dev/null @@ -1,192 +0,0 @@ ---- -created: "2019-05-25T11:24:53.486036Z" -creator: insta@0.8.1 -source: crates/ra_ide_api/src/syntax_highlighting.rs -expression: result ---- -Ok( - [ - HighlightedRange { - range: [1; 24), - tag: "attribute", - id: None, - }, - HighlightedRange { - range: [25; 31), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [32; 35), - tag: "variable", - id: Some( - 8465336196764640996, - ), - }, - HighlightedRange { - range: [42; 45), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [46; 47), - tag: "variable", - id: Some( - 176272420896316891, - ), - }, - HighlightedRange { - range: [49; 52), - tag: "text", - id: None, - }, - HighlightedRange { - range: [58; 61), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [62; 63), - tag: "variable", - id: Some( - 15061637676198917049, - ), - }, - HighlightedRange { - range: [65; 68), - tag: "text", - id: None, - }, - HighlightedRange { - range: [73; 75), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [76; 79), - tag: "variable", - id: Some( - 14077410872302487760, - ), - }, - HighlightedRange { - range: [80; 81), - tag: "type", - id: None, - }, - HighlightedRange { - range: [80; 81), - tag: "variable", - id: Some( - 8379786015941272633, - ), - }, - HighlightedRange { - range: [88; 89), - tag: "type", - id: None, - }, - HighlightedRange { - range: [96; 110), - tag: "macro", - id: None, - }, - HighlightedRange { - range: [117; 127), - tag: "comment", - id: None, - }, - HighlightedRange { - range: [128; 130), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [131; 135), - tag: "variable", - id: Some( - 5766414492220109266, - ), - }, - HighlightedRange { - range: [145; 153), - tag: "macro", - id: None, - }, - HighlightedRange { - range: [154; 166), - tag: "string", - id: None, - }, - HighlightedRange { - range: [168; 170), - tag: "literal", - id: None, - }, - HighlightedRange { - range: [178; 181), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [182; 185), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [186; 189), - tag: "macro", - id: None, - }, - HighlightedRange { - range: [197; 200), - tag: "macro", - id: None, - }, - HighlightedRange { - range: [192; 195), - tag: "text", - id: None, - }, - HighlightedRange { - range: [208; 211), - tag: "macro", - id: None, - }, - HighlightedRange { - range: [212; 216), - tag: "macro", - id: None, - }, - HighlightedRange { - range: [226; 227), - tag: "literal", - id: None, - }, - HighlightedRange { - range: [232; 233), - tag: "literal", - id: None, - }, - HighlightedRange { - range: [242; 248), - tag: "keyword.unsafe", - id: None, - }, - HighlightedRange { - range: [251; 254), - tag: "text", - id: None, - }, - HighlightedRange { - range: [255; 262), - tag: "text", - id: None, - }, - HighlightedRange { - range: [263; 264), - tag: "literal", - id: None, - }, - ], -) diff --git a/crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap b/crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap deleted file mode 100644 index 84cd521a2..000000000 --- a/crates/ra_ide_api/src/snapshots/tests__rainbow_highlighting.snap +++ /dev/null @@ -1,128 +0,0 @@ ---- -created: "2019-05-25T11:21:56.117898Z" -creator: insta@0.8.1 -source: crates/ra_ide_api/src/syntax_highlighting.rs -expression: result ---- -Ok( - [ - HighlightedRange { - range: [1; 3), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [4; 8), - tag: "variable", - id: Some( - 5766414492220109266, - ), - }, - HighlightedRange { - range: [17; 20), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [21; 26), - tag: "variable", - id: Some( - 15975256018338854530, - ), - }, - HighlightedRange { - range: [29; 36), - tag: "string", - id: None, - }, - HighlightedRange { - range: [42; 45), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [46; 47), - tag: "variable", - id: Some( - 176272420896316891, - ), - }, - HighlightedRange { - range: [50; 55), - tag: "variable", - id: Some( - 15975256018338854530, - ), - }, - HighlightedRange { - range: [56; 65), - tag: "text", - id: None, - }, - HighlightedRange { - range: [73; 76), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [77; 78), - tag: "variable", - id: Some( - 15061637676198917049, - ), - }, - HighlightedRange { - range: [81; 86), - tag: "variable", - id: Some( - 15975256018338854530, - ), - }, - HighlightedRange { - range: [87; 96), - tag: "text", - id: None, - }, - HighlightedRange { - range: [105; 108), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [109; 110), - tag: "variable", - id: Some( - 1714508680417729339, - ), - }, - HighlightedRange { - range: [113; 134), - tag: "string", - id: None, - }, - HighlightedRange { - range: [140; 143), - tag: "keyword", - id: None, - }, - HighlightedRange { - range: [144; 145), - tag: "variable", - id: Some( - 15953336624848413466, - ), - }, - HighlightedRange { - range: [148; 149), - tag: "variable", - id: Some( - 1714508680417729339, - ), - }, - HighlightedRange { - range: [150; 159), - tag: "text", - id: None, - }, - ], -) diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 407fcda4a..8981c85e6 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -10,7 +10,7 @@ use crate::{FileId, db::RootDatabase}; pub struct HighlightedRange { pub range: TextRange, pub tag: &'static str, - pub id: Option, + pub binding_hash: Option, } fn is_control_keyword(kind: SyntaxKind) -> bool { @@ -30,15 +30,18 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let _p = profile("highlight"); - let source_file = db.parse(file_id); - fn hash(x: T) -> u64 { - use std::{collections::hash_map::DefaultHasher, hash::Hasher}; + fn calc_binding_hash(file_id: FileId, text: &SmolStr, shadow_count: u32) -> u64 { + fn hash(x: T) -> u64 { + use std::{collections::hash_map::DefaultHasher, hash::Hasher}; + + let mut hasher = DefaultHasher::new(); + x.hash(&mut hasher); + hasher.finish() + } - let mut hasher = DefaultHasher::new(); - x.hash(&mut hasher); - hasher.finish() + hash((file_id, text, shadow_count)) } // Visited nodes to handle highlighting priorities @@ -50,66 +53,92 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec ("comment", None), - STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => ("string", None), - ATTR => ("attribute", None), + let mut binding_hash = None; + let tag = match node.kind() { + COMMENT => "comment", + STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", + ATTR => "attribute", NAME_REF => { - if let Some(name_ref) = node.as_ast_node::() { + if let Some(name_ref) = node.as_node().and_then(ast::NameRef::cast) { use crate::name_ref_kind::{classify_name_ref, NameRefKind::*}; use hir::{ModuleDef, ImplItem}; // FIXME: try to reuse the SourceAnalyzers let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); match classify_name_ref(db, &analyzer, name_ref) { - Some(Method(_)) => ("function", None), - Some(Macro(_)) => ("macro", None), - Some(FieldAccess(_)) => ("field", None), - Some(AssocItem(ImplItem::Method(_))) => ("function", None), - Some(AssocItem(ImplItem::Const(_))) => ("constant", None), - Some(AssocItem(ImplItem::TypeAlias(_))) => ("type", None), - Some(Def(ModuleDef::Module(_))) => ("module", None), - Some(Def(ModuleDef::Function(_))) => ("function", None), - Some(Def(ModuleDef::Struct(_))) => ("type", None), - Some(Def(ModuleDef::Union(_))) => ("type", None), - Some(Def(ModuleDef::Enum(_))) => ("type", None), - Some(Def(ModuleDef::EnumVariant(_))) => ("constant", None), - Some(Def(ModuleDef::Const(_))) => ("constant", None), - Some(Def(ModuleDef::Static(_))) => ("constant", None), - Some(Def(ModuleDef::Trait(_))) => ("type", None), - Some(Def(ModuleDef::TypeAlias(_))) => ("type", None), - Some(SelfType(_)) => ("type", None), - Some(Pat(ptr)) => ("variable", Some(hash({ - let text = ptr.syntax_node_ptr().to_node(&source_file.syntax()).text().to_smol_string(); - let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); - (text, shadow_count) - }))), - Some(SelfParam(_)) => ("type", None), - Some(GenericParam(_)) => ("type", None), - None => ("text", None), + Some(Method(_)) => "function", + Some(Macro(_)) => "macro", + Some(FieldAccess(field)) => { + let (hir_file_id, src) = field.source(db); + if let hir::FieldSource::Named(name) = src { + let text = name.syntax().text().to_smol_string(); + let shadow_count = 0; // potentially even from different file + binding_hash = Some(calc_binding_hash(hir_file_id.original_file(db), &text, shadow_count)); + } + + "field" + }, + Some(AssocItem(ImplItem::Method(_))) => "function", + Some(AssocItem(ImplItem::Const(_))) => "constant", + Some(AssocItem(ImplItem::TypeAlias(_))) => "type", + Some(Def(ModuleDef::Module(_))) => "module", + Some(Def(ModuleDef::Function(_))) => "function", + Some(Def(ModuleDef::Struct(_))) => "type", + Some(Def(ModuleDef::Union(_))) => "type", + Some(Def(ModuleDef::Enum(_))) => "type", + Some(Def(ModuleDef::EnumVariant(_))) => "constant", + Some(Def(ModuleDef::Const(_))) => "constant", + Some(Def(ModuleDef::Static(_))) => "constant", + Some(Def(ModuleDef::Trait(_))) => "type", + Some(Def(ModuleDef::TypeAlias(_))) => "type", + Some(SelfType(_)) => "type", + Some(Pat(ptr)) => { + binding_hash = Some({ + let text = ptr.syntax_node_ptr().to_node(&source_file.syntax()).text().to_smol_string(); + let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); + calc_binding_hash(file_id, &text, *shadow_count) + }); + + "variable" + }, + Some(SelfParam(_)) => "type", + Some(GenericParam(_)) => "type", + None => "text", } } else { - ("text", None) + "text" } } NAME => { - if let Some(name) = node.as_ast_node::() { - ("variable", Some(hash({ - let text = name.syntax().text().to_smol_string(); - let shadow_count = bindings_shadow_count.entry(text.clone()).or_insert(1); - *shadow_count += 1; - (text, shadow_count) - }))) + if let Some(name) = node.as_node().and_then(ast::Name::cast) { + if name.syntax().ancestors().any(|x| ast::BindPat::cast(x).is_some()) { + binding_hash = Some({ + let text = name.syntax().text().to_smol_string(); + let shadow_count = bindings_shadow_count.entry(text.clone()).or_insert(0); + *shadow_count += 1; + calc_binding_hash(file_id, &text, *shadow_count) + }); + "variable" + } else if name.syntax().ancestors().any(|x| ast::NamedFieldDef::cast(x).is_some()) { + binding_hash = Some({ + let text = name.syntax().text().to_smol_string(); + let shadow_count = 0; + calc_binding_hash(file_id, &text, shadow_count) + }); + "variable" + } else { + "function" + } } else { - ("text", None) + "text" } } - TYPE_ALIAS_DEF | TYPE_ARG | TYPE_PARAM => ("type", None), - INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => ("literal", None), - LIFETIME => ("parameter", None), - T![unsafe] => ("keyword.unsafe", None), - k if is_control_keyword(k) => ("keyword.control", None), - k if k.is_keyword() => ("keyword", None), + TYPE_ALIAS_DEF | TYPE_ARG | TYPE_PARAM => "type", + INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", + LIFETIME => "parameter", + T![unsafe] => "keyword.unsafe", + k if is_control_keyword(k) => "keyword.control", + k if k.is_keyword() => "keyword", _ => { // let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); if let Some(macro_call) = node.as_node().and_then(ast::MacroCall::cast) { @@ -128,7 +157,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec Vec String { +pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { let source_file = db.parse(file_id); + fn rainbowify(seed: u64) -> String { + use rand::prelude::*; + let mut rng = SmallRng::seed_from_u64(seed); + format!("hsl({h},{s}%,{l}%)", + h = rng.gen_range::(0, 361), + s = rng.gen_range::(42, 99), + l = rng.gen_range::(40, 91), + ) + } + let mut ranges = highlight(db, file_id); ranges.sort_by_key(|it| it.range.start()); // quick non-optimal heuristic to intersect token ranges and highlighted ranges @@ -166,16 +205,20 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId) -> String { } } let text = html_escape(&token.text()); - let classes = could_intersect + let ranges = could_intersect .iter() .filter(|it| token.range().is_subrange(&it.range)) - .map(|it| it.tag) .collect::>(); - if classes.is_empty() { + if ranges.is_empty() { buf.push_str(&text); } else { - let classes = classes.join(" "); - buf.push_str(&format!("{}", classes, text)); + let classes = ranges.iter().map(|x| x.tag).collect::>().join(" "); + let binding_hash = ranges.first().and_then(|x| x.binding_hash); + let color = match (rainbow, binding_hash) { + (true, Some(hash)) => format!(" data-binding-hash=\"{}\" style=\"color: {};\"", hash, rainbowify(hash)), + _ => "".into() + }; + buf.push_str(&format!("{}", classes, color, text)); } } buf.push_str(""); @@ -189,11 +232,8 @@ fn html_escape(text: &str) -> String { const STYLE: &str = " "; @@ -241,12 +280,12 @@ fn main() { } unsafe { vec.set_len(0); } } -"#, +"#.trim(), ); let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); let actual_html = &analysis.highlight_as_html(file_id).unwrap(); let expected_html = &read_text(&dst_file); - // std::fs::write(dst_file, &actual_html).unwrap(); + std::fs::write(dst_file, &actual_html).unwrap(); assert_eq_text!(expected_html, actual_html); } @@ -261,9 +300,13 @@ fn main() { let x = "other color please!"; let y = x.to_string(); -}"#, +} +"#.trim(), ); - let result = analysis.highlight(file_id); - assert_debug_snapshot_matches!("rainbow_highlighting", result); + let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/rainbow_highlighting.html"); + let actual_html = &analysis.highlight_as_html(file_id).unwrap(); + let expected_html = &read_text(&dst_file); + std::fs::write(dst_file, &actual_html).unwrap(); + assert_eq_text!(expected_html, actual_html); } } diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs index 89f92e0b7..80054f529 100644 --- a/crates/ra_syntax/src/syntax_node.rs +++ b/crates/ra_syntax/src/syntax_node.rs @@ -523,10 +523,6 @@ impl<'a> SyntaxElement<'a> { } } - pub fn as_ast_node(&self) -> Option<&T> { - self.as_node().and_then(|x| ::cast(x)) - } - pub fn as_token(&self) -> Option> { match self { SyntaxElement::Node(_) => None, -- cgit v1.2.3 From 2b200f6e1a600e263f314efba5d8c3743095071b Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sat, 25 May 2019 16:29:39 +0200 Subject: Disable broken struct field rainbowing --- crates/ra_ide_api/src/lib.rs | 6 +++--- crates/ra_ide_api/src/snapshots/highlighting.html | 6 +++--- crates/ra_ide_api/src/syntax_highlighting.rs | 18 +----------------- 3 files changed, 7 insertions(+), 23 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 65a3b591a..452407e8e 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -463,8 +463,8 @@ impl Analysis { } /// Computes syntax highlighting for the given file. - pub fn highlight_as_html(&self, file_id: FileId) -> Cancelable { - self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, true)) + pub fn highlight_as_html(&self, file_id: FileId, rainbow: bool) -> Cancelable { + self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, rainbow)) } /// Computes completions at the given position. @@ -472,7 +472,7 @@ impl Analysis { self.with_db(|db| completion::completions(db, position).map(Into::into)) } - /// Computes assists (aks code actons aka intentions) for the given + /// Computes assists (aka code actions aka intentions) for the given /// position. pub fn assists(&self, frange: FileRange) -> Cancelable> { self.with_db(|db| assists::assists(db, frange)) diff --git a/crates/ra_ide_api/src/snapshots/highlighting.html b/crates/ra_ide_api/src/snapshots/highlighting.html index 4f4ed62a1..ebd187a35 100644 --- a/crates/ra_ide_api/src/snapshots/highlighting.html +++ b/crates/ra_ide_api/src/snapshots/highlighting.html @@ -19,8 +19,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4e
#[derive(Clone, Debug)]
 struct Foo {
-    pub x: i32,
-    pub y: i32,
+    pub x: i32,
+    pub y: i32,
 }
 
 fn foo<T>() -> T {
@@ -33,7 +33,7 @@ pre        { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4e
 
     let mut vec = Vec::new();
     if true {
-        vec.push(Foo { x: 0, y: 1 });
+        vec.push(Foo { x: 0, y: 1 });
     }
     unsafe { vec.set_len(0); }
 }
\ No newline at end of file diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 8981c85e6..e46686ab9 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -68,16 +68,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "function", Some(Macro(_)) => "macro", - Some(FieldAccess(field)) => { - let (hir_file_id, src) = field.source(db); - if let hir::FieldSource::Named(name) = src { - let text = name.syntax().text().to_smol_string(); - let shadow_count = 0; // potentially even from different file - binding_hash = Some(calc_binding_hash(hir_file_id.original_file(db), &text, shadow_count)); - } - - "field" - }, + Some(FieldAccess(_)) => "field", Some(AssocItem(ImplItem::Method(_))) => "function", Some(AssocItem(ImplItem::Const(_))) => "constant", Some(AssocItem(ImplItem::TypeAlias(_))) => "type", @@ -119,13 +110,6 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec Date: Sun, 26 May 2019 11:56:31 +0200 Subject: make it build again --- crates/ra_cli/src/main.rs | 2 +- crates/ra_ide_api/src/syntax_highlighting.rs | 38 ++++++++++++++++++-------- crates/ra_lsp_server/src/main_loop/handlers.rs | 2 +- 3 files changed, 28 insertions(+), 14 deletions(-) (limited to 'crates') diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index bdc7a76c6..84a1564ce 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs @@ -18,7 +18,7 @@ fn main() -> Result<()> { .subcommand(SubCommand::with_name("symbols")) .subcommand( SubCommand::with_name("highlight") - .arg(Arg::with_name("rainbow").short("r").long("rainbow")) + .arg(Arg::with_name("rainbow").short("r").long("rainbow")), ) .subcommand( SubCommand::with_name("analysis-stats") diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index e46686ab9..dcefb0513 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -85,13 +85,18 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "type", Some(Pat(ptr)) => { binding_hash = Some({ - let text = ptr.syntax_node_ptr().to_node(&source_file.syntax()).text().to_smol_string(); - let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); + let text = ptr + .syntax_node_ptr() + .to_node(&source_file.syntax()) + .text() + .to_smol_string(); + let shadow_count = + bindings_shadow_count.entry(text.clone()).or_default(); calc_binding_hash(file_id, &text, *shadow_count) }); "variable" - }, + } Some(SelfParam(_)) => "type", Some(GenericParam(_)) => "type", None => "text", @@ -105,7 +110,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec String { use rand::prelude::*; let mut rng = SmallRng::seed_from_u64(seed); - format!("hsl({h},{s}%,{l}%)", + format!( + "hsl({h},{s}%,{l}%)", h = rng.gen_range::(0, 361), s = rng.gen_range::(42, 99), l = rng.gen_range::(40, 91), @@ -199,8 +206,12 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo let classes = ranges.iter().map(|x| x.tag).collect::>().join(" "); let binding_hash = ranges.first().and_then(|x| x.binding_hash); let color = match (rainbow, binding_hash) { - (true, Some(hash)) => format!(" data-binding-hash=\"{}\" style=\"color: {};\"", hash, rainbowify(hash)), - _ => "".into() + (true, Some(hash)) => format!( + " data-binding-hash=\"{}\" style=\"color: {};\"", + hash, + rainbowify(hash) + ), + _ => "".into(), }; buf.push_str(&format!("{}", classes, color, text)); } @@ -264,10 +275,11 @@ fn main() { } unsafe { vec.set_len(0); } } -"#.trim(), +"# + .trim(), ); let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); - let actual_html = &analysis.highlight_as_html(file_id).unwrap(); + let actual_html = &analysis.highlight_as_html(file_id, true).unwrap(); let expected_html = &read_text(&dst_file); std::fs::write(dst_file, &actual_html).unwrap(); assert_eq_text!(expected_html, actual_html); @@ -285,10 +297,12 @@ fn main() { let x = "other color please!"; let y = x.to_string(); } -"#.trim(), +"# + .trim(), ); - let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/rainbow_highlighting.html"); - let actual_html = &analysis.highlight_as_html(file_id).unwrap(); + let dst_file = + project_dir().join("crates/ra_ide_api/src/snapshots/rainbow_highlighting.html"); + let actual_html = &analysis.highlight_as_html(file_id, true).unwrap(); let expected_html = &read_text(&dst_file); std::fs::write(dst_file, &actual_html).unwrap(); assert_eq_text!(expected_html, actual_html); diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5dfd64ed4..1df8224ba 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -875,7 +875,7 @@ fn highlight(world: &ServerWorld, file_id: FileId) -> Result> { .map(|h| Decoration { range: h.range.conv_with(&line_index), tag: h.tag, - id: h.id.map(|x| x.to_string()), + id: h.binding_hash.map(|x| x.to_string()), }) .collect(); Ok(res) -- cgit v1.2.3 From 4ac338b608bb40c5126d019db63232e7834914c2 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sun, 26 May 2019 15:39:57 +0200 Subject: rename stray id field --- crates/ra_lsp_server/src/main_loop/handlers.rs | 2 +- crates/ra_lsp_server/src/req.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'crates') diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 1df8224ba..e36db12b3 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -875,7 +875,7 @@ fn highlight(world: &ServerWorld, file_id: FileId) -> Result> { .map(|h| Decoration { range: h.range.conv_with(&line_index), tag: h.tag, - id: h.binding_hash.map(|x| x.to_string()), + binding_hash: h.binding_hash.map(|x| x.to_string()), }) .collect(); Ok(res) diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index cea0e6ce7..992c24eac 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs @@ -129,7 +129,7 @@ pub struct PublishDecorationsParams { pub struct Decoration { pub range: Range, pub tag: &'static str, - pub id: Option, + pub binding_hash: Option, } pub enum ParentModule {} -- cgit v1.2.3 From 1e6ba1901550fb1610a1a464c48ec358cd3c339c Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Mon, 27 May 2019 11:26:15 +0200 Subject: Make rainbows optional --- crates/ra_syntax/src/syntax_text.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crates') diff --git a/crates/ra_syntax/src/syntax_text.rs b/crates/ra_syntax/src/syntax_text.rs index bff1ed5a0..c9038cd5c 100644 --- a/crates/ra_syntax/src/syntax_text.rs +++ b/crates/ra_syntax/src/syntax_text.rs @@ -35,7 +35,8 @@ impl<'a> SyntaxText<'a> { } pub fn to_smol_string(&self) -> SmolStr { - // TODO: `impl iter::FromIterator<&str> for SmolStr` + // FIXME: use `self.chunks().collect()` here too once + // https://github.com/matklad/smol_str/pull/12 is merged and published self.to_string().into() } -- cgit v1.2.3