Jelajahi Sumber

Update the vscode language server setup (#4663)

Switches from js to ts, and starts bundling files in order to produce a
better package for deployment. Fixes the README.md to be a more
appropriate front page, moving dev content to development.md. Makes the
path to `carbon` configurable so that it's more stable than just running
in `bazel-bin`.

This is built using suggestions from samples at
https://github.com/microsoft/vscode-extension-samples/tree/main/lsp-sample
and
https://github.com/microsoft/vscode-extension-samples/tree/main/esbuild-sample.
Note the esbuild in particular comes from complaints from `vsce` to use
an option from
https://code.visualstudio.com/api/working-with-extensions/bundling-extension,
and esbuild is just the first option detailed there (I have no real
opinion on options).

I'm bumping the version, and will do a release after merging.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Jon Ross-Perkins 1 tahun lalu
induk
melakukan
f922988c8c

+ 8 - 1
.pre-commit-config.yaml

@@ -54,7 +54,7 @@ repos:
         name: prettier
         language: node
         additional_dependencies: ['prettier@3.3.3']
-        types_or: [html, javascript, markdown, yaml]
+        types_or: [html, javascript, json, markdown, yaml]
         entry: npx prettier --write --log-level=warn
   - repo: local
     hooks:
@@ -189,6 +189,11 @@ repos:
           - '// '
           - ''
           - --custom_format
+          - '\.(js|ts|mjs)$'
+          - '/*'
+          - ' * '
+          - ' */'
+          - --custom_format
           - '\.(l|lpp|y)$'
           - '/*'
           - ''
@@ -221,9 +226,11 @@ repos:
               compile_flags.txt|
               github_tools/requirements.txt|
               third_party/.*|
+              utils/vscode/esbuild.js|
               website/.ruby-version|
               website/Gemfile.lock|
               .*\.def|
+              .*\.png|
               .*\.svg|
               .*/fuzzer_corpus/.*|
               .*/testdata/.*\.golden

+ 2 - 1
utils/vscode/.gitignore

@@ -2,5 +2,6 @@
 # Exceptions. See /LICENSE for license information.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
+*.vsix
+/dist
 /node_modules
-/out

+ 3 - 5
utils/vscode/.vscode/launch.json

@@ -1,7 +1,3 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
 {
   "version": "0.2.0",
   "configurations": [
@@ -9,7 +5,9 @@
       "name": "Run Extension",
       "type": "extensionHost",
       "request": "launch",
-      "args": ["--extensionDevelopmentPath=${workspaceFolder}"]
+      "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
+      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
+      "preLaunchTask": "${defaultBuildTask}"
     }
   ]
 }

+ 55 - 0
utils/vscode/.vscode/tasks.json

@@ -0,0 +1,55 @@
+{
+  "version": "2.0.0",
+  "tasks": [
+    {
+      "label": "watch",
+      "dependsOn": ["npm: watch:tsc", "npm: watch:esbuild"],
+      "presentation": {
+        "reveal": "never"
+      },
+      "group": {
+        "kind": "build",
+        "isDefault": true
+      }
+    },
+    {
+      "type": "npm",
+      "script": "watch:esbuild",
+      "group": "build",
+      "isBackground": true,
+      "label": "npm: watch:esbuild",
+      "presentation": {
+        "group": "watch",
+        "reveal": "never"
+      }
+    },
+    {
+      "type": "npm",
+      "script": "watch:tsc",
+      "group": "build",
+      "problemMatcher": "$tsc-watch",
+      "isBackground": true,
+      "label": "npm: watch:tsc",
+      "presentation": {
+        "group": "watch",
+        "reveal": "never"
+      }
+    },
+    {
+      "type": "npm",
+      "script": "watch-tests",
+      "problemMatcher": "$tsc-watch",
+      "isBackground": true,
+      "presentation": {
+        "reveal": "never",
+        "group": "watchers"
+      },
+      "group": "build"
+    },
+    {
+      "label": "tasks: watch-tests",
+      "dependsOn": ["npm: watch", "npm: watch-tests"],
+      "problemMatcher": []
+    }
+  ]
+}

+ 12 - 0
utils/vscode/.vscodeignore

@@ -0,0 +1,12 @@
+# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+# Exceptions. See /LICENSE for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+.gitignore
+.vscode/
+node_modules/
+src/
+development.md
+esbuild.js
+eslint.config.mjs
+tsconfig.json

+ 28 - 22
utils/vscode/README.md

@@ -1,39 +1,45 @@
+# Carbon Language
+
 <!--
 Part of the Carbon Language project, under the Apache License v2.0 with LLVM
 Exceptions. See /LICENSE for license information.
 SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 -->
 
-# VS Code Extension for Carbon
+This extension provides support for the
+[Carbon Language](https://github.com/carbon-language/carbon-lang).
 
-Currently only contains basic syntax highlighting.
+This extension is currently experimental, and being developed alongside Carbon.
 
-## Installing
+## Quickstart
 
-1. Install Node JS.
-2. To generate VS Code extension file (.vsix).
+1. Download and install a `carbon`
+   [release](https://github.com/carbon-language/carbon-lang/releases).
+    - By default, the extension will look for `carbon` under `./bazel-bin`. This
+      is for developers actively working on Carbon and running VS Code inside a
+      [carbon-lang](https://github.com/carbon-language/carbon-lang) clone.
+2. Install the
+   [Carbon Language extension](https://marketplace.visualstudio.com/items?itemName=carbon-lang.carbon-vscode).
+3. Configure the installed path to `carbon`.
 
-```shell
-npm install && npm run package
-```
+## Configuration
 
-3. Install the extension
+The configuration is under `carbon-vscode.*`. At present, the only configuration
+is the path to the `carbon` binary. This looks like:
 
-```shell
-code --install-extension out/carbon.vsix
+```
+"carbon.carbonPath": "/path/to/carbon"
 ```
 
-## Development
+## Communication
 
-1. `bazel build //toolchain` in project root.
-2. Open utils/vscode folder in VS Code.
-3. Launch the extension using Run command (F5).
-4. In the opened window, open the carbon-lang repository as folder.
-5. Open a carbon file.
-6. Open code outline (Ctrl+Shift+O).
+See Carbon's
+[collaboration systems](https://github.com/carbon-language/carbon-lang/blob/trunk/CONTRIBUTING.md#collaboration-systems).
+We're most active on [Discord](https://discord.gg/ZjVdShJDAs) and have a
+#editor-integrations channel. We'll also respond to questions on
+[GitHub Discussions](https://github.com/carbon-language/carbon-lang/discussions).
 
-To update dependencies:
+## Documentation
 
-```shell
-npm update
-```
+Carbon currently only has project-level documentation. See the
+[GitHub repository](https://github.com/carbon-language/carbon-lang).

+ 51 - 0
utils/vscode/development.md

@@ -0,0 +1,51 @@
+# Extension development
+
+<!--
+Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+Exceptions. See /LICENSE for license information.
+SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+-->
+
+Currently only contains basic syntax highlighting.
+
+## Releases
+
+This assumes NodeJS is installed, along with `vsce` (using
+`npm install -g vsce`).
+
+1.  `npm install && vsce publish`
+
+## Local installation
+
+This assumes NodeJS is installed, along with `vsce` (using
+`npm install -g vsce`).
+
+1.  `npm install && vsce package -o carbon.vsix && realpath carbon.vsix`
+    -   This installs dependencies, builds the VSIX file, and prints the path
+        for installation.
+2.  Install the plugin:
+    -   If you're using VS Code locally, run
+        `npm install && vsce package -o carbon.vsix && code --install-extension carbon.vsix`
+    -   If you're using VS Code's remote mode:
+        1.  In vscode, open the
+            [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
+            and select "Extensions: Install from VSIX...".
+        2.  Enter the path printed by the above command.
+
+## Development
+
+1.  `bazel build //toolchain` in project root.
+2.  Open utils/vscode folder in VS Code.
+3.  Launch the extension using Run command (F5).
+4.  In the opened window, open the carbon-lang repository as folder.
+5.  Open a carbon file.
+6.  Open code outline (Ctrl+Shift+O).
+
+## Debugging output
+
+1.  Go to the "Output" panel.
+2.  In the top right, there is a dropdown; select "Carbon Language Server".
+
+## Updating dependencies
+
+To update dependencies, run `npm update`.

+ 88 - 0
utils/vscode/esbuild.js

@@ -0,0 +1,88 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2015 - present Microsoft Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This supports using esbuild to bundle the extension for releases. This is
+ * invoked through package.json.
+ *
+ * For information about this, see:
+ * https://code.visualstudio.com/api/working-with-extensions/bundling-extension
+ */
+
+const esbuild = require('esbuild');
+
+const production = process.argv.includes('--production');
+const watch = process.argv.includes('--watch');
+
+/**
+ * @type {import('esbuild').Plugin}
+ */
+const esbuildProblemMatcherPlugin = {
+  name: 'esbuild-problem-matcher',
+
+  setup(build) {
+    build.onStart(() => {
+      console.log('[watch] build started');
+    });
+    build.onEnd((result) => {
+      result.errors.forEach(({ text, location }) => {
+        console.error(`✘ [ERROR] ${text}`);
+        console.error(
+          `    ${location.file}:${location.line}:${location.column}:`
+        );
+      });
+      console.log('[watch] build finished');
+    });
+  },
+};
+
+async function main() {
+  const ctx = await esbuild.context({
+    entryPoints: ['src/extension.ts'],
+    bundle: true,
+    format: 'cjs',
+    minify: production,
+    sourcemap: !production,
+    sourcesContent: false,
+    platform: 'node',
+    outfile: 'dist/extension.js',
+    external: ['vscode'],
+    logLevel: 'silent',
+    plugins: [
+      /* add to the end of plugins array */
+      esbuildProblemMatcherPlugin,
+    ],
+  });
+  if (watch) {
+    await ctx.watch();
+  } else {
+    await ctx.rebuild();
+    await ctx.dispose();
+  }
+}
+
+main().catch((e) => {
+  console.error(e);
+  process.exit(1);
+});

+ 49 - 0
utils/vscode/eslint.config.mjs

@@ -0,0 +1,49 @@
+/*
+ * Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+ * Exceptions. See /LICENSE for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/*
+ * ESLint configuration.
+ *
+ * See https://eslint.style and https://typescript-eslint.io for additional
+ * linting options.
+ */
+
+// @ts-check
+import js from '@eslint/js';
+import tseslint from 'typescript-eslint';
+import stylistic from '@stylistic/eslint-plugin';
+
+export default tseslint.config(
+  {
+    ignores: ['dist', 'out', 'esbuild.js'],
+  },
+  js.configs.recommended,
+  ...tseslint.configs.recommended,
+  ...tseslint.configs.stylistic,
+  {
+    plugins: {
+      '@stylistic': stylistic,
+    },
+    rules: {
+      curly: 'warn',
+      '@stylistic/semi': ['warn', 'always'],
+      '@typescript-eslint/no-empty-function': 'off',
+      '@typescript-eslint/naming-convention': [
+        'warn',
+        {
+          selector: 'import',
+          format: ['camelCase', 'PascalCase'],
+        },
+      ],
+      '@typescript-eslint/no-unused-vars': [
+        'error',
+        {
+          argsIgnorePattern: '^_',
+        },
+      ],
+    },
+  }
+);

File diff ditekan karena terlalu besar
+ 924 - 105
utils/vscode/package-lock.json


+ 31 - 6
utils/vscode/package.json

@@ -1,7 +1,7 @@
 {
   "name": "carbon-vscode",
   "displayName": "Carbon Language",
-  "version": "0.0.2",
+  "version": "0.0.3",
   "publisher": "carbon-lang",
   "description": "Carbon language support for Visual Studio Code.",
   "repository": {
@@ -15,7 +15,7 @@
   ],
   "icon": "images/icon.png",
   "activationEvents": [],
-  "main": "./src/extension.js",
+  "main": "./dist/extension.js",
   "contributes": {
     "languages": [
       {
@@ -35,16 +35,41 @@
         "scopeName": "source.carbon",
         "path": "./carbon.tmLanguage.json"
       }
-    ]
+    ],
+    "configuration": {
+      "type": "object",
+      "title": "Carbon Language",
+      "properties": {
+        "carbon.carbonPath": {
+          "type": "string",
+          "description": "The path to the 'carbon' binary."
+        }
+      }
+    }
   },
   "scripts": {
-    "package": "mkdir -p out && vsce package -o out/carbon.vsix"
+    "vscode:prepublish": "npm run package",
+    "compile": "npm run check-types && npm run lint && node esbuild.js",
+    "watch": "npm-run-all -p watch:*",
+    "watch:esbuild": "node esbuild.js --watch",
+    "watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
+    "package": "npm run check-types && npm run lint && node esbuild.js --production",
+    "compile-tests": "tsc -p . --outDir out",
+    "check-types": "tsc --noEmit",
+    "lint": "eslint"
   },
   "devDependencies": {
-    "@vscode/vsce": "^2.27.0"
+    "@eslint/js": "^9.13.0",
+    "@stylistic/eslint-plugin": "^2.9.0",
+    "@types/node": "^20",
+    "@types/vscode": "^1.73.0",
+    "@vscode/vsce": "^2.27.0",
+    "esbuild": "^0.24.0",
+    "eslint": "^9.13.0",
+    "typescript": "^5.7.2",
+    "typescript-eslint": "^8.16.0"
   },
   "dependencies": {
-    "@vscode/vsce": "^2.27.0",
     "vscode-languageclient": "^9.0.1"
   }
 }

+ 0 - 37
utils/vscode/src/extension.js

@@ -1,37 +0,0 @@
-/*
- * Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- * Exceptions. See /LICENSE for license information.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
-
-const { LanguageClient } = require('vscode-languageclient/node');
-
-function activate(context) {
-  const command = './bazel-bin/toolchain/install/run_carbon';
-  const args = ['language-server'];
-  const serverOptions = {
-    run: { command: command, args: args },
-    debug: { command: command, args: args },
-  };
-
-  const clientOptions = {
-    documentSelector: [{ scheme: 'file', language: 'carbon' }],
-  };
-
-  const client = new LanguageClient(
-    'languageServer',
-    'Language Server for Carbon',
-    serverOptions,
-    clientOptions
-  );
-
-  // stop client on shutdown
-  context.subscriptions.push(client.start());
-}
-
-function deactivate() {}
-
-module.exports = {
-  activate,
-  deactivate,
-};

+ 53 - 0
utils/vscode/src/extension.ts

@@ -0,0 +1,53 @@
+/*
+ * Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+ * Exceptions. See /LICENSE for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/*
+ * This is the main launcher for the LSP extension.
+ */
+
+import { workspace, ExtensionContext } from 'vscode';
+
+import {
+  LanguageClient,
+  LanguageClientOptions,
+  ServerOptions,
+} from 'vscode-languageclient/node';
+
+let client: LanguageClient;
+
+export function activate(context: ExtensionContext) {
+  const settings = workspace.getConfiguration('carbon');
+
+  const serverOptions: ServerOptions = {
+    // The Carbon server can be configured, but we try to use bazel output as a
+    // fallback.
+    command: settings.get(
+      'carbonPath',
+      context.asAbsolutePath('./bazel-bin/toolchain/install/run_carbon')
+    ),
+    args: ['language-server'],
+  };
+
+  const clientOptions: LanguageClientOptions = {
+    documentSelector: [{ language: 'carbon' }],
+  };
+
+  // Create and start the client.
+  client = new LanguageClient(
+    'carbonLanguageServer',
+    'Carbon Language Server',
+    serverOptions,
+    clientOptions
+  );
+  client.start();
+}
+
+export function deactivate(): Thenable<void> | undefined {
+  if (!client) {
+    return undefined;
+  }
+  return client.stop();
+}

+ 13 - 0
utils/vscode/tsconfig.json

@@ -0,0 +1,13 @@
+{
+  "compilerOptions": {
+    "module": "commonjs",
+    "target": "es2020",
+    "lib": ["es2020"],
+    "outDir": "out",
+    "sourceMap": true,
+    "strict": true,
+    "rootDir": "src"
+  },
+  "include": ["src"],
+  "exclude": ["node_modules"]
+}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini