Просмотр исходного кода

Support language-server arguments in the extension. (#5056)

I was on the fence about just having a string which was
"language-server", but was thinking split options might be less
error-prone (e.g., changing options to just "-v" and trying to figure
out why nothing worked).

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Jon Ross-Perkins 1 год назад
Родитель
Сommit
92b3e61289
3 измененных файлов с 103 добавлено и 6 удалено
  1. 2 2
      utils/vscode/package-lock.json
  2. 12 2
      utils/vscode/package.json
  3. 89 2
      utils/vscode/src/extension.ts

+ 2 - 2
utils/vscode/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "carbon-vscode",
-  "version": "0.0.5",
+  "version": "0.0.6",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "carbon-vscode",
-      "version": "0.0.5",
+      "version": "0.0.6",
       "dependencies": {
         "vscode-languageclient": "^9.0.1"
       },

+ 12 - 2
utils/vscode/package.json

@@ -1,7 +1,7 @@
 {
   "name": "carbon-vscode",
   "displayName": "Carbon Language",
-  "version": "0.0.5",
+  "version": "0.0.6",
   "publisher": "carbon-lang",
   "description": "Carbon language support for Visual Studio Code.",
   "repository": {
@@ -42,8 +42,18 @@
       "properties": {
         "carbon.carbonPath": {
           "type": "string",
-          "description": "The path to the 'carbon' binary.",
+          "description": "The path to the `carbon` binary.",
           "default": "./bazel-bin/toolchain/carbon"
+        },
+        "carbon.carbonServerCommandArgs": {
+          "type": "string",
+          "description": "Extra flags to pass to `carbon` before the `language-server` subcommand, such as `-v` for debugging.",
+          "default": ""
+        },
+        "carbon.carbonServerSubcommandArgs": {
+          "type": "string",
+          "description": "Extra flags to pass to the `language-server` subcommand.",
+          "default": ""
         }
       }
     },

+ 89 - 2
utils/vscode/src/extension.ts

@@ -8,7 +8,12 @@
  * This is the main launcher for the LSP extension.
  */
 
-import { workspace, ExtensionContext, commands } from 'vscode';
+import {
+  workspace,
+  ExtensionContext,
+  commands,
+  WorkspaceConfiguration,
+} from 'vscode';
 
 import {
   LanguageClient,
@@ -18,6 +23,88 @@ import {
 
 let client: LanguageClient;
 
+/**
+ * Splits a CLI-style quoted string.
+ */
+function splitQuotedString(argsString: string): string[] {
+  const args: string[] = [];
+  let arg = '';
+  // Track whether there's an arg to handle `""` and similar.
+  let hasArg = true;
+  // Whether this is in a quote-delimited section.
+  let inSingleQuotes = false;
+  let inDoubleQuotes = false;
+  // Whether this is a `\`-escaped character.
+  let inEscape = false;
+
+  for (const char of argsString) {
+    // While spaces can appear in arguments, they can only be an argument in
+    // combination with other characters.
+    hasArg = hasArg || char != ' ';
+
+    if (inEscape) {
+      // After an escape, directly append the character.
+      arg += char;
+      inEscape = false;
+      continue;
+    }
+    switch (char) {
+      case '\\':
+        // First character of an escape.
+        inEscape = true;
+        continue;
+      case "'":
+        if (!inDoubleQuotes) {
+          // Single-quoted section.
+          inSingleQuotes = !inSingleQuotes;
+          continue;
+        }
+        break;
+      case '"':
+        if (!inSingleQuotes) {
+          // Double-quoted section.
+          inDoubleQuotes = !inDoubleQuotes;
+          continue;
+        }
+        break;
+      case ' ':
+        if (!inSingleQuotes && !inDoubleQuotes) {
+          // Space between arguments (but possibly multiple spaces).
+          if (hasArg) {
+            args.push(arg);
+            arg = '';
+            hasArg = false;
+          }
+          continue;
+        }
+        break;
+    }
+    arg += char;
+  }
+
+  // Finish any pending argument.
+  if (hasArg) {
+    args.push(arg);
+  }
+
+  return args;
+}
+
+/**
+ * Combines the `language-server` command with args from settings.
+ */
+function buildServerArgs(settings: WorkspaceConfiguration): string[] {
+  const result: string[] = [];
+  result.push(
+    ...splitQuotedString(settings.get('carbonServerCommandArgs', ''))
+  );
+  result.push('language-server');
+  result.push(
+    ...splitQuotedString(settings.get('carbonServerSubcommandArgs', ''))
+  );
+  return result;
+}
+
 export function activate(context: ExtensionContext) {
   const settings = workspace.getConfiguration('carbon');
 
@@ -28,7 +115,7 @@ export function activate(context: ExtensionContext) {
       'carbonPath',
       context.asAbsolutePath('./bazel-bin/toolchain/carbon')
     ),
-    args: ['language-server'],
+    args: buildServerArgs(settings),
   };
 
   const clientOptions: LanguageClientOptions = {