jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Maps an array of TM scopes to the most specific scope that is added. Needed to 
have fast access to a rule when doing the actual coloring.


Repository:
  rG LLVM Github Monorepo

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
@@ -11,8 +11,23 @@
     const getScopeRule = (scope: string) =>
         scopeColorRules.find((v) => v.scope === scope);
     assert.equal(scopeColorRules.length, 3);
-    assert.deepEqual(getScopeRule('a'), {scope : 'a', textColor : '#fff'});
-    assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
-    assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
+    assert.deepEqual(getScopeRule('a'), {scope : 'a', foreground : '#fff'});
+    assert.deepEqual(getScopeRule('b'), {scope : 'b', foreground : '#000'});
+    assert.deepEqual(getScopeRule('c'), {scope : 'c', foreground : '#bcd'});
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+    const scopes = [ 'a.b.c.d', 'a.b.f', 'a' ];
+    const rules = [
+      {scope : 'a.b.c', foreground : '1'},
+      {scope : 'a.b', foreground : '2'},
+      {scope : 'a.b.c.d', foreground : '3'},
+      {scope : 'a', foreground : '4'},
+    ];
+
+    const tm = new TM.ScopeRules(scopes);
+    rules.forEach((r) => tm.addRule(r));
+    assert.deepEqual(tm.getRule(0), rules[2]);
+    assert.deepEqual(tm.getRule(1), rules[1]);
+    assert.deepEqual(tm.getRule(2), rules[3]);
   });
 });
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
@@ -12,6 +12,39 @@
   foreground: string;
 }
 
+export class ScopeRules {
+  // The TextMate scopes that should be mapped to a color.
+  private scopes: string[];
+  // Contains the current best matching scope for the scope at the 
corresponding
+  // index.
+  private scopeRules: TokenColorRule[];
+
+  constructor(scopes: string[]) {
+    this.scopes = scopes;
+    this.scopeRules =
+        this.scopes.map(() => ({scope : '', foreground : '#000'}));
+  }
+
+  addRule(rule: TokenColorRule) {
+    // Find the associated clangd scope(s) index for this scope. A scope being 
a
+    // possible candidate means that the clangd scope must have the rule's 
scope
+    // as a prefix.
+    const allCandidates =
+        this.scopes.map((s, i) => ({s : s, i : i}))
+            .filter(({s}) => s.substr(0, rule.scope.length) === rule.scope);
+    // If this scope is more specific than any of current scopes for the clangd
+    // scopes it should be replaced. As both options are prefixes of the clangd
+    // scope it's enough to compare lengths.
+    allCandidates.forEach(({i}) => {
+      if (rule.scope.length > this.scopeRules[i].scope.length) {
+        this.scopeRules[i] = rule;
+      }
+    });
+  }
+
+  getRule(idx: number) { return this.scopeRules[idx]; }
+}
+
 // Get all token color rules provided by the theme.
 function loadTheme(themeName: string): Promise<TokenColorRule[]> {
   const extension =


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
@@ -11,8 +11,23 @@
     const getScopeRule = (scope: string) =>
         scopeColorRules.find((v) => v.scope === scope);
     assert.equal(scopeColorRules.length, 3);
-    assert.deepEqual(getScopeRule('a'), {scope : 'a', textColor : '#fff'});
-    assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
-    assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
+    assert.deepEqual(getScopeRule('a'), {scope : 'a', foreground : '#fff'});
+    assert.deepEqual(getScopeRule('b'), {scope : 'b', foreground : '#000'});
+    assert.deepEqual(getScopeRule('c'), {scope : 'c', foreground : '#bcd'});
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+    const scopes = [ 'a.b.c.d', 'a.b.f', 'a' ];
+    const rules = [
+      {scope : 'a.b.c', foreground : '1'},
+      {scope : 'a.b', foreground : '2'},
+      {scope : 'a.b.c.d', foreground : '3'},
+      {scope : 'a', foreground : '4'},
+    ];
+
+    const tm = new TM.ScopeRules(scopes);
+    rules.forEach((r) => tm.addRule(r));
+    assert.deepEqual(tm.getRule(0), rules[2]);
+    assert.deepEqual(tm.getRule(1), rules[1]);
+    assert.deepEqual(tm.getRule(2), rules[3]);
   });
 });
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
@@ -12,6 +12,39 @@
   foreground: string;
 }
 
+export class ScopeRules {
+  // The TextMate scopes that should be mapped to a color.
+  private scopes: string[];
+  // Contains the current best matching scope for the scope at the corresponding
+  // index.
+  private scopeRules: TokenColorRule[];
+
+  constructor(scopes: string[]) {
+    this.scopes = scopes;
+    this.scopeRules =
+        this.scopes.map(() => ({scope : '', foreground : '#000'}));
+  }
+
+  addRule(rule: TokenColorRule) {
+    // Find the associated clangd scope(s) index for this scope. A scope being a
+    // possible candidate means that the clangd scope must have the rule's scope
+    // as a prefix.
+    const allCandidates =
+        this.scopes.map((s, i) => ({s : s, i : i}))
+            .filter(({s}) => s.substr(0, rule.scope.length) === rule.scope);
+    // If this scope is more specific than any of current scopes for the clangd
+    // scopes it should be replaced. As both options are prefixes of the clangd
+    // scope it's enough to compare lengths.
+    allCandidates.forEach(({i}) => {
+      if (rule.scope.length > this.scopeRules[i].scope.length) {
+        this.scopeRules[i] = rule;
+      }
+    });
+  }
+
+  getRule(idx: number) { return this.scopeRules[idx]; }
+}
+
 // Get all token color rules provided by the theme.
 function loadTheme(themeName: string): Promise<TokenColorRule[]> {
   const extension =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to