[clang-tools-extra] r368834 - [clangd] Loading TokenColorRules as a class mapping the rules to their associated clangd TextMate scope index.
Johan Vikstrom via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 14 05:11:59 PDT 2019
Author: jvikstrom
Date: Wed Aug 14 05:11:58 2019
New Revision: 368834
URL: http://llvm.org/viewvc/llvm-project?rev=368834&view=rev
Log:
[clangd] Loading TokenColorRules as a class mapping the rules to their associated clangd TextMate scope index.
Summary: Loads a mapping of the clangd scope lookup table scopes to the most specific rule with the highest "precedence" on initialize. Preprocesses into a class so it's simple/fast to access when doing the actual coloring later.
Reviewers: hokein, ilya-biryukov
Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D65856
Modified:
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
Modified: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts?rev=368834&r1=368833&r2=368834&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts (original)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts Wed Aug 14 05:11:58 2019
@@ -47,6 +47,8 @@ export class SemanticHighlightingFeature
// The TextMate scope lookup table. A token with scope index i has the scopes
// on index i in the lookup table.
scopeLookupTable: string[][];
+ // The rules for the current theme.
+ themeRuleMatcher: ThemeRuleMatcher;
fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
// Extend the ClientCapabilities type and add semantic highlighting
// capability to the object.
@@ -58,6 +60,12 @@ export class SemanticHighlightingFeature
};
}
+ async loadCurrentTheme() {
+ this.themeRuleMatcher = new ThemeRuleMatcher(
+ await loadTheme(vscode.workspace.getConfiguration('workbench')
+ .get<string>('colorTheme')));
+ }
+
initialize(capabilities: vscodelc.ServerCapabilities,
documentSelector: vscodelc.DocumentSelector|undefined) {
// The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@ export class SemanticHighlightingFeature
if (!serverCapabilities.semanticHighlighting)
return;
this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+ this.loadCurrentTheme();
}
handleNotification(params: SemanticHighlightingParams) {}
@@ -101,6 +110,39 @@ interface TokenColorRule {
foreground: string;
}
+export class ThemeRuleMatcher {
+ // The rules for the theme.
+ private themeRules: TokenColorRule[];
+ // A cache for the getBestThemeRule function.
+ private bestRuleCache: Map<string, TokenColorRule> = new Map();
+ constructor(rules: TokenColorRule[]) { this.themeRules = rules; }
+ // Returns the best rule for a scope.
+ getBestThemeRule(scope: string): TokenColorRule {
+ if (this.bestRuleCache.has(scope))
+ return this.bestRuleCache.get(scope);
+ let bestRule: TokenColorRule = {scope : '', foreground : ''};
+ this.themeRules.forEach((rule) => {
+ // The best rule for a scope is the rule that is the longest prefix of the
+ // scope (unless a perfect match exists in which case the perfect match is
+ // the best). If a rule is not a prefix and we tried to match with longest
+ // common prefix instead variables would be highlighted as `less`
+ // variables when using Light+ (as variable.other would be matched against
+ // variable.other.less in this case). Doing common prefix matching also
+ // means we could match variable.cpp to variable.css if variable.css
+ // occurs before variable in themeRules.
+ // FIXME: This is not defined in the TextMate standard (it is explicitly
+ // undefined, https://macromates.com/manual/en/scope_selectors). Might
+ // want to rank some other way.
+ if (scope.startsWith(rule.scope) &&
+ rule.scope.length > bestRule.scope.length)
+ // This rule matches and is more specific than the old rule.
+ bestRule = rule;
+ });
+ this.bestRuleCache.set(scope, bestRule);
+ return bestRule;
+ }
+}
+
// Get all token color rules provided by the theme.
function loadTheme(themeName: string): Promise<TokenColorRule[]> {
const extension =
Modified: clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts?rev=368834&r1=368833&r2=368834&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts (original)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts Wed Aug 14 05:11:58 2019
@@ -1,13 +1,13 @@
import * as assert from 'assert';
import * as path from 'path';
-import * as TM from '../src/semantic-highlighting';
+import * as SM 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 TM.parseThemeFile(themePath);
+ const scopeColorRules = await SM.parseThemeFile(themePath);
const getScopeRule = (scope: string) =>
scopeColorRules.find((v) => v.scope === scope);
assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,28 @@ suite('SemanticHighlighting Tests', () =
]
];
testCases.forEach((testCase, i) => assert.deepEqual(
- TM.decodeTokens(testCase), expected[i]));
+ SM.decodeTokens(testCase), expected[i]));
+ });
+ test('ScopeRules overrides for more specific themes', () => {
+ const rules = [
+ {scope : 'variable.other.css', foreground : '1'},
+ {scope : 'variable.other', foreground : '2'},
+ {scope : 'storage', foreground : '3'},
+ {scope : 'storage.static', foreground : '4'},
+ {scope : 'storage', foreground : '5'},
+ {scope : 'variable.other.parameter', foreground : '6'},
+ ];
+ const tm = new SM.ThemeRuleMatcher(rules);
+ assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope,
+ 'variable.other');
+ assert.deepEqual(tm.getBestThemeRule('storage.static').scope,
+ 'storage.static');
+ assert.deepEqual(
+ tm.getBestThemeRule('storage'),
+ rules[2]); // Match the first element if there are duplicates.
+ assert.deepEqual(tm.getBestThemeRule('variable.other.parameter').scope,
+ 'variable.other.parameter');
+ assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
+ 'variable.other.parameter');
});
});
More information about the cfe-commits
mailing list