[clang-tools-extra] r368136 - [clangd] Added a TextMate theme parser to the vscode extension.

Johan Vikstrom via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 7 01:48:52 PDT 2019


Author: jvikstrom
Date: Wed Aug  7 01:48:52 2019
New Revision: 368136

URL: http://llvm.org/viewvc/llvm-project?rev=368136&view=rev
Log:
[clangd] Added a TextMate theme parser to the vscode extension.

Summary:
Adds a TextMate parser module to the vscode extension. It parses a theme into an array of a pair of TextMate scopes and text colors.

Reviewers: hokein, ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D65738

Added:
    clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
    clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/
    clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc
    clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc
    clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
Modified:
    clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json

Modified: clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json?rev=368136&r1=368135&r2=368136&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json (original)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json Wed Aug  7 01:48:52 2019
@@ -36,14 +36,15 @@
         "test": "node ./node_modules/vscode/bin/test"
     },
     "dependencies": {
+        "jsonc-parser": "^2.1.0",
         "vscode-languageclient": "^5.3.0-next.6",
         "vscode-languageserver": "^5.3.0-next.6"
     },
     "devDependencies": {
         "@types/mocha": "^2.2.32",
         "@types/node": "^6.0.40",
-        "mocha": "^5.2.0",
         "clang-format": "1.2.4",
+        "mocha": "^5.2.0",
         "typescript": "^2.0.3",
         "vscode": "^1.1.0"
     },

Added: 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=368136&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts (added)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts Wed Aug  7 01:48:52 2019
@@ -0,0 +1,102 @@
+import * as fs from 'fs';
+import * as jsonc from "jsonc-parser";
+import * as path from 'path';
+import * as vscode from 'vscode';
+
+// A rule for how to color TextMate scopes.
+interface TokenColorRule {
+  // A TextMate scope that specifies the context of the token, e.g.
+  // "entity.name.function.cpp".
+  scope: string;
+  // foreground is the color tokens of this scope should have.
+  foreground: string;
+}
+
+// Get all token color rules provided by the theme.
+function loadTheme(themeName: string): Promise<TokenColorRule[]> {
+  const extension =
+      vscode.extensions.all.find((extension: vscode.Extension<any>) => {
+        const contribs = extension.packageJSON.contributes;
+        if (!contribs || !contribs.themes)
+          return false;
+        return contribs.themes.some((theme: any) => theme.id === themeName ||
+                                                    theme.label === themeName);
+      });
+
+  if (!extension) {
+    return Promise.reject('Could not find a theme with name: ' + themeName);
+  }
+
+  const themeInfo = extension.packageJSON.contributes.themes.find(
+      (theme: any) => theme.id === themeName || theme.label === themeName);
+  return parseThemeFile(path.join(extension.extensionPath, themeInfo.path));
+}
+
+/**
+ * Parse the TextMate theme at fullPath. If there are multiple TextMate scopes
+ * of the same name in the include chain only the earliest entry of the scope is
+ * saved.
+ * @param fullPath The absolute path to the theme.
+ * @param seenScopes A set containing the name of the scopes that have already
+ *     been set.
+ */
+export async function parseThemeFile(
+    fullPath: string, seenScopes?: Set<string>): Promise<TokenColorRule[]> {
+  if (!seenScopes)
+    seenScopes = new Set();
+  // FIXME: Add support for themes written as .tmTheme.
+  if (path.extname(fullPath) === '.tmTheme')
+    return [];
+  try {
+    const contents = await readFileText(fullPath);
+    const parsed = jsonc.parse(contents);
+    const rules: TokenColorRule[] = [];
+    // To make sure it does not crash if tokenColors is undefined.
+    if (!parsed.tokenColors)
+      parsed.tokenColors = [];
+    parsed.tokenColors.forEach((rule: any) => {
+      if (!rule.scope || !rule.settings || !rule.settings.foreground)
+        return;
+      const textColor = rule.settings.foreground;
+      // Scopes that were found further up the TextMate chain should not be
+      // overwritten.
+      const addColor = (scope: string) => {
+        if (seenScopes.has(scope))
+          return;
+        rules.push({scope, foreground : textColor});
+        seenScopes.add(scope);
+      };
+      if (rule.scope instanceof Array) {
+        return rule.scope.forEach((s: string) => addColor(s));
+      }
+      addColor(rule.scope);
+    });
+
+    if (parsed.include)
+      // Get all includes and merge into a flat list of parsed json.
+      return [
+        ...(await parseThemeFile(
+            path.join(path.dirname(fullPath), parsed.include), seenScopes)),
+        ...rules
+      ];
+    return rules;
+  } catch (err) {
+    // If there is an error opening a file, the TextMate files that were
+    // correctly found and parsed further up the chain should be returned.
+    // Otherwise there will be no highlightings at all.
+    console.warn('Could not open file: ' + fullPath + ', error: ', err);
+  }
+
+  return [];
+}
+
+function readFileText(path: string): Promise<string> {
+  return new Promise((resolve, reject) => {
+    fs.readFile(path, 'utf8', (err, data) => {
+      if (err) {
+        return reject(err);
+      }
+      return resolve(data);
+    });
+  });
+}

Added: clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc?rev=368136&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc (added)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc Wed Aug  7 01:48:52 2019
@@ -0,0 +1,28 @@
+{
+    // Some comment
+    "include": "simpleTheme.jsonc",
+    "name": "TestTheme",
+    "type": "dark",
+    "colors": {
+        "dropdown.background": "#fff"
+    },
+    "tokenColors": [
+        {
+            "settings": {
+                "foreground": "#fff"
+            }
+        },
+        {
+            "scope": "a",
+            "settings": {
+                "foreground": "#fff"
+            }
+        },
+        {
+            "scope": ["a", "b"],
+            "settings": {
+                "foreground": "#000"
+            }
+        }
+    ]
+}

Added: clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc?rev=368136&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc (added)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc Wed Aug  7 01:48:52 2019
@@ -0,0 +1,17 @@
+{
+    // Some comment
+    "tokenColors": [
+        {
+            "scope": "a",
+            "settings": {
+                "foreground": "#ff0000"
+            }
+        },
+        {
+            "scope": "c",
+            "settings": {
+                "foreground": "#bcd"
+            }
+        }
+    ]
+}

Added: 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=368136&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts (added)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts Wed Aug  7 01:48:52 2019
@@ -0,0 +1,18 @@
+import * as assert from 'assert';
+import * as path from 'path';
+
+import * as TM from '../src/semantic-highlighting';
+
+suite('TextMate Tests', () => {
+  test('Parses arrays of textmate themes.', async () => {
+    const themePath =
+        path.join(__dirname, '../../test/assets/includeTheme.jsonc');
+    const scopeColorRules = await TM.parseThemeFile(themePath);
+    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'});
+  });
+});




More information about the cfe-commits mailing list