jvikstrom updated this revision to Diff 214813.
jvikstrom added a comment.

Lazy load the best theme rule for a scope.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

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
@@ -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,20 @@
       ]
     ];
     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 : 'c.b', foreground : '1'},
+      {scope : 'a', foreground : '2'},
+      {scope : 'a.b', foreground : '3'},
+      {scope : 'a', foreground : '4'},
+      {scope : 'c.b.a', foreground : '5'},
+    ];
+    const tm = new SM.ThemeRules(rules);
+    assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+    assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+    assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+    assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
   });
 });
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
@@ -47,6 +47,8 @@
   // 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.
+  themeRules: ThemeRules;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
     // Extend the ClientCapabilities type and add semantic highlighting
     // capability to the object.
@@ -58,6 +60,18 @@
     };
   }
 
+  async loadCurrentTheme() {
+    const name =
+        vscode.workspace.getConfiguration('workbench').get('colorTheme');
+    if (typeof name != 'string') {
+      console.warn('The current theme name is not a string, is:' +
+                       (typeof name) + ', value: ',
+                   name);
+      return;
+    }
+    this.themeRules = await loadTheme(name);
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
              documentSelector: vscodelc.DocumentSelector|undefined) {
     // The semantic highlighting capability information is in the capabilities
@@ -68,6 +82,7 @@
     if (!serverCapabilities.semanticHighlighting)
       return;
     this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+    this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,8 +116,31 @@
   foreground: string;
 }
 
+export class ThemeRules {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map<string, TokenColorRule> = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = 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.rules.forEach((rule) => {
+      if (rule.scope.length <= scope.length &&
+          scope.substr(0, rule.scope.length) === 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[]> {
+async function loadTheme(themeName: string): Promise<ThemeRules> {
   const extension =
       vscode.extensions.all.find((extension: vscode.Extension<any>) => {
         const contribs = extension.packageJSON.contributes;
@@ -118,7 +156,8 @@
 
   const themeInfo = extension.packageJSON.contributes.themes.find(
       (theme: any) => theme.id === themeName || theme.label === themeName);
-  return parseThemeFile(path.join(extension.extensionPath, themeInfo.path));
+  return new ThemeRules(
+      await parseThemeFile(path.join(extension.extensionPath, themeInfo.path)));
 }
 
 /**
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to