diff options
Diffstat (limited to 'clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts')
-rw-r--r-- | clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts | 109 |
1 files changed, 104 insertions, 5 deletions
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 index a8b39306eb4..eab555d4587 100644 --- 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 @@ -1,13 +1,15 @@ import * as assert from 'assert'; import * as path from 'path'; +import * as vscode from 'vscode'; -import * as SM from '../src/semantic-highlighting'; +import * as semanticHighlighting from '../src/semantic-highlighting'; suite('SemanticHighlighting Tests', () => { test('Parses arrays of textmate themes.', async () => { const themePath = path.join(__dirname, '../../test/assets/includeTheme.jsonc'); - const scopeColorRules = await SM.parseThemeFile(themePath); + const scopeColorRules = + await semanticHighlighting.parseThemeFile(themePath); const getScopeRule = (scope: string) => scopeColorRules.find((v) => v.scope === scope); assert.equal(scopeColorRules.length, 3); @@ -32,8 +34,9 @@ suite('SemanticHighlighting Tests', () => { {character : 10, scopeIndex : 0, length : 1} ] ]; - testCases.forEach((testCase, i) => assert.deepEqual( - SM.decodeTokens(testCase), expected[i])); + testCases.forEach( + (testCase, i) => assert.deepEqual( + semanticHighlighting.decodeTokens(testCase), expected[i])); }); test('ScopeRules overrides for more specific themes', () => { const rules = [ @@ -44,7 +47,7 @@ suite('SemanticHighlighting Tests', () => { {scope : 'storage', foreground : '5'}, {scope : 'variable.other.parameter', foreground : '6'}, ]; - const tm = new SM.ThemeRuleMatcher(rules); + const tm = new semanticHighlighting.ThemeRuleMatcher(rules); assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope, 'variable.other'); assert.deepEqual(tm.getBestThemeRule('storage.static').scope, @@ -57,4 +60,100 @@ suite('SemanticHighlighting Tests', () => { assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope, 'variable.other.parameter'); }); + test('Colorizer groups decorations correctly', async () => { + const scopeTable = [ + [ 'variable' ], [ 'entity.type.function' ], + [ 'entity.type.function.method' ] + ]; + // Create the scope source ranges the highlightings should be highlighted + // at. Assumes the scopes used are the ones in the "scopeTable" variable. + const createHighlightingScopeRanges = + (highlightingLines: + 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(() => []); + highlightingLines.forEach((line) => { + line.tokens.forEach((token) => { + scopeRanges[token.scopeIndex].push(new vscode.Range( + new vscode.Position(line.line, token.character), + new vscode.Position(line.line, + token.character + token.length))); + }); + }); + return scopeRanges; + }; + + class MockHighlighter extends semanticHighlighting.Highlighter { + applicationUriHistory: string[] = []; + // Override to make the highlighting calls accessible to the test. Also + // makes the test not depend on visible text editors. + applyHighlights(fileUri: string) { + this.applicationUriHistory.push(fileUri); + } + // Override to make it accessible from the test. + getDecorationRanges(fileUri: string) { + return super.getDecorationRanges(fileUri); + } + // Override to make tests not depend on visible text editors. + getVisibleTextEditorUris() { return [ 'file1', 'file2' ]; } + } + const highlighter = new MockHighlighter(scopeTable); + const tm = new semanticHighlighting.ThemeRuleMatcher([ + {scope : 'variable', foreground : '1'}, + {scope : 'entity.type', foreground : '2'}, + ]); + // Recolorizes when initialized. + highlighter.highlight('file1', []); + assert.deepEqual(highlighter.applicationUriHistory, [ 'file1' ]); + highlighter.initialize(tm); + assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1' ]); + // Groups decorations into the scopes used. + let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [ + { + line : 1, + tokens : [ + {character : 1, length : 2, scopeIndex : 1}, + {character : 10, length : 2, scopeIndex : 2}, + ] + }, + { + line : 2, + tokens : [ + {character : 3, length : 2, scopeIndex : 1}, + {character : 6, length : 2, scopeIndex : 1}, + {character : 8, length : 2, scopeIndex : 2}, + ] + }, + ]; + + highlighter.highlight('file1', highlightingsInLine); + assert.deepEqual(highlighter.applicationUriHistory, + [ 'file1', 'file1', 'file1' ]); + assert.deepEqual(highlighter.getDecorationRanges('file1'), + createHighlightingScopeRanges(highlightingsInLine)); + // Keeps state separate between files. + const highlightingsInLine1: + semanticHighlighting.SemanticHighlightingLine = { + line : 1, + tokens : [ + {character : 2, length : 1, scopeIndex : 0}, + ] + }; + highlighter.highlight('file2', [ highlightingsInLine1 ]); + assert.deepEqual(highlighter.applicationUriHistory, + [ 'file1', 'file1', 'file1', 'file2' ]); + assert.deepEqual(highlighter.getDecorationRanges('file2'), + createHighlightingScopeRanges([ highlightingsInLine1 ])); + // Does full colorizations. + highlighter.highlight('file1', [ highlightingsInLine1 ]); + assert.deepEqual(highlighter.applicationUriHistory, + [ 'file1', 'file1', 'file1', 'file2', 'file1' ]); + // After the incremental update to line 1, the old highlightings at line 1 + // will no longer exist in the array. + assert.deepEqual( + highlighter.getDecorationRanges('file1'), + createHighlightingScopeRanges( + [ highlightingsInLine1, ...highlightingsInLine.slice(1) ])); + }); }); |