From 309fc701559088d630121ffccb114422ff18460c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 2 Apr 2020 09:52:27 +0200 Subject: [PATCH] Remove old syntax highlighting --- crates/rust-analyzer/src/config.rs | 3 - crates/rust-analyzer/src/main_loop.rs | 20 +- .../rust-analyzer/src/main_loop/handlers.rs | 35 +-- crates/rust-analyzer/src/req.rs | 32 +-- editors/code/package.json | 10 - editors/code/src/client.ts | 1 - editors/code/src/config.ts | 2 - editors/code/src/highlighting.ts | 255 ------------------ editors/code/src/main.ts | 4 - 9 files changed, 3 insertions(+), 359 deletions(-) delete mode 100644 editors/code/src/highlighting.ts diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3c8f55f1e4..602423919f 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -16,7 +16,6 @@ use serde::Deserialize; #[derive(Debug, Clone)] pub struct Config { pub client_caps: ClientCapsConfig, - pub publish_decorations: bool, pub publish_diagnostics: bool, pub notifications: NotificationsConfig, pub inlay_hints: InlayHintsConfig, @@ -60,7 +59,6 @@ pub struct ClientCapsConfig { impl Default for Config { fn default() -> Self { Config { - publish_decorations: false, publish_diagnostics: true, notifications: NotificationsConfig { workspace_loaded: true, @@ -105,7 +103,6 @@ impl Config { *self = Default::default(); self.client_caps = client_caps; - set(value, "/publishDecorations", &mut self.publish_decorations); set(value, "/excludeGlobs", &mut self.exclude_globs); set(value, "/useClientWatching", &mut self.use_client_watching); set(value, "/lruCapacity", &mut self.lru_capacity); diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 45ae0ad9d1..47fef59d46 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -250,9 +250,7 @@ impl fmt::Debug for Event { } } Event::Task(Task::Notify(not)) => { - if notification_is::(not) - || notification_is::(not) - { + if notification_is::(not) { return debug_verbose_not(not, f); } } @@ -427,7 +425,6 @@ fn loop_turn( update_file_notifications_on_threadpool( pool, world_state.snapshot(), - world_state.config.publish_decorations, task_sender.clone(), loop_state.subscriptions.subscriptions(), ) @@ -508,7 +505,6 @@ fn on_request( .on::(handlers::handle_goto_type_definition)? .on::(handlers::handle_parent_module)? .on::(handlers::handle_runnables)? - .on::(handlers::handle_decorations)? .on::(handlers::handle_completion)? .on::(handlers::handle_code_action)? .on::(handlers::handle_code_lens)? @@ -884,7 +880,6 @@ where fn update_file_notifications_on_threadpool( pool: &ThreadPool, world: WorldSnapshot, - publish_decorations: bool, task_sender: Sender, subscriptions: Vec, ) { @@ -904,19 +899,6 @@ fn update_file_notifications_on_threadpool( } } } - if publish_decorations { - match handlers::publish_decorations(&world, file_id) { - Err(e) => { - if !is_canceled(&e) { - log::error!("failed to compute decorations: {:?}", e); - } - } - Ok(params) => { - let not = notification_new::(params); - task_sender.send(Task::Notify(not)).unwrap(); - } - } - } } }); } diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 23e48c0896..db620dca30 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs @@ -38,7 +38,7 @@ use crate::{ }, diagnostics::DiagnosticTask, from_json, - req::{self, Decoration, InlayHint, InlayHintsParams}, + req::{self, InlayHint, InlayHintsParams}, semantic_tokens::SemanticTokensBuilder, world::WorldSnapshot, LspError, Result, @@ -389,15 +389,6 @@ pub fn handle_runnables( Ok(res) } -pub fn handle_decorations( - world: WorldSnapshot, - params: TextDocumentIdentifier, -) -> Result> { - let _p = profile("handle_decorations"); - let file_id = params.try_conv_with(&world)?; - highlight(&world, file_id) -} - pub fn handle_completion( world: WorldSnapshot, params: req::CompletionParams, @@ -970,15 +961,6 @@ pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result Result { - let _p = profile("publish_decorations"); - let uri = world.file_id_to_uri(file_id)?; - Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? }) -} - fn to_lsp_runnable( world: &WorldSnapshot, file_id: FileId, @@ -1008,21 +990,6 @@ fn to_lsp_runnable( }) } -fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result> { - let line_index = world.analysis().file_line_index(file_id)?; - let res = world - .analysis() - .highlight(file_id)? - .into_iter() - .map(|h| Decoration { - range: h.range.conv_with(&line_index), - tag: h.highlight.to_string(), - binding_hash: h.binding_hash.map(|x| x.to_string()), - }) - .collect(); - Ok(res) -} - pub fn handle_inlay_hints( world: WorldSnapshot, params: InlayHintsParams, diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs index 994f0ed614..ce799a683e 100644 --- a/crates/rust-analyzer/src/req.rs +++ b/crates/rust-analyzer/src/req.rs @@ -1,6 +1,6 @@ //! Defines `rust-analyzer` specific custom messages. -use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; +use lsp_types::{Location, Position, Range, TextDocumentIdentifier}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; @@ -86,36 +86,6 @@ pub struct FindMatchingBraceParams { pub offsets: Vec, } -pub enum DecorationsRequest {} - -impl Request for DecorationsRequest { - type Params = TextDocumentIdentifier; - type Result = Vec; - const METHOD: &'static str = "rust-analyzer/decorationsRequest"; -} - -pub enum PublishDecorations {} - -impl Notification for PublishDecorations { - type Params = PublishDecorationsParams; - const METHOD: &'static str = "rust-analyzer/publishDecorations"; -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct PublishDecorationsParams { - pub uri: Url, - pub decorations: Vec, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct Decoration { - pub range: Range, - pub tag: String, - pub binding_hash: Option, -} - pub enum ParentModule {} impl Request for ParentModule { diff --git a/editors/code/package.json b/editors/code/package.json index 146b696e9c..9f98ab736f 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -182,16 +182,6 @@ "default": false, "description": "Use proposed semantic tokens API for syntax highlighting" }, - "rust-analyzer.highlightingOn": { - "type": "boolean", - "default": false, - "description": "Highlight Rust code (overrides built-in syntax highlighting)" - }, - "rust-analyzer.rainbowHighlightingOn": { - "type": "boolean", - "default": false, - "description": "When highlighting Rust code, use a unique color per identifier" - }, "rust-analyzer.featureFlags": { "type": "object", "default": {}, diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index f909f8db26..8ddc1cdca2 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -7,7 +7,6 @@ import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode- export function configToServerOptions(config: Config) { return { - publishDecorations: !config.highlightingSemanticTokens, lruCapacity: config.lruCapacity, inlayHintsType: config.inlayHints.typeHints, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 501997fef7..c37c6276bb 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -71,8 +71,6 @@ export class Config { get channel() { return this.cfg.get("updates.channel")!; } get askBeforeDownload() { return this.cfg.get("updates.askBeforeDownload")!; } get highlightingSemanticTokens() { return this.cfg.get("highlighting.semanticTokens")!; } - get highlightingOn() { return this.cfg.get("highlightingOn")!; } - get rainbowHighlightingOn() { return this.cfg.get("rainbowHighlightingOn")!; } get lruCapacity() { return this.cfg.get("lruCapacity")!; } get excludeGlobs() { return this.cfg.get("excludeGlobs")!; } get useClientWatching() { return this.cfg.get("useClientWatching")!; } diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts deleted file mode 100644 index ea2dfc0e39..0000000000 --- a/editors/code/src/highlighting.ts +++ /dev/null @@ -1,255 +0,0 @@ -import * as vscode from 'vscode'; -import * as ra from './rust-analyzer-api'; - -import { ColorTheme, TextMateRuleSettings } from './color_theme'; - -import { Ctx } from './ctx'; -import { sendRequestWithRetry, isRustDocument } from './util'; - -export function activateHighlighting(ctx: Ctx) { - const highlighter = new Highlighter(ctx); - - ctx.client.onNotification(ra.publishDecorations, params => { - if (!ctx.config.highlightingOn) return; - - const targetEditor = vscode.window.visibleTextEditors.find( - editor => { - const unescapedUri = unescape( - editor.document.uri.toString(), - ); - // Unescaped URI looks like: - // file:///c:/Workspace/ra-test/src/main.rs - return unescapedUri === params.uri; - }, - ); - if (!targetEditor) return; - - highlighter.setHighlights(targetEditor, params.decorations); - }); - - - vscode.workspace.onDidChangeConfiguration( - _ => highlighter.removeHighlights(), - null, - ctx.subscriptions, - ); - - vscode.window.onDidChangeActiveTextEditor( - async (editor: vscode.TextEditor | undefined) => { - if (!editor || !isRustDocument(editor.document)) return; - if (!ctx.config.highlightingOn) return; - const client = ctx.client; - if (!client) return; - - const decorations = await sendRequestWithRetry( - client, - ra.decorationsRequest, - { uri: editor.document.uri.toString() }, - ); - highlighter.setHighlights(editor, decorations); - }, - null, - ctx.subscriptions, - ); -} - -// Based on this HSL-based color generator: https://gist.github.com/bendc/76c48ce53299e6078a76 -function fancify(seed: string, shade: 'light' | 'dark') { - const random = randomU32Numbers(hashString(seed)); - const randomInt = (min: number, max: number) => { - return Math.abs(random()) % (max - min + 1) + min; - }; - - const h = randomInt(0, 360); - const s = randomInt(42, 98); - const l = shade === 'light' ? randomInt(15, 40) : randomInt(40, 90); - return `hsl(${h},${s}%,${l}%)`; -} - -class Highlighter { - private ctx: Ctx; - private decorations: Map< - string, - vscode.TextEditorDecorationType - > | null = null; - - constructor(ctx: Ctx) { - this.ctx = ctx; - } - - public removeHighlights() { - if (this.decorations == null) { - return; - } - - // Decorations are removed when the object is disposed - for (const decoration of this.decorations.values()) { - decoration.dispose(); - } - - this.decorations = null; - } - - public setHighlights(editor: vscode.TextEditor, highlights: ra.Decoration[]) { - const client = this.ctx.client; - if (!client) return; - // Initialize decorations if necessary - // - // Note: decoration objects need to be kept around so we can dispose them - // if the user disables syntax highlighting - if (this.decorations == null) { - this.decorations = initDecorations(); - } - - const byTag: Map = new Map(); - const colorfulIdents: Map< - string, - [vscode.Range[], boolean] - > = new Map(); - const rainbowTime = this.ctx.config.rainbowHighlightingOn; - - for (const tag of this.decorations.keys()) { - byTag.set(tag, []); - } - - for (const d of highlights) { - if (!byTag.get(d.tag)) { - continue; - } - - if (rainbowTime && d.bindingHash) { - if (!colorfulIdents.has(d.bindingHash)) { - const mut = d.tag.endsWith('.mut'); - colorfulIdents.set(d.bindingHash, [[], mut]); - } - colorfulIdents - .get(d.bindingHash)![0] - .push( - client.protocol2CodeConverter.asRange(d.range), - ); - } else { - byTag - .get(d.tag)! - .push( - client.protocol2CodeConverter.asRange(d.range), - ); - } - } - - for (const tag of byTag.keys()) { - const dec = this.decorations.get( - tag, - ) as vscode.TextEditorDecorationType; - const ranges = byTag.get(tag)!; - editor.setDecorations(dec, ranges); - } - - for (const [hash, [ranges, mut]] of colorfulIdents.entries()) { - const textDecoration = mut ? 'underline' : undefined; - const dec = vscode.window.createTextEditorDecorationType({ - light: { color: fancify(hash, 'light'), textDecoration }, - dark: { color: fancify(hash, 'dark'), textDecoration }, - }); - editor.setDecorations(dec, ranges); - } - } -} - -function initDecorations(): Map { - const theme = ColorTheme.load(); - const res = new Map(); - TAG_TO_SCOPES.forEach((scopes, tag) => { - // We are going to axe this soon, so don't try to detect unknown tags. - // Users should switch to the new semantic tokens implementation. - if (!scopes) return; - const rule = theme.lookup(scopes); - const decor = createDecorationFromTextmate(rule); - res.set(tag, decor); - }); - return res; -} - -function createDecorationFromTextmate( - themeStyle: TextMateRuleSettings, -): vscode.TextEditorDecorationType { - const decorationOptions: vscode.DecorationRenderOptions = {}; - decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; - - if (themeStyle.foreground) { - decorationOptions.color = themeStyle.foreground; - } - - if (themeStyle.background) { - decorationOptions.backgroundColor = themeStyle.background; - } - - if (themeStyle.fontStyle) { - const parts: string[] = themeStyle.fontStyle.split(' '); - parts.forEach(part => { - switch (part) { - case 'italic': - decorationOptions.fontStyle = 'italic'; - break; - case 'bold': - decorationOptions.fontWeight = 'bold'; - break; - case 'underline': - decorationOptions.textDecoration = 'underline'; - break; - default: - break; - } - }); - } - return vscode.window.createTextEditorDecorationType(decorationOptions); -} - -// sync with tags from `syntax_highlighting.rs`. -const TAG_TO_SCOPES = new Map([ - ["field", ["entity.name.field"]], - ["function", ["entity.name.function"]], - ["module", ["entity.name.module"]], - ["constant", ["entity.name.constant"]], - ["macro", ["entity.name.macro"]], - - ["variable", ["variable"]], - ["variable.mutable", ["variable", "meta.mutable"]], - - ["type", ["entity.name.type"]], - ["type.builtin", ["entity.name.type", "support.type.primitive"]], - ["type.self", ["entity.name.type.parameter.self"]], - ["type.param", ["entity.name.type.parameter", "entity.name.type.param.rust"]], - ["type.lifetime", ["entity.name.type.lifetime", "entity.name.lifetime.rust"]], - - ["literal.byte", ["constant.character.byte"]], - ["literal.char", ["constant.character.rust"]], - ["numeric_literal", ["constant.numeric"]], - - ["comment", ["comment"]], - ["string_literal", ["string.quoted"]], - ["attribute", ["meta.attribute.rust"]], - - ["keyword", ["keyword"]], - ["keyword.unsafe", ["keyword.other.unsafe"]], - ["keyword.control", ["keyword.control"]], -]); - -function randomU32Numbers(seed: number) { - let random = seed | 0; - return () => { - random ^= random << 13; - random ^= random >> 17; - random ^= random << 5; - random |= 0; - return random; - }; -} - -function hashString(str: string): number { - let res = 0; - for (let i = 0; i < str.length; ++i) { - const c = str.codePointAt(i)!; - res = (res * 31 + c) & ~0; - } - return res; -} diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 7ba16120c3..4f3b89f446 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -7,7 +7,6 @@ import * as commands from './commands'; import { activateInlayHints } from './inlay_hints'; import { activateStatusDisplay } from './status_display'; import { Ctx } from './ctx'; -import { activateHighlighting } from './highlighting'; import { Config, NIGHTLY_TAG } from './config'; import { log, assert } from './util'; import { PersistentState } from './persistent_state'; @@ -97,9 +96,6 @@ export async function activate(context: vscode.ExtensionContext) { activateStatusDisplay(ctx); - if (!ctx.config.highlightingSemanticTokens) { - activateHighlighting(ctx); - } activateInlayHints(ctx); vscode.workspace.onDidChangeConfiguration(