├── .eslintrc.json ├── .github ├── renovate.json └── workflows │ ├── build.yaml │ ├── release-github.yml │ └── release-marketplace.yaml ├── .gitignore ├── .husky └── pre-commit ├── .prettierrc.json ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASING.md ├── images ├── autocomplete.gif ├── document-outline.gif ├── feature-file-icons.png ├── formatting.gif ├── generate-step-definition.gif ├── goto-step-definition.gif ├── icon.png ├── icon.svg ├── localisation.png ├── syntax-highlighting.gif └── vscode-output.png ├── language-configuration.json ├── package-lock.json ├── package.json ├── scripts ├── update-settings-docs.sh └── vscode-types-compatible.sh ├── src ├── VscodeFiles.ts ├── extension.ts └── test │ ├── runTest.ts │ └── suite │ ├── extension.test.ts │ └── index.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "parser": "@typescript-eslint/parser", 7 | "parserOptions": { 8 | "project": "tsconfig.json", 9 | "sourceType": "module" 10 | }, 11 | "plugins": ["import", "simple-import-sort", "n", "@typescript-eslint"], 12 | "extends": [ 13 | "eslint:recommended", 14 | "plugin:import/typescript", 15 | "plugin:@typescript-eslint/eslint-recommended", 16 | "plugin:@typescript-eslint/recommended", 17 | "plugin:prettier/recommended" 18 | ], 19 | "rules": { 20 | "import/no-cycle": "error", 21 | "n/no-extraneous-import": "error", 22 | "@typescript-eslint/ban-ts-ignore": "off", 23 | "@typescript-eslint/ban-ts-comment": "off", 24 | "@typescript-eslint/explicit-module-boundary-types": "off", 25 | "@typescript-eslint/explicit-function-return-type": "off", 26 | "@typescript-eslint/no-use-before-define": "off", 27 | "@typescript-eslint/interface-name-prefix": "off", 28 | "@typescript-eslint/member-delimiter-style": "off", 29 | "@typescript-eslint/no-explicit-any": "error", 30 | "@typescript-eslint/no-non-null-assertion": "error", 31 | "simple-import-sort/imports": "error", 32 | "simple-import-sort/exports": "error" 33 | }, 34 | "overrides": [ 35 | { 36 | "files": ["test/**"], 37 | "rules": { 38 | "@typescript-eslint/no-non-null-assertion": "off" 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "github>cucumber/renovate-config" 5 | ], 6 | "packageRules": [ 7 | { 8 | "matchPackageNames": ["vscode"], 9 | "automerge": false 10 | }, 11 | { 12 | "matchPackageNames": ["@types/vscode"], 13 | "enabled": false 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - renovate/** 8 | pull_request: 9 | branches: 10 | - main 11 | workflow_call: 12 | 13 | jobs: 14 | build: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | os: 20 | - ubuntu-latest 21 | - macos-latest 22 | node-version: 23 | - '16.x' 24 | - '18.x' 25 | - '20.x' 26 | 27 | steps: 28 | - name: set git core.autocrlf to 'input' 29 | run: git config --global core.autocrlf input 30 | - uses: actions/checkout@v4 31 | - name: with Node.js ${{ matrix.node-version }} on ${{ matrix.os }} 32 | uses: actions/setup-node@v4 33 | with: 34 | node-version: ${{ matrix.node-version }} 35 | cache: 'npm' 36 | cache-dependency-path: package-lock.json 37 | - run: npm install-ci-test 38 | - run: npm run vscode-types-compatible 39 | - run: npm run update-settings-docs 40 | - run: npm run build 41 | - run: npm run package 42 | - run: npm run eslint 43 | -------------------------------------------------------------------------------- /.github/workflows/release-github.yml: -------------------------------------------------------------------------------- 1 | name: Release GitHub 2 | 3 | on: 4 | push: 5 | branches: [release/*] 6 | 7 | jobs: 8 | create-github-release: 9 | name: Create GitHub Release and Git tag 10 | runs-on: ubuntu-latest 11 | environment: Release 12 | permissions: 13 | contents: write 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: cucumber/action-create-github-release@v1.1.1 17 | with: 18 | github-token: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/release-marketplace.yaml: -------------------------------------------------------------------------------- 1 | name: Release to marketplace 2 | 3 | on: 4 | push: 5 | branches: [release/*] 6 | 7 | jobs: 8 | publish-marketplace: 9 | name: Release to marketplace 10 | runs-on: ubuntu-latest 11 | environment: Release 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: '22' 17 | cache: 'npm' 18 | cache-dependency-path: package-lock.json 19 | - run: npm install-test 20 | - name: Show Dependency Manifest 21 | run: npm ls -a 22 | - name: Publish to Visual Studio Marketplace 23 | uses: HaaLeo/publish-vscode-extension@v2 24 | with: 25 | pat: ${{ secrets.MICROSOFT_MARKETPLACE_TOKEN }} 26 | registryUrl: https://marketplace.visualstudio.com 27 | - name: Publish to Open VSX Registry 28 | uses: HaaLeo/publish-vscode-extension@v2 29 | with: 30 | pat: ${{ secrets.OPEN_VSX_TOKEN }} 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .idea/ 3 | node_modules/ 4 | *.log 5 | *.iml 6 | .vscode-test 7 | *.vsix 8 | out/ 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged --no-stash 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "semi": false, 4 | "singleQuote": true, 5 | "printWidth": 100 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "args": [ 9 | "--extensionDevelopmentPath=${workspaceFolder}" 10 | ], 11 | "outFiles": [ 12 | "${workspaceFolder}/dist/**/*.js" 13 | ], 14 | "log": true, 15 | "preLaunchTask": { 16 | "type": "npm", 17 | "script": "build" 18 | } 19 | }, 20 | { 21 | "name": "Extension Tests", 22 | "type": "extensionHost", 23 | "request": "launch", 24 | "args": [ 25 | "--extensionDevelopmentPath=${workspaceFolder}", 26 | "--extensionTestsPath=${workspaceFolder}/dist/src/test/suite/index" 27 | ], 28 | "outFiles": [ 29 | "${workspaceFolder}/dist/src/test/**/*.js" 30 | ], 31 | "preLaunchTask": "${defaultBuildTask}" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "dist": true // set this to false to show the "dist" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "dist": true // set this to false to include "dist" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "always", 13 | "panel": "new" 14 | }, 15 | "group": { 16 | "kind": "build", 17 | "isDefault": true 18 | } 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | * 2 | */** 3 | # Whitelist the following files 4 | !package.json 5 | !language-configuration.json 6 | !LICENSE 7 | !README.md 8 | !CHANGELOG.md 9 | !images/icon.png 10 | !images/icon.svg 11 | !out/*.js 12 | !out/*.wasm 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | ## [Unreleased] 9 | 10 | ## [1.11.0] - 2025-05-18 11 | ### Changed 12 | - Update dependency @cucumber/language-server to 1.7.0 13 | 14 | ## [1.10.0] - 2024-04-21 15 | ### Added 16 | - (Go) Godog step definitions support ([language-service#130](https://github.com/cucumber/language-service/pull/130)) 17 | - (Java) Cucumber JVM `@And` and `@But` step definition annotations support ([language-service#202](https://github.com/cucumber/language-service/pull/202)) 18 | - (Python) Behave `@step` step definition decorator support ([language-service#200](https://github.com/cucumber/language-service/pull/200)) 19 | - (i18n) Syntax highlighting for Malayalam (`ml`) localisation ([gherkin v27.0.0](https://github.com/cucumber/gherkin/releases/tag/v27.0.0)) 20 | - (i18n) Syntax highlighting for `Rule` in Vietnamese, Irish, Danish, Dutch ([gherkin v27.0.0](https://github.com/cucumber/gherkin/releases/tag/v27.0.0), [gherkin v28.0.0](https://github.com/cucumber/gherkin/releases/tag/v28.0.0)) 21 | 22 | ### Fixed 23 | - (Python) Only match parameter types with names and regular expressions ([language-service#196](https://github.com/cucumber/language-service/pull/196)) 24 | - (Python) Generate step definitions without redundant commas and spaces ([language-service#160](https://github.com/cucumber/language-service/issues/160)) 25 | - (Python) Step definition patterns with explicit unicode strings (`u""`) ([language-service#173](https://github.com/cucumber/language-service/pull/173)) 26 | - (Rust) Step definition patterns with `r#` raw strings ([language-service#176](https://github.com/cucumber/language-service/pull/176)) 27 | - (Rust) Step definition patterns with line continuations ([language-service#179](https://github.com/cucumber/language-service/pull/179)) 28 | - (Java) Step definition patterns with concatenated strings ([language-service#202](https://github.com/cucumber/language-service/pull/202)) 29 | - Format empty headings without introducing trailing whitespace ([gherkin-utils#35](https://github.com/cucumber/gherkin-utils/pull/35)) 30 | - Format trailing comments ([gherkin-utils#38](https://github.com/cucumber/gherkin-utils/pull/41)) 31 | - Format tables with full-width characters ([gherkin-utils#53](https://github.com/cucumber/gherkin-utils/pull/53)) 32 | - Verbose alternation in optional error message with Cucumber Expressions ([cucumber-expressions#260](https://github.com/cucumber/cucumber-expressions/pull/260), [cucumber-expressions#253](https://github.com/cucumber/cucumber-expressions/pull/253)) 33 | 34 | ## [1.9.0] - 2024-03-24 35 | ### Added 36 | - Cucumber icon for feature files ([#206](https://github.com/cucumber/vscode/pull/206)) 37 | - Semantic highlighting enabled by default for gherkin ([#207](https://github.com/cucumber/vscode/pull/207)) 38 | 39 | ## [1.8.1] - 2024-01-14 40 | ### Changed 41 | - Optimised extension bundling using GitHub CDN for documentation images and by excluding redundant files ([#194](https://github.com/cucumber/vscode/issues/194)) 42 | 43 | ### Fixed 44 | - Comments are no longer stripped when formatting Gherkin documents 45 | - Fix the glue for CSharp step definitions - [#144](https://github.com/cucumber/vscode/pull/144) 46 | 47 | ## [1.8.0] - 2023-09-20 48 | ### Fixed 49 | - Bumped the minimum Code version requirement to 1.82.0 to prevent people from using the extension with incompatible, older versions 50 | 51 | ## [1.7.0] - 2022-12-08 52 | ### Added 53 | - Added support for JavaScript - [#42](https://github.com/cucumber/language-service/issues/42), [#115](https://github.com/cucumber/language-service/pull/115), [#120](https://github.com/cucumber/language-service/pull/120) 54 | 55 | ### Fixed 56 | - Fixed a regression in the python language implementation for regexes [#119](https://github.com/cucumber/language-service/pull/119) 57 | 58 | ## [1.6.0] - 2022-11-18 59 | ### Added 60 | - Added context to python snippet to properly support `behave` 61 | - Added `ParameterType` support to the python language implementation. This is currently supported via [cuke4behave](http://gitlab.com/cuke4behave/cuke4behave) 62 | 63 | ## [1.5.1] - 2022-10-11 64 | ### Fixed 65 | - (TypeScript) Fix bug in template literal recognition 66 | 67 | ## [1.5.0] - 2022-10-10 68 | ### Added 69 | - New Document Outline panel, making it easier to navigate between scenarios. 70 | - (Java) Recognise regexps with `(?i)`, with the caveat that the resulting JavaScript `RegExp` is _not_ case insensitive ([#100](https://github.com/cucumber/language-service/issues/100), [#108](https://github.com/cucumber/language-service/pull/108)) 71 | - (TypeScript) Add support for template literals without subsitutions. ([#101](https://github.com/cucumber/language-service/issues/101), [#107](https://github.com/cucumber/language-service/pull/107)) 72 | 73 | ## [1.4.1] - 2022-10-10 74 | ### Fixed 75 | - Add Rust document selector ([#131](https://github.com/cucumber/vscode/pull/113)) 76 | - Fix rust snippet fn name to lowercase ([#103](https://github.com/cucumber/language-service/issues/103), [#104](https://github.com/cucumber/language-service/pull/104)) 77 | 78 | ## [1.4.0] - 2022-10-06 79 | ### Added 80 | - Support for [Cucumber Rust](https://github.com/cucumber-rs/cucumber) ([#82](https://github.com/cucumber/language-service/issues/82), [#99](https://github.com/cucumber/language-service/pull/99)) 81 | 82 | ### Changed 83 | - The Cucumber Language Server is now started in-process ([#105](https://github.com/cucumber/vscode/pull/105)) 84 | 85 | ### Fixed 86 | - Don't throw an error when Regular Expressions have optional capture groups ([#96](https://github.com/cucumber/language-service/issues/96), [#97](https://github.com/cucumber/language-service/pull/97)). 87 | 88 | ## [1.3.0] - 2022-09-10 89 | ### Added 90 | - Add support for `.tsx` ([#87](https://github.com/cucumber/language-service/issues/87) [#90](https://github.com/cucumber/language-service/pull/90)) 91 | 92 | ### Fixed 93 | - RegExp flags in Step Definitions are preserved ([#91](https://github.com/cucumber/language-service/issues/91#issuecomment-1242243037) [#92](https://github.com/cucumber/language-service/pull/92)) 94 | 95 | ## [1.2.11] - 2022-08-29 96 | ### Fixed 97 | - Change defaults so that [pytest-bdd](https://pypi.org/project/pytest-bdd/) works out of the box ([#102](https://github.com/cucumber/vscode/pull/102)) 98 | - Trigger reindexing when Python files change ([#101](https://github.com/cucumber/vscode/pull/101)) 99 | 100 | ## [1.2.10] - 2022-08-27 101 | ### Fixed 102 | - Fix `@types/vscode` - require minimum version `1.69.0`. 103 | 104 | ## [1.2.9] - 2022-08-27 105 | ### Fixed 106 | - Fixed defaults for C# ([#93](https://github.com/cucumber/vscode/pull/93)) 107 | - Fix syntax highlighting of `Background` keyword ([#91](https://github.com/cucumber/vscode/issues/91)) 108 | - Bugfixes in [@cucumber/language-server 0.12.12](https://github.com/cucumber/language-service/releases/tag/v0.12.12) 109 | - Bugfixes in [@cucumber/language-service 0.32.0](https://github.com/cucumber/language-service/releases/tag/v0.33.0) 110 | 111 | ## [1.2.8] - 2022-07-14 112 | ### Fixed 113 | - Bugfixes in [@cucumber/language-server 0.12.11](https://github.com/cucumber/language-service/releases/tag/v0.12.11) 114 | - Bugfixes in [@cucumber/language-service 0.31.0](https://github.com/cucumber/language-service/releases/tag/v0.31.0) 115 | 116 | ## [1.2.7] - 2022-06-14 117 | ### Fixed 118 | - Better SpecFlow/C# support. See [@cucumber/language-service 0.30.0](https://github.com/cucumber/language-service/releases/tag/v0.30.0) for details. 119 | 120 | ## [1.2.6] - 2022-05-26 121 | ### Fixed 122 | - Log working directory in addition to root path 123 | 124 | ## [1.2.5] - 2022-05-26 125 | ### Fixed 126 | - Don't throw an error when generating suggestions for RegExp. 127 | 128 | ## [1.2.4] - 2022-05-26 129 | ### Fixed 130 | - Log the root path 131 | 132 | ## [1.2.3] - 2022-05-26 133 | ### Fixed 134 | - Don't crash on Cucumber Expression optionals following non-text or whitespace 135 | 136 | ## [1.2.2] - 2022-05-25 137 | ### Fixed 138 | - Generate step definition now correctly uses `Given`, `When` or `Then` for undefined steps that use `And` or `But` 139 | - Generated C# step definitions now follow SpecFlow conventions. 140 | 141 | ## [1.2.1] - 2022-05-25 142 | ### Fixed 143 | - Errors during reindexing are hopefully fixed 144 | 145 | ## [1.2.0] - 2022-05-24 146 | ### Added 147 | - Implemented generate step definition quick-fix 148 | 149 | ## [1.1.0] - 2022-05-23 150 | ### Added 151 | - Implemented go to step definition shortcut 152 | 153 | ## [1.0.9] - 2022-05-12 154 | ### Fixed 155 | - Trigger reindexing when glue code is modified 156 | 157 | ## [1.0.8] - 2022-05-12 158 | ### Fixed 159 | - Upgraded to [@cucumber/language-server 0.10.4](https://github.com/cucumber/language-server/blob/main/CHANGELOG.md#0104---2022-05-12) 160 | 161 | ## [1.0.7] - 2022-05-12 162 | ### Added 163 | - Publish to Open VSX Registry as well as VS Code Marketplace 164 | 165 | ## [1.0.6] - 2022-05-12 166 | ### Fixed 167 | - Upgraded to [@cucumber/language-server 0.10.0](https://github.com/cucumber/language-server/blob/main/CHANGELOG.md#0100---2022-05-12) 168 | 169 | ## [1.0.5] - 2022-05-11 170 | ### Fixed 171 | - Upgraded to [@cucumber/language-server 0.9.0](https://github.com/cucumber/language-server/blob/main/CHANGELOG.md#090---2022-05-11) 172 | 173 | ## [1.0.4] - 2022-05-11 174 | ### Fixed 175 | - Upload `.visx` to GitHub releases 176 | 177 | ## [1.0.3] - 2022-05-11 178 | ### Fixed 179 | - Configure automated release to VS Code Marketplace and https://open-vsx.org/ 180 | - Allow installation on any VS Code version `>= 1.63.2` 181 | 182 | ## [1.0.2] - 2022-05-11 183 | ### Fixed 184 | - Hopefully fixed marketplace release automation 185 | 186 | ## [1.0.1] - 2022-05-10 187 | ### Fixed 188 | - Fix default settings 189 | 190 | ## [1.0.0] - 2021-05-10 191 | ### Added 192 | - First release 193 | 194 | [Unreleased]: https://github.com/cucumber/vscode/compare/v1.11.0...HEAD 195 | [1.11.0]: https://github.com/cucumber/vscode/compare/v1.10.0...v1.11.0 196 | [1.10.0]: https://github.com/cucumber/vscode/compare/v1.9.0...v1.10.0 197 | [1.9.0]: https://github.com/cucumber/vscode/compare/v1.8.1...v1.9.0 198 | [1.8.1]: https://github.com/cucumber/vscode/compare/v1.8.0...v1.8.1 199 | [1.8.0]: https://github.com/cucumber/vscode/compare/v1.7.0...v1.8.0 200 | [1.7.0]: https://github.com/cucumber/vscode/compare/v1.6.0...v1.7.0 201 | [1.6.0]: https://github.com/cucumber/vscode/compare/v1.5.1...v1.6.0 202 | [1.5.1]: https://github.com/cucumber/vscode/compare/v1.5.0...v1.5.1 203 | [1.5.0]: https://github.com/cucumber/vscode/compare/v1.4.1...v1.5.0 204 | [1.4.1]: https://github.com/cucumber/vscode/compare/v1.4.0...v1.4.1 205 | [1.4.0]: https://github.com/cucumber/vscode/compare/v1.3.0...v1.4.0 206 | [1.3.0]: https://github.com/cucumber/vscode/compare/v1.2.11...v1.3.0 207 | [1.2.11]: https://github.com/cucumber/vscode/compare/v1.2.10...v1.2.11 208 | [1.2.10]: https://github.com/cucumber/vscode/compare/v1.2.9...v1.2.10 209 | [1.2.9]: https://github.com/cucumber/vscode/compare/v1.2.8...v1.2.9 210 | [1.2.8]: https://github.com/cucumber/vscode/compare/v1.2.7...v1.2.8 211 | [1.2.7]: https://github.com/cucumber/vscode/compare/v1.2.6...v1.2.7 212 | [1.2.6]: https://github.com/cucumber/vscode/compare/v1.2.5...v1.2.6 213 | [1.2.5]: https://github.com/cucumber/vscode/compare/v1.2.4...v1.2.5 214 | [1.2.4]: https://github.com/cucumber/vscode/compare/v1.2.3...v1.2.4 215 | [1.2.3]: https://github.com/cucumber/vscode/compare/v1.2.2...v1.2.3 216 | [1.2.2]: https://github.com/cucumber/vscode/compare/v1.2.1...v1.2.2 217 | [1.2.1]: https://github.com/cucumber/vscode/compare/v1.2.0...v1.2.1 218 | [1.2.0]: https://github.com/cucumber/vscode/compare/v1.1.0...v1.2.0 219 | [1.1.0]: https://github.com/cucumber/vscode/compare/v1.0.9...v1.1.0 220 | [1.0.9]: https://github.com/cucumber/vscode/compare/v1.0.8...v1.0.9 221 | [1.0.8]: https://github.com/cucumber/vscode/compare/v1.0.7...v1.0.8 222 | [1.0.7]: https://github.com/cucumber/vscode/compare/v1.0.6...v1.0.7 223 | [1.0.6]: https://github.com/cucumber/vscode/compare/v1.0.5...v1.0.6 224 | [1.0.5]: https://github.com/cucumber/vscode/compare/v1.0.4...v1.0.5 225 | [1.0.4]: https://github.com/cucumber/vscode/compare/v1.0.3...v1.0.4 226 | [1.0.3]: https://github.com/cucumber/vscode/compare/v1.0.2...v1.0.3 227 | [1.0.2]: https://github.com/cucumber/vscode/compare/v1.0.1...v1.0.2 228 | [1.0.1]: https://github.com/cucumber/vscode/compare/v1.0.0...v1.0.1 229 | [1.0.0]: https://github.com/cucumber/vscode/tree/v1.0.0 230 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Welcome! 👋 We're happy to have you here. Thank you for your interest in contributing to the [Cucumber Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=CucumberOpen.cucumber-official). 4 | 5 | This guide will provide you with the information you need to start making awesome contributions to this project. If you encounter a problem, please reach out for help through our [Discord community](https://cucumber.io/docs/community/get-in-touch#discord) or feel free to [open an Issue](https://github.com/cucumber/vscode/issues). 6 | 7 | We look forward to supporting your contributions! 💖 8 | 9 | ## Getting Started 10 | 11 | The following steps will help you to get the extension up and running locally - directly from the source code. 12 | 13 | 1. Open the repository in Visual Studio Code. 14 | 2. Ensure that the [Cucumber extension](https://marketplace.visualstudio.com/items?itemName=CucumberOpen.cucumber-official) is disabled in case you have installed it from the marketplace. 15 | 3. Run `npm install` to install the required dependencies. 16 | 4. Press `F5` to build and run the extension in a new window. 17 | 5. Open a `.feature` file - you should observe gherkin syntax highlighting. 18 | 6. Finally, open the Output window to view logs from the extension under `Output -> Cucumber Language Server`. 19 | 20 | ![Visual Studio Code Output](https://raw.githubusercontent.com/cucumber/vscode/main/images/vscode-output.png) 21 | 22 | Achievement unlocked! You are now running the extension locally! 🏆 23 | 24 | ## Modifying the Language Server 25 | 26 | Once you have completed [getting started](#getting-started), you may be wondering how you can begin modifying the implementation. 🤔 27 | 28 | 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. 29 | 30 | 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: 31 | 32 | ```console 33 | directory/ 34 | ├── language-server/ 35 | ├── language-service/ 36 | └── vscode/ 37 | ``` 38 | 39 | 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. 40 | 3. Now for the tricky part - we need to build and link to the packages of the repositories we've just cloned. 41 | 42 | a. Inside the __Language Service__ repository, build and link the package to your global node modules. 43 | 44 | When you run `npm link` in the package directory, npm creates a symlink in the global node modules directory that links to the package. This makes the package appear as if it's globally installed on your system. 45 | 46 | ```console 47 | npm install 48 | npm link 49 | npm run build 50 | ``` 51 | 52 | b. Repeat the same inside the __Language Server__ repository, this time linking back to the Language Service we just built - so the Language Server uses our local version. 53 | 54 | ```console 55 | npm install 56 | npm link @cucumber/language-service 57 | npm link 58 | npm run build 59 | ``` 60 | 61 | c. Finally, within the __extension__ repository, link back to the Language Server we just built. 62 | 63 | ```console 64 | npm install 65 | npm link @cucumber/language-server 66 | ``` 67 | 68 | You can verify that links are correctly configured by executing the below command in each respective repository 69 | 70 | ```console 71 | la node_modules/@cucumber 72 | lrwxr-xr-x 1 username staff 24 Jan 22 09:32 language-server -> ../../../language-server 73 | ``` 74 | 75 | 4. Now open the extension repository in Visual Studio Code. 76 | 5. As before, press `F5` to build and run the extension in a new window. 77 | 78 | Phew! That was tough - but all going well, you did it! 🙌 You can now start modifying the implementation and observe those changes running in Visual Studio Code - awesome! 😎 79 | 80 | **Note:** If you require further guidance on these steps, watch a [walkthrough on linking with the GitLab VSCode extension](https://www.youtube.com/watch?app=desktop&v=Re1pwIEsSio) - which has a similar setup. 81 | 82 | ### Rebuilding 83 | 84 | If you need to make further changes to these packages, you have to rebuild them but relinking is not necessary e.g. you only need to run `npm run build` in the Language Service. To load your changes, either reload the window running the extension (`Ctrl+R` or `Cmd+R` on Mac) or relaunch the extension from the debug toolbar in the window that you are developing the extension. 85 | 86 | For debugging the extension, set breakpoints within the code. 🐞 87 | 88 | ### Check everything is working 89 | 90 | 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. 91 | 92 | Make a small change to a selected snippet - such as adding a comment; rebuild the language service and reload the extension (see [Rebuilding](#rebuilding)). Ensure you have an existing step definition matching extension settings (see [generate step definition](README.md#generate-step-definition)) and a feature file containing an undefined step. Finally, click the `Quick Fix` on the undefined step to generate the step definition. You should see your template changes reflected in the output. 93 | 94 | If your changes are not reflected or something went wrong, we would love to know what happened. Please [open an issue](https://github.com/cucumber/vscode/issues) and provide as much detail as possible: versions, operating system, error messages, etc. We will help you resolve the issue. 🤝 95 | 96 | ## Preparing Your Pull Request 97 | 98 | Before submitting a pull request, there are a few actions that we must ensure to carry out. 99 | 100 | - Format all code to align with project coding standards. This is executed by the pre-commit hook by default. 101 | 102 | ```console 103 | npm run eslint-fix 104 | ``` 105 | 106 | - Run the update command for any modifications to [extension settings](README.md#extension-settings) in `README.md`, to ensure they are reflected in `package.json`. This is executed by the pre-commit hook by default. 107 | 108 | ```console 109 | npm run update-settings-docs 110 | ``` 111 | 112 | - Update `.vscodeignore` with the paths of any new or modified files or directories that should be included in the packaged version of the extension. 113 | 114 | - Package the extension locally and ensure the command runs without error - see [Packaging Extensions](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#packaging-extensions) for more detail. 115 | 116 | ```console 117 | npm run package 118 | ``` 119 | 120 | - [Perform manual testing](RELEASING.md#perform-manual-testing) and verify that the [extension features](README.md#features) are working as expected. 121 | 122 | - Update the [CHANGELOG](CHANGELOG.md) with any changes that users should be made aware of. 123 | 124 | Your pull request should be good to go. 125 | 126 | ## Resources 127 | 128 | The following resources are useful in the development of this extension. 129 | 130 | - [Visual Studio Code Extension documentation](https://code.visualstudio.com/api) - Comprehensive documentation covering capabilities, guides and guidelines for Visual Studio Code extensions. 131 | - [Contributing Guidelines for the Cucumber Language Service](https://github.com/cucumber/language-service/blob/main/CONTRIBUTING.md) - Guidance for contributing to the [Cucumber Language Service](https://github.com/cucumber/language-service), the core component responsible for implementing the majority of features in this extension. 132 | - Type definitions for the Visual Studio Code Extension API release used by this extension can be found within the file `node_modules/@types/vscode/index.d.ts`. 133 | 134 | ## Code of Conduct 135 | 136 | We want to create a welcoming environment for everyone who is interested in contributing. Visit our [Code of Conduct page](https://github.com/cucumber/common/blob/main/CODE_OF_CONDUCT.md) to learn more about our commitment to an open and welcoming environment. 137 | 138 | ## Feedback 139 | 140 | Making this extension easier to contribute to is truly important. If you feel the contributing guidelines or infrastructure could be improved, please [create an issue](https://github.com/cucumber/vscode/issues) or raise a pull request - your input is most welcome. 141 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Cucumber Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 | Cucumber for VSCode 5 |

6 |

7 | Official Visual Studio Code extension for Cucumber and Gherkin 8 |

9 | 10 |

11 | 12 | Visual Studio Marketplace Version 13 | 14 | 15 | Visual Studio Marketplace Installs 16 | 17 | 18 | Visual Studio Marketplace Downloads 19 | 20 | 21 | Visual Studio Marketplace Rating (Stars) 22 | 23 | 24 | build 25 | 26 |

27 | 28 | Maintained by the [Cucumber team](https://github.com/cucumber/) and powered by the [Cucumber Language Server](https://github.com/cucumber/language-server#readme). 29 | 30 | Available from the [Open VSX Registry](https://open-vsx.org/extension/CucumberOpen/cucumber-official) and 31 | [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=CucumberOpen.cucumber-official). 32 | 33 | ## Features 34 | 35 | - ⌨️ [Autocomplete steps](#autocomplete) 36 | - 📍 [Go to step definition](#go-to-step-definition) 37 | - 🪄 [Generate step definition](#generate-step-definition) 38 | - 💄 [Syntax highlighting](#syntax-highlighting) 39 | - ✨ [Formatting](#formatting) 40 | - 🌎 [Gherkin localisation](#gherkin-localisation) 41 | - 📖 [Language support](#language-support) 42 | - C#/SpecFlow 43 | - Go/Godog 44 | - Java 45 | - JavaScript 46 | - PHP 47 | - Python/Behave 48 | - Ruby 49 | - Rust 50 | - TypeScript 51 | - 🗂 [Document outline](#document-outline) 52 | - 🥒 [Feature file icons](#feature-file-icons) 53 | 54 | ### Autocomplete 55 | 56 | ![Autocomplete](https://raw.githubusercontent.com/cucumber/vscode/main/images/autocomplete.gif) 57 | 58 | When you start typing a step, you will see auto-complete suggestions 59 | based on existing step definitions and Gherkin steps. 60 | 61 | The suggestions are more helpful if your step definitions use 62 | [Cucumber Expressions](https://github.com/cucumber/cucumber-expressions#readme) 63 | but you'll also get suggestions if they use Regular Expressions. 64 | 65 | ### Go to step definition 66 | 67 | ![Go to step definition](https://raw.githubusercontent.com/cucumber/vscode/main/images/goto-step-definition.gif) 68 | 69 | You can quickly navigate from a Gherkin step to a step definition. 70 | 71 | ### Generate step definition 72 | 73 | ![Generate step definition](https://raw.githubusercontent.com/cucumber/vscode/main/images/generate-step-definition.gif) 74 | 75 | Generate step definition snippets with a quick fix - `⌘` + `.` (MacOS) or 76 | `Ctrl` + `.` (Windows). 77 | 78 | _IMPORTANT_: Generate step definition will only be enabled 79 | if there is at least one existing step definition. This is 80 | so that the extension can determine the programming language 81 | for the step definition, and provide choices for existing files 82 | to add it to. 83 | 84 | ### Syntax highlighting 85 | 86 | ![Syntax highlighting](https://raw.githubusercontent.com/cucumber/vscode/main/images/syntax-highlighting.gif) 87 | 88 | Gherkin keywords and step parameters are highlighted. 89 | Undefined steps and syntax errors are underlined. 90 | 91 | ### Formatting 92 | 93 | ![Formatting](https://raw.githubusercontent.com/cucumber/vscode/main/images/formatting.gif) 94 | 95 | Gherkin documents are formatted using two space indentation. 96 | 97 | Numeric cells are right-aligned (as in Excel). Non-numeric cells are left-aligned. 98 | 99 | ### Document Outline 100 | 101 | ![Document outline](https://raw.githubusercontent.com/cucumber/vscode/main/images/document-outline.gif) 102 | 103 | The Outline panel displays an outline of the Gherkin document, 104 | making it easy to navigate between scenarios. 105 | 106 | ### Gherkin Localisation 107 | 108 | Gherkin supports many translations. To specify a translation, include a `# language: ` header in your feature file, with a supported language key from the [localisation documentation](https://cucumber.io/docs/gherkin/languages/). 109 | 110 | ![Localisation](https://raw.githubusercontent.com/cucumber/vscode/main/images/localisation.png) 111 | 112 | New translations or updates are welcome and can be submitted through the [gherkin parser](https://github.com/cucumber/gherkin). 113 | 114 | ### Language Support 115 | 116 | Step definitions support is provided for [different languages and frameworks](#features). 117 | 118 | If you experience an issue with a supported language, please [raise a detailed bug report](https://github.com/cucumber/vscode/issues) or reach out for help through [our Discord community](https://cucumber.io/docs/community/get-in-touch#discord). 119 | 120 | If your language or framework is unsupported, please [open an issue](https://github.com/cucumber/language-service/issues) or [raise a pull request](https://github.com/cucumber/language-service/pulls) in the [Cucumber Language Service](https://github.com/cucumber/language-service) - where language support is implemented. 121 | 122 | ### Feature File Icons 123 | 124 | The Cucumber icon is applied to all feature files in your workspace. This replaces the default document icon, making it easier to identify your feature files at a glance. 125 | 126 | ![Feature file icon](https://raw.githubusercontent.com/cucumber/vscode/main/images/feature-file-icons.png) 127 | 128 | ## Extension Settings 129 | 130 | In most cases you shouldn't need to specify any settings 131 | as the extension comes with reasonable defaults. 132 | 133 | If your `.feature` files and step definition files are 134 | in an unconventional file structure, you need to change the 135 | settings to make autocomplete work properly. 136 | 137 | With multi-root workspaces, you will need to either specify glob paths for each workspace individually (e.g. `workspace-a/features/*.feature` and `workspace-b/features/*.feature`) or specify a glob path that matches all of them (e.g. `**/features/*.feature`). See [VSCode documentation for configuring a multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces#_workspace-file-schema). 138 | 139 | ### `cucumber.features` 140 | 141 | [//]: # () 142 | The `cucumber.features` setting overrides where the extension 143 | should look for `.feature` files. 144 | 145 | If no feature files are found, [autocomplete](#autocomplete) 146 | will not work. 147 | 148 | Default value: 149 | 150 | ```json 151 | { 152 | "cucumber.features": [ 153 | "src/test/**/*.feature", 154 | "features/**/*.feature", 155 | "tests/**/*.feature", 156 | "*specs*/**/*.feature" 157 | ] 158 | } 159 | ``` 160 | 161 | [//]: # () 162 | 163 | ### `cucumber.glue` 164 | 165 | [//]: # () 166 | The `cucumber.glue` setting overrides where the extension 167 | should look for source code where step definitions and 168 | parameter types are defined. 169 | 170 | If no glue files are found, [autocomplete](#autocomplete) 171 | will not work, and all Gherkin steps will be underlined as 172 | undefined. [Generate step definition](#generate-step-definition) 173 | will not work either. 174 | 175 | Default value: 176 | 177 | ```json 178 | { 179 | "cucumber.glue": [ 180 | "*specs*/**/*.cs", 181 | "features/**/*.js", 182 | "features/**/*.jsx", 183 | "features/**/*.php", 184 | "features/**/*.py", 185 | "features/**/*.rs", 186 | "features/**/*.rb", 187 | "features/**/*.ts", 188 | "features/**/*.tsx", 189 | "features/**/*_test.go", 190 | "src/test/**/*.java", 191 | "tests/**/*.py", 192 | "tests/**/*.rs" 193 | ] 194 | } 195 | ``` 196 | 197 | [//]: # () 198 | 199 | ### `cucumber.parameterTypes` 200 | 201 | [//]: # () 202 | Override the `cucumber.parameterTypes` setting if your Cucumber Expressions 203 | are using [Custom Parameter Types](https://github.com/cucumber/cucumber-expressions#custom-parameter-types) that are defined outside your `cucumber.glue` setting. 204 | 205 | Parameter Types in the `cucumber.glue` globs will be picked up automatically. 206 | 207 | Default value: 208 | 209 | ```json 210 | { 211 | "cucumber.parameterTypes": [] 212 | } 213 | ``` 214 | 215 | For example, if you're using the `actor` parameter type from [@cucumber/screenplay](https://github.com/cucumber/screenplay.js#actors) you'll have to declare this in the `parameterTypes` setting: 216 | 217 | ````json 218 | { 219 | "cucumber.parameterTypes": [ 220 | { "name": "actor", "regexp": "[A-Z][a-z]+" } 221 | ] 222 | } 223 | ```` 224 | 225 | [//]: # () 226 | 227 | ## Feedback 228 | 229 | If you discover a bug, or have a suggestion for a feature request, please 230 | submit an [issue](https://github.com/cucumber/vscode/issues). 231 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing 2 | 3 | ## Perform Manual Testing 4 | 5 | Before a release it is important to do a manual test. 6 | We haven't invested in automated tests to catch regressions. 7 | 8 | npm install 9 | code . 10 | 11 | Run the extension (opens a new window) and check all the functionality such as: 12 | 13 | * Syntax highlighting 14 | * Autocomplete 15 | * Formatting 16 | 17 | ## GitHub Actions release 18 | 19 | See [.github/RELEASING](https://github.com/cucumber/.github/blob/main/RELEASING.md). 20 | 21 | *IMPORTANT:* After updating dependencies, revert both `engines.vscode` and `"@types/vscode"` to the *same* version. 22 | 23 | Use a version that is 2 *minor* versions behind the latest version so that the extension doesn't require the latest version of Visual Studio Code. 24 | -------------------------------------------------------------------------------- /images/autocomplete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/autocomplete.gif -------------------------------------------------------------------------------- /images/document-outline.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/document-outline.gif -------------------------------------------------------------------------------- /images/feature-file-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/feature-file-icons.png -------------------------------------------------------------------------------- /images/formatting.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/formatting.gif -------------------------------------------------------------------------------- /images/generate-step-definition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/generate-step-definition.gif -------------------------------------------------------------------------------- /images/goto-step-definition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/goto-step-definition.gif -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/icon.png -------------------------------------------------------------------------------- /images/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/localisation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/localisation.png -------------------------------------------------------------------------------- /images/syntax-highlighting.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/syntax-highlighting.gif -------------------------------------------------------------------------------- /images/vscode-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cucumber/vscode/0c380d3ddaf8902501255d397a7c2b395149415b/images/vscode-output.png -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#" 4 | }, 5 | "autoClosingPairs": [ 6 | ["\"\"\"", "\"\"\""], 7 | ["```", "```"] 8 | ], 9 | "surroundingPairs": [ 10 | ["\"\"\"", "\"\"\""], 11 | ["```", "```"] 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cucumber-official", 3 | "displayName": "Cucumber", 4 | "description": "Cucumber for Visual Studio Code", 5 | "version": "1.11.0", 6 | "publisher": "CucumberOpen", 7 | "engines": { 8 | "vscode": "^1.82.0" 9 | }, 10 | "categories": [ 11 | "Programming Languages", 12 | "Formatters", 13 | "Linters", 14 | "Testing" 15 | ], 16 | "keywords": [ 17 | "Cucumber", 18 | "Gherkin", 19 | "Feature" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "git://github.com/cucumber/vscode.git" 24 | }, 25 | "icon": "images/icon.png", 26 | "main": "./out/extension.js", 27 | "contributes": { 28 | "languages": [ 29 | { 30 | "id": "cucumber", 31 | "aliases": [ 32 | "Cucumber" 33 | ], 34 | "extensions": [ 35 | ".feature" 36 | ], 37 | "configuration": "./language-configuration.json", 38 | "icon": { 39 | "light": "./images/icon.svg", 40 | "dark": "./images/icon.svg" 41 | } 42 | } 43 | ], 44 | "configurationDefaults": { 45 | "[cucumber]": { 46 | "editor.semanticHighlighting.enabled": true 47 | } 48 | }, 49 | "configuration": { 50 | "title": "Cucumber", 51 | "properties": { 52 | "cucumber.features": { 53 | "markdownDescription": "The `cucumber.features` setting overrides where the extension\nshould look for `.feature` files.\n\nIf no feature files are found, [autocomplete](#autocomplete)\nwill not work.\n\nDefault value:\n\n```json\n{\n \"cucumber.features\": [\n \"src/test/**/*.feature\",\n \"features/**/*.feature\",\n \"tests/**/*.feature\",\n \"*specs*/**/*.feature\"\n ]\n}\n```", 54 | "type": "array", 55 | "required": false, 56 | "default": [ 57 | "src/test/**/*.feature", 58 | "features/**/*.feature", 59 | "tests/**/*.feature", 60 | "*specs*/**/*.feature" 61 | ] 62 | }, 63 | "cucumber.glue": { 64 | "markdownDescription": "The `cucumber.glue` setting overrides where the extension\nshould look for source code where step definitions and\nparameter types are defined.\n\nIf no glue files are found, [autocomplete](#autocomplete)\nwill not work, and all Gherkin steps will be underlined as\nundefined. [Generate step definition](#generate-step-definition)\nwill not work either.\n\nDefault value:\n\n```json\n{\n \"cucumber.glue\": [\n \"*specs*/**/*.cs\",\n \"features/**/*.js\",\n \"features/**/*.jsx\",\n \"features/**/*.php\",\n \"features/**/*.py\",\n \"features/**/*.rs\",\n \"features/**/*.rb\",\n \"features/**/*.ts\",\n \"features/**/*.tsx\",\n \"features/**/*_test.go\",\n \"src/test/**/*.java\",\n \"tests/**/*.py\",\n \"tests/**/*.rs\"\n ]\n}\n```", 65 | "type": "array", 66 | "required": false, 67 | "default": [ 68 | "*specs*/**/*.cs", 69 | "features/**/*.js", 70 | "features/**/*.jsx", 71 | "features/**/*.php", 72 | "features/**/*.py", 73 | "features/**/*.rs", 74 | "features/**/*.rb", 75 | "features/**/*.ts", 76 | "features/**/*.tsx", 77 | "features/**/*_test.go", 78 | "src/test/**/*.java", 79 | "tests/**/*.py", 80 | "tests/**/*.rs" 81 | ] 82 | }, 83 | "cucumber.parameterTypes": { 84 | "markdownDescription": "Override the `cucumber.parameterTypes` setting if your Cucumber Expressions\nare using [Custom Parameter Types](https://github.com/cucumber/cucumber-expressions#custom-parameter-types) that are defined outside your `cucumber.glue` setting.\n\nParameter Types in the `cucumber.glue` globs will be picked up automatically.\n\nDefault value:\n\n```json\n{\n \"cucumber.parameterTypes\": []\n}\n```\n\nFor example, if you're using the `actor` parameter type from [@cucumber/screenplay](https://github.com/cucumber/screenplay.js#actors) you'll have to declare this in the `parameterTypes` setting:\n\n````json\n{\n \"cucumber.parameterTypes\": [\n { \"name\": \"actor\", \"regexp\": \"[A-Z][a-z]+\" }\n ]\n}\n````", 85 | "type": "array", 86 | "required": false, 87 | "default": [] 88 | } 89 | } 90 | } 91 | }, 92 | "scripts": { 93 | "vscode:prepublish": "npm run build", 94 | "esbuild-extension": "esbuild ./src/extension.ts --external:vscode --bundle --outfile=out/extension.js --format=cjs --platform=node --minify --sourcemap", 95 | "build": "npm run esbuild-extension", 96 | "compile": "tsc --build", 97 | "prepare": "husky && npm run copy-wasms", 98 | "copy-wasms": "mkdir -p out && cp node_modules/@cucumber/language-service/dist/*.wasm out", 99 | "pretest": "npm run compile", 100 | "eslint": "eslint src --ext ts", 101 | "eslint-fix": "eslint src --ext ts --max-warnings 0 --fix", 102 | "test": "node ./dist/src/test/runTest.js", 103 | "prepublishOnly": "npm run update-settings-docs", 104 | "update-settings-docs": "./scripts/update-settings-docs.sh", 105 | "vscode-types-compatible": "./scripts/vscode-types-compatible.sh", 106 | "package": "vsce package", 107 | "publish": "vsce publish" 108 | }, 109 | "lint-staged": { 110 | "README.md": "npm run update-settings-docs", 111 | "src/**/*.ts": "npm run eslint-fix" 112 | }, 113 | "dependencies": { 114 | "@cucumber/language-server": "1.7.0", 115 | "vscode-languageclient": "9.0.1" 116 | }, 117 | "devDependencies": { 118 | "@types/glob": "8.1.0", 119 | "@types/mocha": "10.0.10", 120 | "@types/vscode": "1.82.0", 121 | "@typescript-eslint/eslint-plugin": "7.18.0", 122 | "@typescript-eslint/parser": "7.18.0", 123 | "@vscode/test-electron": "2.5.2", 124 | "@vscode/vsce": "3.5.0", 125 | "esbuild": "0.25.5", 126 | "eslint": "8.57.1", 127 | "eslint-config-prettier": "10.1.5", 128 | "eslint-plugin-import": "2.31.0", 129 | "eslint-plugin-n": "17.19.0", 130 | "eslint-plugin-prettier": "5.4.1", 131 | "eslint-plugin-simple-import-sort": "12.1.1", 132 | "glob": "11.0.2", 133 | "husky": "9.1.7", 134 | "lint-staged": "16.1.0", 135 | "mocha": "11.5.0", 136 | "prettier": "3.5.3", 137 | "typescript": "5.8.3" 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /scripts/update-settings-docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script updates the docs for the configuration properties. 3 | # It extracts sections from the README.md and writes them into the markdownDescription 4 | # fields in `package.json`. 5 | 6 | function section { 7 | file=$1 8 | setting=$2 9 | sed -n "/\[\/\/\]: # (<${setting}>)/,/\[\/\/\]: # (<\/${setting}>)/p" "${file}" | tail -n +2 | sed -e '$ d' 10 | } 11 | 12 | function jsonReplace { 13 | file=$1 14 | variable=$2 15 | value=$3 16 | json=$4 17 | 18 | original=$(cat "${file}") 19 | 20 | if [ "${json}" = 1 ]; then 21 | json=$(jq --argjson value "${value}" "${variable} = \$value" "${file}") 22 | else 23 | json=$(jq --arg value "${value}" "${variable} = \$value" "${file}") 24 | fi 25 | 26 | # Compare the original and updated contents 27 | if [ "${json}" != "${original}" ]; then 28 | echo "${json}" > "${file}" 29 | return 1 30 | else 31 | return 0 32 | fi 33 | } 34 | 35 | function updateMarkdownDescription { 36 | setting=$1 37 | markdown=$(section 'README.md' "${setting}") 38 | jsonReplace \ 39 | 'package.json' \ 40 | ".contributes.configuration.properties.\"${setting}\".markdownDescription" \ 41 | "${markdown}" \ 42 | 0 43 | updatedDescription=$? 44 | 45 | default=$(echo "${markdown}" | sed -n "/^\`\`\`json$/,/^\`\`\`$/p" | tail -n +2 | sed -e '$ d' | jq ".\"${setting}\"") 46 | jsonReplace \ 47 | 'package.json' \ 48 | ".contributes.configuration.properties.\"${setting}\".default" \ 49 | "${default}" \ 50 | 1 51 | updatedDefault=$? 52 | 53 | if [ "${updatedDescription}" = 1 ] || [ "${updatedDefault}" = 1 ]; then 54 | return 1 55 | else 56 | return 0 57 | fi 58 | } 59 | 60 | updateMarkdownDescription "cucumber.features" 61 | updateResult1=$? 62 | updateMarkdownDescription "cucumber.glue" 63 | updateResult2=$? 64 | updateMarkdownDescription "cucumber.parameterTypes" 65 | updateResult3=$? 66 | 67 | if [ "$updateResult1" -eq 1 ] || [ "$updateResult2" -eq 1 ] || [ "$updateResult3" -eq 1 ]; then 68 | echo "The settings descriptions and default values in 'package.json' do not match those specified in 'README.md'. Updating 'package.json' to match." 69 | exit 1 70 | else 71 | echo "The settings descriptions and default values in 'package.json' match those specified in 'README.md'." 72 | exit 0 73 | fi 74 | -------------------------------------------------------------------------------- /scripts/vscode-types-compatible.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script validates whether the @types/vscode package version matches the VSCode 3 | # compatibility engine version. If the types exceeds the engine version, then the 4 | # extension will not run. 5 | 6 | # Parse package.json and get the versions of the two packages 7 | vscodeVersion=$(jq -r '.engines.vscode' package.json) 8 | vscodeSemanticVersion=$(echo $vscodeVersion | sed 's/\^//g') 9 | vscodeTypesVersion=$(jq -r '.devDependencies["@types/vscode"]' package.json) 10 | 11 | # Compare the versions 12 | if [ "$vscodeTypesVersion" != "$vscodeSemanticVersion" ]; then 13 | echo "The @types/vscode package version ($vscodeTypesVersion) does not match the VSCode compatibility engine version ($vscodeSemanticVersion). Please update @types/vscode to match." 14 | exit 1 15 | else 16 | echo "The @types/vscode package version ($vscodeTypesVersion) matches the VSCode compatibility engine version ($vscodeSemanticVersion)." 17 | exit 0 18 | fi 19 | -------------------------------------------------------------------------------- /src/VscodeFiles.ts: -------------------------------------------------------------------------------- 1 | import { Files } from '@cucumber/language-server' 2 | import { FileSystem, Uri, workspace } from 'vscode' 3 | 4 | export class VscodeFiles implements Files { 5 | constructor(private readonly fs: FileSystem) {} 6 | 7 | async exists(uri: string): Promise { 8 | try { 9 | await this.fs.stat(Uri.parse(uri)) 10 | return true 11 | } catch { 12 | return false 13 | } 14 | } 15 | 16 | async readFile(uri: string): Promise { 17 | const data = await this.fs.readFile(Uri.parse(uri)) 18 | return new TextDecoder().decode(data) 19 | } 20 | 21 | async findUris(glob: string): Promise { 22 | const uris = await workspace.findFiles(glob) 23 | return uris.map((file) => file.toString()) 24 | } 25 | 26 | relativePath(uri: string): string { 27 | return workspace.asRelativePath(Uri.parse(uri), true) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import { startEmbeddedServer } from '@cucumber/language-server/wasm' 2 | import vscode from 'vscode' 3 | import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node' 4 | 5 | import { VscodeFiles } from './VscodeFiles' 6 | 7 | let client: LanguageClient 8 | 9 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 10 | export async function activate(context: vscode.ExtensionContext) { 11 | const serverOptions: ServerOptions = async () => 12 | startEmbeddedServer( 13 | __dirname, 14 | () => new VscodeFiles(vscode.workspace.fs), 15 | () => undefined 16 | ) 17 | 18 | const clientOptions: LanguageClientOptions = { 19 | // We need to list all supported languages here so that 20 | // the language server is notified to reindex when a file changes 21 | // https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers 22 | documentSelector: [ 23 | { scheme: 'file', language: 'csharp' }, 24 | { scheme: 'file', language: 'cucumber' }, 25 | { scheme: 'file', language: 'java' }, 26 | { scheme: 'file', language: 'javascript' }, 27 | { scheme: 'file', language: 'php' }, 28 | { scheme: 'file', language: 'ruby' }, 29 | { scheme: 'file', language: 'typescript' }, 30 | { scheme: 'file', language: 'typescriptreact' }, 31 | { scheme: 'file', language: 'python' }, 32 | { scheme: 'file', language: 'rust' }, 33 | ], 34 | } 35 | 36 | client = new LanguageClient('Cucumber', 'Cucumber Language Server', serverOptions, clientOptions) 37 | 38 | await client.start() 39 | } 40 | 41 | // this method is called when your extension is deactivated 42 | export async function deactivate() { 43 | await client.stop() 44 | } 45 | -------------------------------------------------------------------------------- /src/test/runTest.ts: -------------------------------------------------------------------------------- 1 | import { runTests } from '@vscode/test-electron' 2 | import path from 'path' 3 | 4 | async function main() { 5 | if (process.env['CI']) { 6 | // https://app.circleci.com/pipelines/github/cucumber/common/7908/workflows/10de1a58-5b66-4834-8a5e-e9ac11748e43/jobs/311298 7 | console.error('Skipping test of vscode plugin in CI') 8 | return 9 | } 10 | 11 | try { 12 | // The folder containing the Extension Manifest package.json 13 | // Passed to `--extensionDevelopmentPath` 14 | const extensionDevelopmentPath = path.resolve(__dirname, '../../') 15 | 16 | // The path to test runner 17 | // Passed to --extensionTestsPath 18 | const extensionTestsPath = path.resolve(__dirname, './suite/index') 19 | 20 | // Download VS Code, unzip it and run the integration test 21 | await runTests({ extensionDevelopmentPath, extensionTestsPath }) 22 | } catch (err) { 23 | console.error('Failed to run tests') 24 | process.exit(1) 25 | } 26 | } 27 | 28 | main() 29 | -------------------------------------------------------------------------------- /src/test/suite/extension.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert' 2 | // You can import and use all API from the 'vscode' module 3 | // as well as import your extension to test it 4 | import * as vscode from 'vscode' 5 | // import * as myExtension from '../../extension'; 6 | 7 | suite('Extension Test Suite', () => { 8 | vscode.window.showInformationMessage('Start all tests.') 9 | 10 | test('Sample test', () => { 11 | assert.strictEqual(-1, [1, 2, 3].indexOf(5)) 12 | assert.strictEqual(-1, [1, 2, 3].indexOf(0)) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /src/test/suite/index.ts: -------------------------------------------------------------------------------- 1 | import { glob } from 'glob' 2 | import Mocha from 'mocha' 3 | import path from 'path' 4 | 5 | export function run(): Promise { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | color: true, 10 | }) 11 | 12 | const testsRoot = path.resolve(__dirname, '..') 13 | return glob('**/**.test.js', { cwd: testsRoot }).then((files) => { 14 | // Add files to the test suite 15 | files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))) 16 | 17 | return new Promise((c, e) => { 18 | try { 19 | // Run the mocha test 20 | mocha.run((failures) => { 21 | if (failures > 0) { 22 | e(new Error(`${failures} tests failed.`)) 23 | } else { 24 | c() 25 | } 26 | }) 27 | } catch (err) { 28 | console.error(err) 29 | e(err) 30 | } 31 | }) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "dist", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "allowJs": false, 8 | "resolveJsonModule": true, 9 | "esModuleInterop": true, 10 | "noImplicitAny": true, 11 | "downlevelIteration": true, 12 | "skipLibCheck": true, 13 | "strictNullChecks": true, 14 | "experimentalDecorators": true, 15 | "module": "CommonJS", 16 | "lib": [ 17 | "ES6", 18 | "dom" 19 | ], 20 | "target": "ES6", 21 | "moduleResolution": "node", 22 | "allowSyntheticDefaultImports": true, 23 | "jsx": "react" 24 | }, 25 | "include": [ 26 | "package.json", 27 | "src", 28 | "test" 29 | ] 30 | } 31 | --------------------------------------------------------------------------------