jvikstrom updated this revision to Diff 213528.
jvikstrom marked 2 inline comments as done.
jvikstrom added a comment.

Narrowed CL down to loading/parsing a text mate theme.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65738

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/package.json
  clang-tools-extra/clangd/clients/clangd-vscode/src/TextMate.ts
  clang-tools-extra/clangd/clients/clangd-vscode/test/TextMate.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/TextMate.test.ts
===================================================================
--- /dev/null
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/TextMate.test.ts
@@ -0,0 +1,27 @@
+/** The module 'assert' provides assertion methods from node */
+import * as assert from 'assert';
+
+import {SemanticHighlighting} from '../src/TextMate';
+
+suite('TextMate Tests', () => {
+  test('Parses arrays of textmate themes.', () => {
+    const themes = [
+      {}, {
+        tokenColors : [
+          {}, {scope : 'a'},
+          {scope : [ 'b', 'c', 'd' ], settings : {background : '#000'}},
+          {scope : 'a', settings : {foreground : '#000'}},
+          {scope : [ 'a', 'b', 'c' ], settings : {foreground : '#fff'}}
+        ]
+      },
+      {tokenColors : [ {scope : 'b', settings : {foreground : '#ff0000'}} ]}
+    ];
+    const scopeColorRules = SemanticHighlighting.themesToScopeColors(themes);
+    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 : '#ff0000'});
+    assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#fff'});
+  });
+});
\ No newline at end of file
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/TextMate.ts
===================================================================
--- /dev/null
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/TextMate.ts
@@ -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';
+
+export namespace SemanticHighlighting {
+interface ScopeColorRule {
+  scope: string, textColor: string,
+}
+
+async function getNamedThemeScopeColors(themeName: string):
+    Promise<ScopeColorRule[]> {
+  const contents = await getFullNamedTheme(themeName);
+  return themesToScopeColors(contents);
+}
+
+/**
+ * Convert an array of TextMate theme contents into the an array of all scopes'
+ * colors. If there are duplicate entries of a scope only the latest occurence
+ * of the scope is kept.
+ * @param themeContents An entry in this array is either the theme's (or an
+ *     included theme's) TextMate definition.
+ */
+export function themesToScopeColors(themeContents: any[]): ScopeColorRule[] {
+  const ruleMap: Map<string, string> = new Map();
+  themeContents.forEach((content) => {
+    if (!content.tokenColors)
+      return;
+    content.tokenColors.forEach((rule: any) => {
+      if (!rule.scope || !rule.settings || !rule.settings.foreground)
+        return;
+      const textColor = rule.settings.foreground;
+      if (rule.scope instanceof Array) {
+        rule.scope.forEach((s: string) => ruleMap.set(s, textColor));
+        return;
+      }
+      ruleMap.set(rule.scope, textColor);
+    });
+  });
+
+  return Array.from(ruleMap.entries())
+      .map(([ scope, textColor ]) => ({scope, textColor}));
+}
+
+// Gets a TextMate theme by its name and all its included themes.
+async function getFullNamedTheme(themeName: string): Promise<any[]> {
+  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 extensionInfo = extension.packageJSON.contributes.themes.find(
+      (theme: any) => theme.id === themeName || theme.label === themeName);
+  return recursiveGetTextMateGrammarPath(
+      path.join(extension.extensionPath, extensionInfo.path));
+}
+
+// TM grammars can include other TM grammars, this function recursively gets all
+// of them.
+async function recursiveGetTextMateGrammarPath(fullPath: string):
+    Promise<any[]> {
+  // If there is an error opening a file, the TM files that were correctly found
+  // and parsed further up the chain should be returned. Otherwise there will be
+  // no highlightings at all.
+  try {
+    const contents = await readFileText(fullPath);
+    // FIXME: Add support for themes written as .thTheme.
+    const parsed = jsonc.parse(contents);
+    if (parsed.include)
+      // Get all includes and merge into a flat list of parsed json.
+      return [
+        ...(await recursiveGetTextMateGrammarPath(
+            path.join(path.dirname(fullPath), parsed.include))),
+        parsed
+      ];
+    return [ parsed ];
+  } catch (err) {
+    console.warn('Could not open file: ' + fullPath + ', error: ', err);
+  }
+
+  return [];
+}
+
+function readFileText(path: string): Promise<string> {
+  return new Promise((res, rej) => {
+    fs.readFile(path, 'utf8', (err, data) => {
+      if (err) {
+        rej(err);
+      }
+      res(data);
+    });
+  });
+}
+}
Index: clang-tools-extra/clangd/clients/clangd-vscode/package.json
===================================================================
--- clang-tools-extra/clangd/clients/clangd-vscode/package.json
+++ clang-tools-extra/clangd/clients/clangd-vscode/package.json
@@ -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"
     },
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to