diff --git a/.gitignore b/.gitignore index 8369c310..41563e44 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ node_modules/ *.vsix out/ .DS_Store +language-server/ +language-service/ \ No newline at end of file diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..d0b9920e --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs 24.11.0 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd726f20..bb3880c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,13 +27,12 @@ Once you have completed [getting started](#getting-started), you may be wonderin This extension uses the _Language Server Protocol_ to communicate with Visual Studio Code, which is an open protocol that allows the development of a common implementation - called a __language server__ - that can communicate with different IDEs. This implementation is stored in the [Cucumber Language Server](https://github.com/cucumber/language-server) and the underlying [Cucumber Language Service](https://github.com/cucumber/language-service). Let's integrate local versions of each into our extension so we can modify them. -1. First, clone the Language Server and the Language Service to the same directory in which you cloned the extension. Your directory structure should appear as follows: +1. First, clone the Language Server and the Language Service in cloned extension directory (this is required in order to build a VSIX package). Your directory structure should appear as follows: ```console - directory/ + vscode/ ├── language-server/ - ├── language-service/ - └── vscode/ + └── language-service/ ``` 2. At this point, please [download and install docker](https://www.docker.com/products/docker-desktop/) if you have not already done so. A [docker installation is required](https://github.com/cucumber/language-service/blob/main/CONTRIBUTING.md#prerequisites) to build the Language Service. @@ -69,7 +68,13 @@ This extension uses the _Language Server Protocol_ to communicate with Visual St ```console la node_modules/@cucumber - lrwxr-xr-x 1 username staff 24 Jan 22 09:32 language-server -> ../../../language-server + lrwxr-xr-x 1 username staff 24 Jan 22 09:32 language-server -> ../../language-server + ``` + + Convenience script was created: [reconfigure_local_modules.sh](./reconfigure_local_modules.sh) + + ```bash + ./reconfigure_local_modules.sh ``` 4. Now open the extension repository in Visual Studio Code. @@ -85,6 +90,12 @@ If you need to make further changes to these packages, you have to rebuild them For debugging the extension, set breakpoints within the code. 🐞 +You can use convenience script - [rebuild.sh](./rebuild.sh) + +```bash +./rebuild.sh +``` + ### Check everything is working A nice way to check you are using the local language server implementations is to modify the snippet templates that generate step definitions for undefined steps. You will find these templates assigned to `defaultSnippetTemplate` in each of the ['\Language.ts' files](https://github.com/cucumber/language-service/tree/main/src/language) of the Language Service, where each `` is a programming language in which you can write compatible step definitions. Preferably, use a language you are comfortable with. diff --git a/package-lock.json b/package-lock.json index 6de819f6..f9259667 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cucumber-official", - "version": "1.11.0", + "version": "2.0.0-beta", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cucumber-official", - "version": "1.11.0", + "version": "2.0.0-beta", "dependencies": { "@cucumber/language-server": "1.7.0", "vscode-languageclient": "9.0.1" @@ -1465,6 +1465,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -1868,6 +1869,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3263,6 +3265,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3333,6 +3336,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -6507,6 +6511,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -7889,17 +7894,6 @@ "node": ">=8.0" } }, - "node_modules/tree-sitter": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", - "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.0" - } - }, "node_modules/tree-sitter-c-sharp": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/tree-sitter-c-sharp/-/tree-sitter-c-sharp-0.23.1.tgz", @@ -8166,15 +8160,6 @@ "node": "^18 || ^20 || >= 21" } }, - "node_modules/tree-sitter/node_modules/node-addon-api": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz", - "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==", - "optional": true, - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -8387,6 +8372,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9940,6 +9926,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, + "peer": true, "requires": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -10194,7 +10181,8 @@ "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -11178,6 +11166,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -11233,6 +11222,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, + "peer": true, "requires": {} }, "eslint-import-resolver-node": { @@ -13464,7 +13454,8 @@ "version": "3.8.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true + "dev": true, + "peer": true }, "prettier-linter-helpers": { "version": "1.0.1", @@ -14422,24 +14413,6 @@ "is-number": "^7.0.0" } }, - "tree-sitter": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", - "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", - "optional": true, - "requires": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.0" - }, - "dependencies": { - "node-addon-api": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz", - "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==", - "optional": true - } - } - }, "tree-sitter-c-sharp": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/tree-sitter-c-sharp/-/tree-sitter-c-sharp-0.23.1.tgz", @@ -14761,7 +14734,8 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true + "dev": true, + "peer": true }, "uc.micro": { "version": "2.1.0", diff --git a/package.json b/package.json index fa3c1e84..a589288a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "cucumber-official", "displayName": "Cucumber", "description": "Cucumber for Visual Studio Code", - "version": "1.11.0", + "version": "2.0.0-beta", "publisher": "CucumberOpen", "engines": { "vscode": "^1.82.0" @@ -87,7 +87,14 @@ "default": [] } } - } + }, + "commands": [ + { + "command": "cucumber.forceReindex", + "title": "Cucumber: Force Reindex", + "description": "Force reindexing of the Cucumber Language Server" + } + ] }, "scripts": { "vscode:prepublish": "npm run build", diff --git a/rebuild.sh b/rebuild.sh new file mode 100755 index 00000000..41655fa0 --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -euo pipefail + +cd language-service +npm run build +cd .. +cd language-server +npm run build +cd .. diff --git a/reconfigure_local_modules.sh b/reconfigure_local_modules.sh new file mode 100755 index 00000000..45c13e5e --- /dev/null +++ b/reconfigure_local_modules.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +cd language-service +npm install +npm link +npm run build +cd .. +cd language-server +npm install +npm link @cucumber/language-service +npm link +npm run build +cd .. +npm install +npm link @cucumber/language-server +ls -lAh node_modules/@cucumber diff --git a/src/extension.ts b/src/extension.ts index 5b8cfc5f..4adce324 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -35,7 +35,40 @@ export async function activate(context: vscode.ExtensionContext) { client = new LanguageClient('Cucumber', 'Cucumber Language Server', serverOptions, clientOptions) + console.log('Connecting to Cucumber Language Server') await client.start() + + // Register the force reindex command + const forceReindexCommand = vscode.commands.registerCommand('cucumber.forceReindex', async () => { + if (!client || !client.isRunning()) { + vscode.window.showWarningMessage('Cucumber Language Server is not running') + return + } + + try { + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: 'Cucumber: Reindexing...', + cancellable: false, + }, + async () => { + const result = await client.sendRequest<{ success: boolean; error?: string }>( + 'cucumber/forceReindex' + ) + if (result.success) { + vscode.window.showInformationMessage('Cucumber: Reindexing completed successfully') + } else { + vscode.window.showErrorMessage(`Cucumber: Reindexing failed - ${result.error}`) + } + } + ) + } catch (error) { + vscode.window.showErrorMessage(`Cucumber: Failed to trigger reindex - ${error}`) + } + }) + + context.subscriptions.push(forceReindexCommand) } // this method is called when your extension is deactivated diff --git a/vscode.code-workspace b/vscode.code-workspace new file mode 100644 index 00000000..d137e176 --- /dev/null +++ b/vscode.code-workspace @@ -0,0 +1,17 @@ +{ + "folders": [ + { + "name": "cucumber-vscode", + "path": "." + }, + { + "name": "language-service", + "path": "language-service" + }, + { + "name": "language-server", + "path": "language-server" + } + ], + "settings": {} +} \ No newline at end of file