From 9a201873b828b64dd276df42b3dbd263682392b7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 22 Aug 2022 13:38:35 +0200 Subject: [PATCH] Move highlight configuration from protocol into the feature --- crates/ide/src/lib.rs | 18 +++++-- crates/ide/src/syntax_highlighting.rs | 56 ++++++++++++++------ crates/ide/src/syntax_highlighting/html.rs | 19 ++++++- crates/ide/src/syntax_highlighting/inject.rs | 21 ++++++-- crates/ide/src/syntax_highlighting/tests.rs | 24 ++++++--- crates/rust-analyzer/src/config.rs | 18 ++----- crates/rust-analyzer/src/handlers.rs | 18 +++---- crates/rust-analyzer/src/to_proto.rs | 31 +---------- 8 files changed, 119 insertions(+), 86 deletions(-) diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 2b2d3f86a2..d61d69a090 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -98,7 +98,7 @@ pub use crate::{ static_index::{StaticIndex, StaticIndexedFile, TokenId, TokenStaticData}, syntax_highlighting::{ tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag}, - HlRange, + HighlightConfig, HlRange, }, }; pub use hir::{Documentation, Semantics}; @@ -517,8 +517,12 @@ impl Analysis { } /// Computes syntax highlighting for the given file - pub fn highlight(&self, file_id: FileId) -> Cancellable> { - self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) + pub fn highlight( + &self, + highlight_config: HighlightConfig, + file_id: FileId, + ) -> Cancellable> { + self.with_db(|db| syntax_highlighting::highlight(db, highlight_config, file_id, None)) } /// Computes all ranges to highlight for a given item in a file. @@ -533,9 +537,13 @@ impl Analysis { } /// Computes syntax highlighting for the given file range. - pub fn highlight_range(&self, frange: FileRange) -> Cancellable> { + pub fn highlight_range( + &self, + highlight_config: HighlightConfig, + frange: FileRange, + ) -> Cancellable> { self.with_db(|db| { - syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) + syntax_highlighting::highlight(db, highlight_config, frange.file_id, Some(frange.range)) }) } diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 3fb49b45d9..21beeb44a9 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -14,7 +14,7 @@ mod html; mod tests; use hir::{Name, Semantics}; -use ide_db::{FxHashMap, RootDatabase}; +use ide_db::{FxHashMap, RootDatabase, SymbolKind}; use syntax::{ ast, AstNode, AstToken, NodeOrToken, SyntaxKind::*, SyntaxNode, TextRange, WalkEvent, T, }; @@ -24,7 +24,7 @@ use crate::{ escape::highlight_escape_string, format::highlight_format_string, highlights::Highlights, macro_::MacroHighlighter, tags::Highlight, }, - FileId, HlMod, HlTag, + FileId, HlMod, HlOperator, HlPunct, HlTag, }; pub(crate) use html::highlight_as_html; @@ -36,6 +36,16 @@ pub struct HlRange { pub binding_hash: Option, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct HighlightConfig { + pub strings: bool, + pub punctuation: bool, + pub specialize_punctuation: bool, + pub specialize_operator: bool, + pub operator: bool, + pub syntactic_name_ref_highlighting: bool, +} + // Feature: Semantic Syntax Highlighting // // rust-analyzer highlights the code semantically. @@ -155,9 +165,9 @@ pub struct HlRange { // image::https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png[] pub(crate) fn highlight( db: &RootDatabase, + config: HighlightConfig, file_id: FileId, range_to_highlight: Option, - syntactic_name_ref_highlighting: bool, ) -> Vec { let _p = profile::span("highlight"); let sema = Semantics::new(db); @@ -183,26 +193,18 @@ pub(crate) fn highlight( Some(it) => it.krate(), None => return hl.to_vec(), }; - traverse( - &mut hl, - &sema, - file_id, - &root, - krate, - range_to_highlight, - syntactic_name_ref_highlighting, - ); + traverse(&mut hl, &sema, config, file_id, &root, krate, range_to_highlight); hl.to_vec() } fn traverse( hl: &mut Highlights, sema: &Semantics<'_, RootDatabase>, + config: HighlightConfig, file_id: FileId, root: &SyntaxNode, krate: hir::Crate, range_to_highlight: TextRange, - syntactic_name_ref_highlighting: bool, ) { let is_unlinked = sema.to_module_def(file_id).is_none(); let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); @@ -325,7 +327,7 @@ fn traverse( Leave(NodeOrToken::Node(node)) => { // Doc comment highlighting injection, we do this when leaving the node // so that we overwrite the highlighting of the doc comment itself. - inject::doc_comment(hl, sema, file_id, &node); + inject::doc_comment(hl, sema, config, file_id, &node); continue; } }; @@ -400,7 +402,8 @@ fn traverse( let string_to_highlight = ast::String::cast(descended_token.clone()); if let Some((string, expanded_string)) = string.zip(string_to_highlight) { if string.is_raw() { - if inject::ra_fixture(hl, sema, &string, &expanded_string).is_some() { + if inject::ra_fixture(hl, sema, config, &string, &expanded_string).is_some() + { continue; } } @@ -421,7 +424,7 @@ fn traverse( sema, krate, &mut bindings_shadow_count, - syntactic_name_ref_highlighting, + config.syntactic_name_ref_highlighting, name_like, ), NodeOrToken::Token(token) => highlight::token(sema, token).zip(Some(None)), @@ -439,6 +442,27 @@ fn traverse( // something unresolvable. FIXME: There should be a way to prevent that continue; } + + // apply config filtering + match &mut highlight.tag { + HlTag::StringLiteral if !config.strings => continue, + // If punctuation is disabled, make the macro bang part of the macro call again. + tag @ HlTag::Punctuation(HlPunct::MacroBang) + if !config.punctuation || !config.specialize_punctuation => + { + *tag = HlTag::Symbol(SymbolKind::Macro); + } + HlTag::Punctuation(_) if !config.punctuation => continue, + tag @ HlTag::Punctuation(_) if !config.specialize_punctuation => { + *tag = HlTag::Punctuation(HlPunct::Other); + } + HlTag::Operator(_) if !config.operator && highlight.mods.is_empty() => continue, + tag @ HlTag::Operator(_) if !config.specialize_operator => { + *tag = HlTag::Operator(HlOperator::Other); + } + _ => (), + } + if inside_attribute { highlight |= HlMod::Attribute } diff --git a/crates/ide/src/syntax_highlighting/html.rs b/crates/ide/src/syntax_highlighting/html.rs index 9777c014c7..c841456aef 100644 --- a/crates/ide/src/syntax_highlighting/html.rs +++ b/crates/ide/src/syntax_highlighting/html.rs @@ -5,7 +5,10 @@ use oorandom::Rand32; use stdx::format_to; use syntax::AstNode; -use crate::{syntax_highlighting::highlight, FileId, RootDatabase}; +use crate::{ + syntax_highlighting::{highlight, HighlightConfig}, + FileId, RootDatabase, +}; pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { let parse = db.parse(file_id); @@ -20,7 +23,19 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo ) } - let hl_ranges = highlight(db, file_id, None, false); + let hl_ranges = highlight( + db, + HighlightConfig { + strings: true, + punctuation: true, + specialize_punctuation: true, + specialize_operator: true, + operator: true, + syntactic_name_ref_highlighting: false, + }, + file_id, + None, + ); let text = parse.tree().syntax().to_string(); let mut buf = String::new(); buf.push_str(STYLE); diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index f376f9fda7..9139528c7e 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -15,13 +15,14 @@ use syntax::{ use crate::{ doc_links::{doc_attributes, extract_definitions_from_docs, resolve_doc_path_for_def}, - syntax_highlighting::{highlights::Highlights, injector::Injector}, + syntax_highlighting::{highlights::Highlights, injector::Injector, HighlightConfig}, Analysis, HlMod, HlRange, HlTag, RootDatabase, }; pub(super) fn ra_fixture( hl: &mut Highlights, sema: &Semantics<'_, RootDatabase>, + config: HighlightConfig, literal: &ast::String, expanded: &ast::String, ) -> Option<()> { @@ -63,7 +64,13 @@ pub(super) fn ra_fixture( let (analysis, tmp_file_id) = Analysis::from_single_file(inj.take_text()); - for mut hl_range in analysis.highlight(tmp_file_id).unwrap() { + for mut hl_range in analysis + .highlight( + HighlightConfig { syntactic_name_ref_highlighting: false, ..config }, + tmp_file_id, + ) + .unwrap() + { for range in inj.map_range_up(hl_range.range) { if let Some(range) = literal.map_range_up(range) { hl_range.range = range; @@ -86,6 +93,7 @@ const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"]; pub(super) fn doc_comment( hl: &mut Highlights, sema: &Semantics<'_, RootDatabase>, + config: HighlightConfig, src_file_id: FileId, node: &SyntaxNode, ) { @@ -206,7 +214,14 @@ pub(super) fn doc_comment( let (analysis, tmp_file_id) = Analysis::from_single_file(inj.take_text()); - if let Ok(ranges) = analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)) { + if let Ok(ranges) = analysis.with_db(|db| { + super::highlight( + db, + HighlightConfig { syntactic_name_ref_highlighting: true, ..config }, + tmp_file_id, + None, + ) + }) { for HlRange { range, highlight, binding_hash } in ranges { for range in inj.map_range_up(range) { hl.add(HlRange { range, highlight: highlight | HlMod::Injected, binding_hash }); diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 382735cb36..246c6e3722 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -4,7 +4,16 @@ use expect_test::{expect_file, ExpectFile}; use ide_db::SymbolKind; use test_utils::{bench, bench_fixture, skip_slow_tests, AssertLinear}; -use crate::{fixture, FileRange, HlTag, TextRange}; +use crate::{fixture, FileRange, HighlightConfig, HlTag, TextRange}; + +const HL_CONFIG: HighlightConfig = HighlightConfig { + strings: true, + punctuation: true, + specialize_punctuation: true, + specialize_operator: true, + operator: true, + syntactic_name_ref_highlighting: false, +}; #[test] fn attributes() { @@ -996,7 +1005,10 @@ struct Foo { // The "x" let highlights = &analysis - .highlight_range(FileRange { file_id, range: TextRange::at(45.into(), 1.into()) }) + .highlight_range( + HL_CONFIG, + FileRange { file_id, range: TextRange::at(45.into(), 1.into()) }, + ) .unwrap(); assert_eq!(&highlights[0].highlight.to_string(), "field.declaration.public"); @@ -1011,7 +1023,7 @@ macro_rules! test {} }"# .trim(), ); - let _ = analysis.highlight(file_id).unwrap(); + let _ = analysis.highlight(HL_CONFIG, file_id).unwrap(); } /// Highlights the code given by the `ra_fixture` argument, renders the @@ -1035,7 +1047,7 @@ fn benchmark_syntax_highlighting_long_struct() { let hash = { let _pt = bench("syntax highlighting long struct"); analysis - .highlight(file_id) + .highlight(HL_CONFIG, file_id) .unwrap() .iter() .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct)) @@ -1061,7 +1073,7 @@ fn syntax_highlighting_not_quadratic() { let time = Instant::now(); let hash = analysis - .highlight(file_id) + .highlight(HL_CONFIG, file_id) .unwrap() .iter() .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct)) @@ -1086,7 +1098,7 @@ fn benchmark_syntax_highlighting_parser() { let hash = { let _pt = bench("syntax highlighting parser"); analysis - .highlight(file_id) + .highlight(HL_CONFIG, file_id) .unwrap() .iter() .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function)) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 13f533c0ec..3badc89095 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -12,8 +12,8 @@ use std::{ffi::OsString, fmt, iter, path::PathBuf}; use flycheck::FlycheckConfig; use ide::{ AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode, - HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayHintsConfig, JoinLinesConfig, - Snippet, SnippetScope, + HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayHintsConfig, + JoinLinesConfig, Snippet, SnippetScope, }; use ide_db::{ imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, @@ -543,15 +543,6 @@ impl HoverActionsConfig { } } -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct HighlightingConfig { - pub strings: bool, - pub punctuation: bool, - pub specialize_punctuation: bool, - pub specialize_operator: bool, - pub operator: bool, -} - #[derive(Debug, Clone)] pub struct FilesConfig { pub watcher: FilesWatcher, @@ -1200,8 +1191,8 @@ impl Config { } } - pub fn highlighting_config(&self) -> HighlightingConfig { - HighlightingConfig { + pub fn highlighting_config(&self) -> HighlightConfig { + HighlightConfig { strings: self.data.semanticHighlighting_strings_enable, punctuation: self.data.semanticHighlighting_punctuation_enable, specialize_punctuation: self @@ -1209,6 +1200,7 @@ impl Config { .semanticHighlighting_punctuation_specialization_enable, operator: self.data.semanticHighlighting_operator_enable, specialize_operator: self.data.semanticHighlighting_operator_specialization_enable, + syntactic_name_ref_highlighting: false, } } diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index beec3433b7..d89f0f5a3c 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1504,10 +1504,8 @@ pub(crate) fn handle_semantic_tokens_full( let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; - let highlights = snap.analysis.highlight(file_id)?; - let highlighting_config = snap.config.highlighting_config(); - let semantic_tokens = - to_proto::semantic_tokens(&text, &line_index, highlights, highlighting_config); + let highlights = snap.analysis.highlight(snap.config.highlighting_config(), file_id)?; + let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); // Unconditionally cache the tokens snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens.clone()); @@ -1525,10 +1523,8 @@ pub(crate) fn handle_semantic_tokens_full_delta( let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; - let highlights = snap.analysis.highlight(file_id)?; - let highlight_strings = snap.config.highlighting_config(); - let semantic_tokens = - to_proto::semantic_tokens(&text, &line_index, highlights, highlight_strings); + let highlights = snap.analysis.highlight(snap.config.highlighting_config(), file_id)?; + let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); let mut cache = snap.semantic_tokens_cache.lock(); let cached_tokens = cache.entry(params.text_document.uri).or_default(); @@ -1556,10 +1552,8 @@ pub(crate) fn handle_semantic_tokens_range( let text = snap.analysis.file_text(frange.file_id)?; let line_index = snap.file_line_index(frange.file_id)?; - let highlights = snap.analysis.highlight_range(frange)?; - let highlight_strings = snap.config.highlighting_config(); - let semantic_tokens = - to_proto::semantic_tokens(&text, &line_index, highlights, highlight_strings); + let highlights = snap.analysis.highlight_range(snap.config.highlighting_config(), frange)?; + let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights); Ok(Some(semantic_tokens.into())) } diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index f05b81c35d..7a89d6e3e1 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -18,7 +18,7 @@ use vfs::AbsPath; use crate::{ cargo_target_spec::CargoTargetSpec, - config::{CallInfoConfig, Config, HighlightingConfig}, + config::{CallInfoConfig, Config}, global_state::GlobalStateSnapshot, line_index::{LineEndings, LineIndex, OffsetEncoding}, lsp_ext, @@ -517,42 +517,15 @@ pub(crate) fn semantic_tokens( text: &str, line_index: &LineIndex, highlights: Vec, - config: HighlightingConfig, ) -> lsp_types::SemanticTokens { let id = TOKEN_RESULT_COUNTER.fetch_add(1, Ordering::SeqCst).to_string(); let mut builder = semantic_tokens::SemanticTokensBuilder::new(id); - for mut highlight_range in highlights { + for highlight_range in highlights { if highlight_range.highlight.is_empty() { continue; } - // apply config filtering - match &mut highlight_range.highlight.tag { - HlTag::StringLiteral if !config.strings => continue, - // If punctuation is disabled, make the macro bang part of the macro call again. - tag @ HlTag::Punctuation(HlPunct::MacroBang) - if !config.punctuation || !config.specialize_punctuation => - { - *tag = HlTag::Symbol(SymbolKind::Macro); - } - HlTag::Punctuation(_) - if !config.punctuation && highlight_range.highlight.mods.is_empty() => - { - continue - } - tag @ HlTag::Punctuation(_) if !config.specialize_punctuation => { - *tag = HlTag::Punctuation(HlPunct::Other); - } - HlTag::Operator(_) if !config.operator && highlight_range.highlight.mods.is_empty() => { - continue - } - tag @ HlTag::Operator(_) if !config.specialize_operator => { - *tag = HlTag::Operator(HlOperator::Other); - } - _ => (), - } - let (ty, mods) = semantic_token_type_and_modifiers(highlight_range.highlight); let token_index = semantic_tokens::type_index(ty); let modifier_bitset = mods.0;