nridge updated this revision to Diff 230586. nridge added a comment. Clean up patch a bit and update tests as well
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D67537/new/ https://reviews.llvm.org/D67537 Files: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts =================================================================== --- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts +++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts @@ -72,16 +72,25 @@ semanticHighlighting.SemanticHighlightingLine[]) => { // Initialize the scope ranges list to the correct size. Otherwise // scopes that don't have any highlightings are missed. - let scopeRanges: vscode.Range[][] = scopeTable.map(() => []); + let tokenRanges: vscode.Range[][] = scopeTable.map(() => []); + let inactiveRanges: vscode.Range[] = []; highlightingLines.forEach((line) => { line.tokens.forEach((token) => { - scopeRanges[token.scopeIndex].push(new vscode.Range( + tokenRanges[token.scopeIndex].push(new vscode.Range( new vscode.Position(line.line, token.character), new vscode.Position(line.line, token.character + token.length))); }); + if (line.isInactive) { + inactiveRanges.push(new vscode.Range( + new vscode.Position(line.line, 0), + new vscode.Position(line.line, 0) + )); + } }); - return scopeRanges; + let result : semanticHighlighting.DecorationRanges = + { tokenRanges, inactiveRanges }; + return result; }; const fileUri1 = vscode.Uri.parse('file:///file1'); @@ -121,7 +130,8 @@ tokens : [ {character : 1, length : 2, scopeIndex : 1}, {character : 10, length : 2, scopeIndex : 2}, - ] + ], + isInactive: false }, { line : 2, @@ -129,7 +139,8 @@ {character : 3, length : 2, scopeIndex : 1}, {character : 6, length : 2, scopeIndex : 1}, {character : 8, length : 2, scopeIndex : 2}, - ] + ], + isInactive: true }, ]; @@ -144,7 +155,8 @@ line : 1, tokens : [ {character : 2, length : 1, scopeIndex : 0}, - ] + ], + isInactive: false }; highlighter.highlight(fileUri2, [ highlightingsInLine1 ]); assert.deepEqual( @@ -167,7 +179,8 @@ // Closing a text document removes all highlightings for the file and no // other files. highlighter.removeFileHighlightings(fileUri1); - assert.deepEqual(highlighter.getDecorationRanges(fileUri1), []); + assert.deepEqual(highlighter.getDecorationRanges(fileUri1), + { tokenRanges: [], inactiveRanges: [] }); assert.deepEqual(highlighter.getDecorationRanges(fileUri2), createHighlightingScopeRanges([ highlightingsInLine1 ])); }); Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts =================================================================== --- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts +++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts @@ -23,6 +23,8 @@ // with its start position, length and the "lookup table" index of of the // semantic highlighting Text Mate scopes. tokens?: string; + // Whether the line is part of an inactive preprocessor branch. + isInactive?: boolean; } // A SemanticHighlightingToken decoded from the base64 data sent by clangd. @@ -40,6 +42,13 @@ line: number; // All SemanticHighlightingTokens on the line. tokens: SemanticHighlightingToken[]; + // Whether the line is part of an inactive preprocessor branch. + isInactive: boolean; +} + +export interface DecorationRanges { + tokenRanges: vscode.Range[][], + inactiveRanges: vscode.Range[] } // Language server push notification providing the semantic highlighting @@ -122,7 +131,10 @@ handleNotification(params: SemanticHighlightingParams) { const lines: SemanticHighlightingLine[] = params.lines.map( - (line) => ({line : line.line, tokens : decodeTokens(line.tokens)})); + (line) => ({ + line: line.line, tokens: decodeTokens(line.tokens), + isInactive: line.isInactive || false + })); this.highlighter.highlight(vscode.Uri.parse(params.textDocument.uri), lines); } @@ -161,6 +173,7 @@ // SemanticHighlightingToken with scopeIndex i should have the decoration at // index i in this list. private decorationTypes: vscode.TextEditorDecorationType[] = []; + private inactiveCodeDecorationType: vscode.TextEditorDecorationType; // The clangd TextMate scope lookup table. private scopeLookupTable: string[][]; constructor(scopeLookupTable: string[][]) { @@ -192,6 +205,18 @@ }; return vscode.window.createTextEditorDecorationType(options); }); + this.inactiveCodeDecorationType = vscode.window.createTextEditorDecorationType({ + isWholeLine: true, + // FIXME: Avoid hardcoding these colors. + light: { + color: "rgb(100, 100, 100)", + backgroundColor: "rgba(220, 220, 220, 0.3)" + }, + dark: { + color: "rgb(100, 100, 100)", + backgroundColor: "rgba(18, 18, 18, 0.3)" + } + }); this.getVisibleTextEditorUris().forEach((fileUri) => this.applyHighlights(fileUri)); } @@ -224,11 +249,13 @@ // TextEditorDecorationType are very expensive to create (which makes // incremental updates infeasible). For this reason one // TextEditorDecorationType is used per scope. - const ranges = this.getDecorationRanges(fileUri); + const decorationRanges = this.getDecorationRanges(fileUri); vscode.window.visibleTextEditors.forEach((e) => { if (e.document.uri.toString() !== fileUriStr) return; - this.decorationTypes.forEach((d, i) => e.setDecorations(d, ranges[i])); + this.decorationTypes.forEach( + (d, i) => e.setDecorations(d, decorationRanges.tokenRanges[i])); + e.setDecorations(this.inactiveCodeDecorationType, decorationRanges.inactiveRanges); }); } @@ -246,24 +273,30 @@ // Returns the ranges that should be used when decorating. Index i in the // range array has the decoration type at index i of this.decorationTypes. - protected getDecorationRanges(fileUri: vscode.Uri): vscode.Range[][] { + protected getDecorationRanges(fileUri: vscode.Uri): DecorationRanges { const fileUriStr = fileUri.toString(); if (!this.files.has(fileUriStr)) // this.files should always have an entry for fileUri if we are here. But // if there isn't one we don't want to crash the extension. This is also // useful for tests. - return []; + return { tokenRanges: [], inactiveRanges: []}; const lines: SemanticHighlightingLine[] = Array.from(this.files.get(fileUriStr).values()); const decorations: vscode.Range[][] = this.decorationTypes.map(() => []); + const inactiveRanges: vscode.Range[] = []; lines.forEach((line) => { line.tokens.forEach((token) => { decorations[token.scopeIndex].push(new vscode.Range( new vscode.Position(line.line, token.character), new vscode.Position(line.line, token.character + token.length))); }); + if (line.isInactive) { + inactiveRanges.push(new vscode.Range( + new vscode.Position(line.line, 0), + new vscode.Position(line.line, 0))); + } }); - return decorations; + return { tokenRanges: decorations, inactiveRanges }; } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits