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? --- editors/code/package-lock.json | 10 +++++++++ editors/code/package.json | 2 ++ editors/code/src/highlighting.ts | 45 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 3 deletions(-) (limited to 'editors/code') diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 29cd260a4..6b3a12f91 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -36,6 +36,11 @@ "integrity": "sha512-Ja7d4s0qyGFxjGeDq5S7Si25OFibSAHUi6i17UWnwNnpitADN7hah9q0Tl25gxuV5R1u2Bx+np6w4LHXfHyj/g==", "dev": true }, + "@types/seedrandom": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.28.tgz", + "integrity": "sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA==" + }, "agent-base": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", @@ -984,6 +989,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "seedrandom": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz", + "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==" + }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index cde5fbcb8..d8ba914f5 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -31,11 +31,13 @@ "singleQuote": true }, "dependencies": { + "seedrandom": "^3.0.1", "vscode-languageclient": "^5.3.0-next.4" }, "devDependencies": { "@types/mocha": "^5.2.6", "@types/node": "^10.14.5", + "@types/seedrandom": "^2.4.28", "prettier": "^1.17.0", "shx": "^0.3.1", "tslint": "^5.16.0", diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 8389d94b8..4597db08f 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -1,3 +1,4 @@ +import seedrandom = require('seedrandom'); import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; @@ -6,6 +7,20 @@ import { Server } from './server'; export interface Decoration { range: lc.Range; tag: string; + id?: string; +} + +// Based on this HSL-based color generator: https://gist.github.com/bendc/76c48ce53299e6078a76 +function fancify(seed: string, shade: 'light' | 'dark') { + const random = seedrandom(seed); + const randomInt = (min: number, max: number) => { + return Math.floor(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}%)`; } export class Highlighter { @@ -76,6 +91,8 @@ export class Highlighter { } const byTag: Map = new Map(); + const colorfulIdents: Map = new Map(); + for (const tag of this.decorations.keys()) { byTag.set(tag, []); } @@ -84,9 +101,23 @@ export class Highlighter { if (!byTag.get(d.tag)) { continue; } - byTag - .get(d.tag)! - .push(Server.client.protocol2CodeConverter.asRange(d.range)); + + if (d.id) { + if (!colorfulIdents.has(d.id)) { + colorfulIdents.set(d.id, []); + } + colorfulIdents + .get(d.id)! + .push( + Server.client.protocol2CodeConverter.asRange(d.range) + ); + } else { + byTag + .get(d.tag)! + .push( + Server.client.protocol2CodeConverter.asRange(d.range) + ); + } } for (const tag of byTag.keys()) { @@ -96,5 +127,13 @@ export class Highlighter { const ranges = byTag.get(tag)!; editor.setDecorations(dec, ranges); } + + for (const [hash, ranges] of colorfulIdents.entries()) { + const dec = vscode.window.createTextEditorDecorationType({ + light: { color: fancify(hash, 'light') }, + dark: { color: fancify(hash, 'dark') } + }); + editor.setDecorations(dec, ranges); + } } } -- 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 --- editors/code/package.json | 5 +++++ editors/code/src/config.ts | 7 +++++++ editors/code/src/highlighting.ts | 11 ++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) (limited to 'editors/code') diff --git a/editors/code/package.json b/editors/code/package.json index d8ba914f5..05c808394 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -164,6 +164,11 @@ "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.showWorkspaceLoadedNotification": { "type": "boolean", "default": true, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 481a5e5f1..8d73a6b34 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -15,6 +15,7 @@ export interface CargoWatchOptions { export class Config { public highlightingOn = true; + public rainbowHighlightingOn = false; public enableEnhancedTyping = true; public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server'; public showWorkspaceLoadedNotification = true; @@ -39,6 +40,12 @@ export class Config { this.highlightingOn = config.get('highlightingOn') as boolean; } + if (config.has('rainbowHighlightingOn')) { + this.rainbowHighlightingOn = config.get( + 'rainbowHighlightingOn' + ) as boolean; + } + if (config.has('showWorkspaceLoadedNotification')) { this.showWorkspaceLoadedNotification = config.get( 'showWorkspaceLoadedNotification' diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 4597db08f..52a0bd4bb 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -7,7 +7,7 @@ import { Server } from './server'; export interface Decoration { range: lc.Range; tag: string; - id?: string; + bindingHash?: string; } // Based on this HSL-based color generator: https://gist.github.com/bendc/76c48ce53299e6078a76 @@ -92,6 +92,7 @@ export class Highlighter { const byTag: Map = new Map(); const colorfulIdents: Map = new Map(); + const rainbowTime = Server.config.rainbowHighlightingOn; for (const tag of this.decorations.keys()) { byTag.set(tag, []); @@ -102,12 +103,12 @@ export class Highlighter { continue; } - if (d.id) { - if (!colorfulIdents.has(d.id)) { - colorfulIdents.set(d.id, []); + if (rainbowTime && d.bindingHash) { + if (!colorfulIdents.has(d.bindingHash)) { + colorfulIdents.set(d.bindingHash, []); } colorfulIdents - .get(d.id)! + .get(d.bindingHash)! .push( Server.client.protocol2CodeConverter.asRange(d.range) ); -- cgit v1.2.3