Page MenuHomePhabricator

D65998.id214613.diff
No OneTemporary

File Metadata

Created
Jan 24 2020, 4:30 PM

D65998.id214613.diff

diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package.json b/clang-tools-extra/clangd/clients/clangd-vscode/package.json
--- a/clang-tools-extra/clangd/clients/clangd-vscode/package.json
+++ b/clang-tools-extra/clangd/clients/clangd-vscode/package.json
@@ -38,7 +38,8 @@
"dependencies": {
"jsonc-parser": "^2.1.0",
"vscode-languageclient": "^5.3.0-next.6",
- "vscode-languageserver": "^5.3.0-next.6"
+ "vscode-languageserver": "^5.3.0-next.6",
+ "vscode-languageserver-types": "^3.14.0"
},
"devDependencies": {
"@types/mocha": "^2.2.32",
diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts b/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
--- a/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ b/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -2,6 +2,94 @@
import * as jsonc from "jsonc-parser";
import * as path from 'path';
import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+import * as vscodelct from 'vscode-languageserver-types';
+
+// Parameters for the semantic highlighting (server-side) push notification.
+interface SemanticHighlightingParams {
+ // The text document that has to be decorated with the semantic highlighting
+ // information.
+ textDocument: vscodelct.VersionedTextDocumentIdentifier;
+ // An array of semantic highlighting information.
+ lines: SemanticHighlightingInformation[];
+}
+
+// Contains the highlighting information for a specified line.
+interface SemanticHighlightingInformation {
+ // The zero-based line position in the text document.
+ line: number;
+ // A base64 encoded string representing every single highlighted characters
+ // with its start position, length and the "lookup table" index of of the
+ // semantic highlighting Text Mate scopes.
+ tokens?: string;
+}
+
+// A single SemanticHighlightingToken that clangd sent.
+interface SemanticHighlightingToken {
+ // Start column for this token.
+ character: number;
+ // Length of the token.
+ length: number;
+ // The TextMate scope index to the clangd scopes.
+ scope: number;
+}
+
+// Language server push notification providing the semantic highlighting
+// information for a text document.
+export const NotificationType =
+ new vscodelc.NotificationType<SemanticHighlightingParams, void>(
+ 'textDocument/semanticHighlighting');
+
+// The feature that should be registered in the vscode lsp for enabling
+// experimental semantic highlighting.
+export class SemanticHighlightingFeature implements vscodelc.StaticFeature {
+ // The TextMate scope lookup table. A token with scope index i has the scopes
+ // on index i in the lookup table.
+ scopeLookupTable: string[][];
+ fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
+ // Extend the ClientCapabilities type and add semantic highlighting
+ // capability to the object.
+ const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities&
+ {semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} =
+ capabilities.textDocument;
+ textDocumentCapabilities.semanticHighlightingCapabilities = {
+ semanticHighlighting : true,
+ };
+ }
+
+ initialize(capabilities: vscodelc.ServerCapabilities,
+ documentSelector: vscodelc.DocumentSelector|undefined) {
+ // The semantic highlighting capability information is in the capabilities
+ // object but to access the data we must first extend the ServerCapabilities
+ // type.
+ const serverCapabilities: vscodelc.ServerCapabilities&
+ {semanticHighlighting?: {scopes : string[][]}} = capabilities;
+ if (!serverCapabilities.semanticHighlighting)
+ return;
+ this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+ }
+
+ handleNotification(params: SemanticHighlightingParams) {}
+}
+
+// Converts a string of base64 encoded tokens into the corresponding array of
+// HighlightingTokens.
+export function decodeTokens(tokens: string): SemanticHighlightingToken[] {
+ const scopeMask = 0xFFFF;
+ const lenShift = 0x10;
+ const uint32Size = 4;
+ const buf = Buffer.from(tokens, 'base64');
+ const retTokens = [];
+ for (let i = 0, end = buf.length / uint32Size; i < end; i += 2) {
+ const start = buf.readUInt32BE(i * uint32Size);
+ const lenKind = buf.readUInt32BE((i + 1) * uint32Size);
+ const scope = lenKind & scopeMask;
+ const len = lenKind >>> lenShift;
+ retTokens.push({character : start, scope : scope, length : len});
+ }
+
+ return retTokens;
+}
// A rule for how to color TextMate scopes.
interface TokenColorRule {
diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
--- a/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ b/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -3,7 +3,7 @@
import * as TM from '../src/semantic-highlighting';
-suite('TextMate Tests', () => {
+suite('SemanticHighlighting Tests', () => {
test('Parses arrays of textmate themes.', async () => {
const themePath =
path.join(__dirname, '../../test/assets/includeTheme.jsonc');
@@ -15,4 +15,24 @@
assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
});
+ test('Decodes tokens correctly', () => {
+ const testCases: string[] = [
+ 'AAAAAAABAAA=', 'AAAAAAADAAkAAAAEAAEAAA==',
+ 'AAAAAAADAAkAAAAEAAEAAAAAAAoAAQAA'
+ ];
+ const expected = [
+ [ {character : 0, scope : 0, length : 1} ],
+ [
+ {character : 0, scope : 9, length : 3},
+ {character : 4, scope : 0, length : 1}
+ ],
+ [
+ {character : 0, scope : 9, length : 3},
+ {character : 4, scope : 0, length : 1},
+ {character : 10, scope : 0, length : 1}
+ ]
+ ];
+ testCases.forEach((testCase, i) => assert.deepEqual(
+ TM.decodeTokens(testCase), expected[i]));
+ });
});

Event Timeline