├── .eslintrc.json ├── .gitignore ├── .vscode ├── extensions.json └── launch.json ├── .vscodeignore ├── CHANGELOG.md ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── dotenv.png ├── extension.js ├── jsconfig.json ├── lib ├── autocloaking.js ├── autocompletion.js ├── commands.js ├── decorations.js ├── fileAssociations.js ├── helpers.js ├── peeking.js ├── providers.js └── settings.js ├── media ├── install.png └── sidebar-icon.svg ├── overview.gif ├── package-lock.json ├── package.json ├── syntaxes ├── dotenv-legacy.tmLanguage.json ├── dotenv-simple.tmLanguage.json ├── dotenv.tmLanguage.json └── language-configuration.json └── test ├── runTest.js └── suite ├── examples ├── .env.example ├── csharp.cs ├── dart.dart ├── elixir.exs ├── go.go ├── java.java ├── javascript.js ├── kotlin.kt ├── php.php ├── python.py ├── ruby.rb └── rust.rs ├── extension.test.js ├── index.js └── lib ├── helpers.test.js ├── providers.test.js └── settings.test.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": false, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true, 7 | "mocha": true 8 | }, 9 | "parserOptions": { 10 | "ecmaVersion": 2018, 11 | "ecmaFeatures": { 12 | "jsx": true 13 | }, 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "no-const-assign": "warn", 18 | "no-this-before-super": "warn", 19 | "no-undef": "warn", 20 | "no-unreachable": "warn", 21 | "no-unused-vars": "warn", 22 | "constructor-super": "warn", 23 | "valid-typeof": "warn" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode-test/ 3 | .vscode/settings.json 4 | *.vsix 5 | .DS_Store 6 | 7 | .env* 8 | !.env.project 9 | !.env.vault 10 | !.env.example -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | }, 16 | { 17 | "name": "Extension Tests", 18 | "type": "extensionHost", 19 | "request": "launch", 20 | "args": [ 21 | "--extensionDevelopmentPath=${workspaceFolder}", 22 | "--extensionTestsPath=${workspaceFolder}/test/suite/index" 23 | ] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | test/** 4 | .gitignore 5 | .yarnrc 6 | vsc-extension-quickstart.md 7 | **/jsconfig.json 8 | **/*.map 9 | **/.eslintrc.json 10 | 11 | .DS_Store 12 | .env* 13 | !.env.project 14 | !.env.vault 15 | !.env.example 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | All notable changes to the Official Dotenv VS Code extension will be documented in this file. 4 | 5 | ## [Unreleased](https://github.com/dotenv-org/dotenv-vscode/compare/v0.28.0...master) 6 | 7 | ## [0.28.1](https://github.com/dotenv-org/dotenv-vscode/compare/v0.28.1...v0.28.0) (2023-11-04) 8 | 9 | ### Added 10 | 11 | * Add additional files to `.vscodeignore` 12 | 13 | ## [0.28.0](https://github.com/dotenv-org/dotenv-vscode/compare/v0.28.0...v0.27.3) (2023-07-02) 14 | 15 | ### Changed 16 | 17 | * Bumped `dotenv-vault` cli to `1.24.0` 18 | 19 | ## [0.27.3](https://github.com/dotenv-org/dotenv-vscode/compare/v0.27.3...v0.27.2) (2023-06-15) 20 | 21 | ### Changed 22 | 23 | * Improved environment variable capture [#96](https://github.com/dotenv-org/dotenv-vscode/pull/96) 24 | 25 | ## [0.27.2](https://github.com/dotenv-org/dotenv-vscode/compare/v0.27.2...v0.27.1) (2023-06-15) 26 | 27 | ### Added 28 | 29 | * For autocompletion, respect secret peeking setting off or on [#97](https://github.com/dotenv-org/dotenv-vscode/pull/97) 30 | 31 | ## [0.27.1](https://github.com/dotenv-org/dotenv-vscode/compare/v0.27.1...v0.27.0) (2023-06-15) 32 | 33 | ### Changed 34 | 35 | * `await` for async function to set `files.associations` in extension.js 36 | 37 | ## [0.27.0](https://github.com/dotenv-org/dotenv-vscode/compare/v0.27.0...v0.26.0) (2023-06-15) 38 | 39 | ### Added 40 | 41 | * Write to `settings.json` with `files.associations` to make sure `.env` files do not get the properties association. [#77](https://github.com/dotenv-org/dotenv-vscode/issues/77) 42 | 43 | ## 0.26.0 44 | 45 | ### Added 46 | 47 | * Add setting to turn off in-code secret peeking. [#95](https://github.com/dotenv-org/dotenv-vscode/pull/95) 48 | 49 | ## 0.25.0 50 | 51 | ### Added 52 | 53 | * Add setting to change the cloak icon. 54 | 55 | ## 0.24.3 56 | 57 | ### Changed 58 | 59 | * 🐞 Fix `textMateRules` setting when not present in user machine `settings.json` file. [#94](https://github.com/dotenv-org/dotenv-vscode/pull/94) 60 | 61 | ## 0.24.2 62 | 63 | ### Changed 64 | 65 | * Changed theme to `highContrast` on Marketplace. 66 | 67 | ## 0.24.1 68 | 69 | ### Fixed 70 | 71 | * Reverted code causing autocloaking to fail [#93](https://github.com/dotenv-org/dotenv-vscode/pull/93) 72 | 73 | ## 0.24.0 74 | 75 | ### Added 76 | 77 | * Added `import.meta.env` format for javascript highlighting/autocomplete [#88](https://github.com/dotenv-org/dotenv-vscode/pull/88) 78 | 79 | ### Fixed 80 | 81 | * Issue where values wouldn't unhide after being autocloaked [#85](https://github.com/dotenv-org/dotenv-vscode/issues/85) [#86](https://github.com/dotenv-org/dotenv-vscode/issues/86) [#87](https://github.com/dotenv-org/dotenv-vscode/pull/87) 82 | 83 | ## 0.23.0 84 | 85 | ### Added 86 | 87 | * Added autocomplete and hover support for elixir. [#48](https://github.com/dotenv-org/dotenv-vscode/issues/48) 88 | 89 | ### Fixed 90 | 91 | * Issue where autocloaking would overwrite other tokenColorCustomization settings resolved [#79](https://github.com/dotenv-org/dotenv-vscode/issues/79) 92 | 93 | ## 0.22.0 94 | 95 | ### Added 96 | 97 | * [#78](https://github.com/dotenv-org/dotenv-vscode/pull/78) 98 | * Added autocomplete and hover support for dart. 99 | * Added autocomplete and hover support for kotlin. 100 | * Added .env.fat to list of files that will automatically be configured for dotEnv syntax highlighting. 101 | 102 | ### Fixed 103 | * Issue where creating a new file and selecting javascript/ruby/python/php language but highlithing would be in .env style resolved. [#66](https://github.com/dotenv-org/dotenv-vscode/issues/66), [#63](https://github.com/dotenv-org/dotenv-vscode/issues/63) 104 | 105 | ## 0.21.0 106 | 107 | ### Changed 108 | 109 | * [#74](https://github.com/dotenv-org/dotenv-vscode/pull/74) 110 | * Improved syntax highlighting for .env files 111 | * Added more .env extensions that should auto-change the vscode langauge identifier to dotenv 112 | 113 | ## 0.20.0 114 | 115 | ### Added 116 | 117 | * Added suport for `var_os` in Rust [#71](https://github.com/dotenv-org/dotenv-vscode/pull/71) 118 | 119 | ## 0.19.0 120 | 121 | ### Removed 122 | 123 | * Remove support for .NET dotenv lib [#61](https://github.com/dotenv-org/dotenv-vscode/pull/61) 124 | 125 | ## 0.18.0 126 | 127 | * Added support for rust [#64](https://github.com/dotenv-org/dotenv-vscode/pull/64) 128 | 129 | ## 0.17.0 130 | 131 | ### Added 132 | 133 | * Added support for .NET dotenv lib [#61](https://github.com/dotenv-org/dotenv-vscode/pull/61) 134 | 135 | ## 0.16.0 136 | 137 | ### Added 138 | 139 | * Added support for C# autocomplete and secret peeking[#59](https://github.com/dotenv-org/dotenv-vscode/pull/59) 140 | 141 | ## 0.15.0 142 | 143 | ### Added 144 | 145 | * Added support for Java autocomplete and secret peeking[#58](https://github.com/dotenv-org/dotenv-vscode/pull/58) 146 | 147 | ## 0.14.1 148 | 149 | ### Changed 150 | 151 | * Updated dotenv-vault to 1.13.4 152 | 153 | ## 0.14.0 154 | 155 | ### Added 156 | 157 | * Added support for Go autocomplete and secret peeking[#57](https://github.com/dotenv-org/dotenv-vscode/pull/57) 158 | 159 | ## 0.13.0 160 | 161 | ### Added 162 | 163 | * Added support for PHP autocomplete and secret peeking[#40](https://github.com/dotenv-org/dotenv-vscode/pull/40) 164 | 165 | ## 0.12.0 166 | 167 | ### Added 168 | 169 | * Added support for Python autocomplete and secret peeking[#38](https://github.com/dotenv-org/dotenv-vscode/pull/38) 170 | 171 | ## 0.11.1 172 | 173 | ### Changed 174 | 175 | * Use workspacePath to load `.env` file [#37](https://github.com/dotenv-org/dotenv-vscode/pull/37) 176 | 177 | ## 0.11.0 178 | 179 | ### Added 180 | 181 | * Added support for Ruby autocomplete [#35](https://github.com/dotenv-org/dotenv-vscode/pull/35) 182 | 183 | ## 0.10.2 184 | 185 | ### Changed 186 | 187 | * Various bug patches around autocloaking 🐞 188 | 189 | ## 0.10.1 190 | 191 | ### Changed 192 | 193 | * Place ENV completion items to top of list [#32](https://github.com/dotenv-org/dotenv-vscode/pull/32) 194 | 195 | ## 0.10.0 196 | 197 | * Added support for Ruby ENV secret peeking 198 | 199 | ## 0.9.0 200 | 201 | ### Added 202 | 203 | * Added support for `.flaskenv` files 204 | 205 | ## 0.8.2 206 | 207 | ### Changed 208 | 209 | * Updated Marketplace description 210 | 211 | ## 0.8.1 212 | 213 | ### Changed 214 | 215 | * Preserve current `textMateRules`. Auto-clocking is either added or removed from the list. 216 | 217 | ## 0.8.0 218 | 219 | ### Added 220 | 221 | * Added auto-cloaking toggle at top of .env file 🎉 ([24](https://github.com/dotenv-org/dotenv-vscode/pull/24)) 222 | 223 | ## 0.7.1 224 | 225 | ### Changed 226 | 227 | * Fixed activation event in event of opening `.env` file first ([23](https://github.com/dotenv-org/dotenv-vscode/pull/23)) 228 | 229 | ## 0.7.0 230 | 231 | ### Added 232 | 233 | * Auto-cloaking 🎉 234 | 235 | ## 0.6.1 236 | 237 | ### Changed 238 | 239 | * Updated dotenv-vault to 1.11.2 240 | 241 | ## 0.6.0 242 | 243 | ### Added 244 | 245 | * Icon in sidebar 🎉 246 | * Working sidebar with buttons for added convenience 🎉 247 | * Modal prompt before running npx dotenv-vault commands 248 | 249 | 250 | ## 0.5.5 251 | 252 | ### Added 253 | 254 | * Added file support 255 | 256 | ## 0.5.4 257 | 258 | ### Added 259 | 260 | * Clarified some content 261 | 262 | ## 0.5.3 263 | 264 | ### Added 265 | 266 | * Added support for more extension types - .vault, .me 267 | 268 | ## 0.5.2 269 | 270 | ### Changed 271 | 272 | * Refactored into helpers 273 | 274 | ### Added 275 | 276 | * Added tests 277 | 278 | ## 0.5.1 279 | 280 | ### Changed 281 | 282 | * Fix typescript support for hover 283 | 284 | ## 0.5.0 285 | 286 | ### Added 287 | 288 | * Added support for vue files to have autocompletion 289 | * Added hover support. Hover over a process.env.VARIABLE and view its vaulue set in your .env file 🎉 290 | 291 | ## 0.4.0 292 | 293 | ### Added 294 | 295 | * Added autocompletion of process.env for .ts files and react code 296 | 297 | ## 0.3.0 298 | 299 | ### Added 300 | 301 | * Added autocompletion of process.env by reading from local .env file 302 | 303 | ### Changed 304 | 305 | * Support older versions of VSCode 306 | 307 | ## 0.2.1 308 | 309 | ### Changed 310 | 311 | * README updates 312 | 313 | ## 0.2.0 314 | 315 | ### Added 316 | 317 | * Syntax highlighting for .env* files 318 | 319 | ## 0.1.4 320 | 321 | ### Changed 322 | 323 | * README updates 324 | 325 | ## 0.1.3 326 | 327 | ### Changed 328 | 329 | * Updated README 330 | 331 | ## 0.1.2 332 | 333 | ### Changed 334 | 335 | * Update banner and turn Q&A off. We will use GitHub Issues. 336 | 337 | ## 0.1.1 338 | 339 | ### Changed 340 | 341 | * Update displayName 342 | 343 | ## 0.1.0 344 | 345 | ### Added 346 | 347 | * Added commands: 348 | 349 | ``` 350 | login 351 | logout 352 | new 353 | open 354 | pull 355 | push 356 | status 357 | versions 358 | whoami 359 | ``` 360 | 361 | ## 0.0.5 362 | 363 | ### Changed 364 | 365 | * Updated displayName 366 | 367 | ## 0.0.4 368 | 369 | ### Changed 370 | 371 | * Updated displayName 372 | 373 | ## 0.0.3 374 | 375 | ### Added 376 | 377 | * Added sponsor link 378 | 379 | ## 0.0.2 380 | 381 | ### Added 382 | 383 | * Added icon to marketplace 384 | 385 | ## 0.0.1 386 | 387 | Initial release 388 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # DEVELOPMENT 2 | 3 | ## Setup 4 | 5 | ``` 6 | npx dotenv-vault pull 7 | ``` 8 | 9 | ## Running in Debug Mode 10 | 11 | Open this project in VSCode. 12 | 13 | Then in VSCode click `Run` > `Start Debugging`. 14 | 15 | That will open up a second VSCode that you can refresh when making changes. [see more](https://www.youtube.com/watch?v=a5DX5pQ9p5M) 16 | 17 | CMD + R to refresh the extension, after making changes. 18 | 19 | ## Tests 20 | 21 | ``` 22 | npm test 23 | ``` 24 | 25 | ## Packaging 26 | 27 | Package it locally. 28 | 29 | ``` 30 | npm run package 31 | ``` 32 | 33 | ## Installing 34 | 35 | Install it locally. 36 | 37 | ``` 38 | npm run install-package dotenv-vscode-x.x.x.vsix 39 | ``` 40 | 41 | or install it by hand through Visual Studio Code. 42 | 43 | Click `Extensions` > `...` > `Install from VSIX` > `Select dotenv-vscode-*-*-*.vsix` 44 | 45 | [1] https://community.particle.io/t/how-to-install-a-vscode-extension-from-a-vsix-file/51014 46 | [2] https://code.visualstudio.com/docs/editor/extension-marketplace#_install-from-a-vsix 47 | 48 | ## Publishing 49 | 50 | For those with access. 51 | 52 | ``` 53 | npm version patch 54 | npm run publish 55 | ``` 56 | 57 | [1] https://code.visualstudio.com/api/working-with-extensions/publishing-extension#publishing-extensions 58 | [2] https://marketplace.visualstudio.com/manage/publishers/dotenv 59 | 60 | ## Icons 61 | 62 | List of all icons [https://code.visualstudio.com/api/references/icons-in-labels](https://code.visualstudio.com/api/references/icons-in-labels) 63 | List of all icons [https://microsoft.github.io/vscode-codicons/dist/codicon.html](https://microsoft.github.io/vscode-codicons/dist/codicon.html) 64 | 65 | ## List of keywords 66 | 67 | Find list of keywords here: https://stackoverflow.com/questions/10834765/where-to-find-a-list-of-scopes-for-sublime2-or-textmate 68 | 69 | ## Reference Theme Colors 70 | 71 | https://stackoverflow.com/questions/47117621/how-to-get-the-vscode-theme-color-in-vscode-extensions 72 | 73 | ## Inspiration 74 | 75 | [GitHub Pull Request Extension](https://github.com/microsoft/vscode-pull-request-github/blob/main/package.json) 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Scott Motte 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 | 5 |
6 | 7 | 8 | 11 | 14 | 17 | 18 |
9 | 10 | 12 | 13 | 15 | 16 |
19 |
20 | 21 | # dotenv-vscode 22 | 23 | #### Syntax highlighting, auto-cloaking, auto-completion, and in-code secret peeking. 24 | 25 | Version 26 | 27 | ## Install 28 | 29 | Install using VSCode Command Palette 30 | 31 | 1. Go to `View -> Command Palette` or press `Ctrl+Shift+P` 32 | 2. Then enter `Install Extension` 33 | 3. Search for `Dotenv` 34 | 4. Select `Official Dotenv` and click `Install` 35 | 36 | ## Usage 37 | 38 | ### Syntax Highlighting 39 | 40 | It just works. Open your `.env` files in VSCode, and they will now be syntax highlighted. 41 | 42 |
43 | 44 | ### Auto-cloaking 45 | 46 | It just works. Open your `.env` files in VSCode, and they will be auto-cloaked. Click the 'Toggle auto-cloaking' link at the top of your `.env` file to toggle it off. Feel safer sharing your screen! 47 | 48 | 49 | 50 | Multiple .env file types supported. 51 | 52 | * .env 53 | * .env.example 54 | * .env.development 55 | * .env.staging 56 | * .env.production 57 | * .env.vault 58 | * .env.me 59 | * .env.* 60 | * .flaskenv 61 | 62 |
63 | 64 | ### Auto-completion 65 | 66 | Start typing `process.env.` (or language specific env statement) and your cursor will be populated with auto-completion options directly from your .env file. Cool! 67 | 68 | 69 | 70 | Multiple languages supported. 71 | 72 | * JavaScript/TypeScript/NodeJS 73 | * Ruby 74 | * Python 75 | * PHP 76 | * Go 77 | * Java 78 | * C# 79 | * Rust 80 | 81 |
82 | 83 | ### In-code secret peeking 84 | 85 | Hover your mouse over a `process.env.SECRET_KEY` or a `ENV["SECRET_KEY"]`, and you will be able to peek at its value without having to open your .env file. Convenient! 86 | 87 | 88 | 89 | Multiple languages supported. 90 | 91 | * JavaScript/TypeScript/NodeJS 92 | * Ruby 93 | * Python 94 | * PHP 95 | * Go 96 | * Java 97 | * C# 98 | * Rust 99 | 100 |
101 | 102 | ### dotenv-vault (included but optional) 103 | 104 | Manage your secrets using dotenv-vault's all-in-one toolkit. Say goodbye to scattered secrets across multiple platforms and tools. 105 | 106 | Read more about dotenv-vault here. 107 | 108 | Usage is similar to git. Run `CMD+Shift+P` (or `Ctrl+Shift+P`) and start typing `dotenv`. 109 | 110 | ```bash 111 | dotenv new 112 | ``` 113 | 114 | Follow those instructions and then run: 115 | 116 | ```bash 117 | dotenv login 118 | ``` 119 | 120 | Then run push and pull 121 | 122 | ```bash 123 | dotenv push 124 | dotenv pull 125 | ``` 126 | 127 | See dotenv-vault in action: 128 | 129 | 130 | 131 | Visit [dotenv.org/docs](https://www.dotenv.org/docs/security/overview?r=8) to learn more. 132 | 133 | ## Commands 134 | 135 | ``` 136 | dotenv new Create your project 137 | dotenv login Log in to dotenv-vault 138 | dotenv logout Log out 139 | dotenv open Open project page 140 | dotenv push Push .env securely 141 | dotenv pull Pull .env securely 142 | dotenv versions List version history 143 | dotenv whoami Display the current logged in user 144 | dotenv status Check dotenv-vault operational status 145 | ``` 146 | 147 | Visit [dotenv.org/docs](https://www.dotenv.org/docs/dotenv-vault?r=8) for details per command. 148 | 149 | ## CHANGELOG 150 | 151 | See [CHANGELOG](CHANGELOG.md) 152 | 153 |
154 |
155 | Thank you for using dotenv-vscode. 156 | -------------------------------------------------------------------------------- /dotenv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotenv-org/dotenv-vscode/01dc12141d059cc4aad5dbfcbb7a321af6462de0/dotenv.png -------------------------------------------------------------------------------- /extension.js: -------------------------------------------------------------------------------- 1 | const autocloaking = require('./lib/autocloaking') 2 | const autocompletion = require('./lib/autocompletion') 3 | const commands = require('./lib/commands') 4 | const peeking = require('./lib/peeking') 5 | const fileAssociations = require('./lib/fileAssociations') 6 | 7 | async function activate (context) { 8 | console.log('Dotenv is active') 9 | 10 | console.log('Set file associations') 11 | fileAssociations.run() 12 | 13 | console.log('Load autocompletion') 14 | await autocompletion.run(context) 15 | 16 | console.log('Load commands') 17 | commands.run(context) 18 | 19 | console.log('Load secret peeking') 20 | peeking.run(context) 21 | 22 | console.log('Load autocloaking') 23 | await autocloaking.run(context) 24 | } 25 | 26 | function deactivate () { 27 | console.log('Dotenv is no longer active') 28 | } 29 | 30 | module.exports = { 31 | activate, 32 | deactivate 33 | } 34 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "checkJs": false, /* Typecheck .js files. */ 6 | "lib": [ 7 | "ES2020" 8 | ] 9 | }, 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /lib/autocloaking.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | const decorations = require('./decorations') 3 | const settings = require('./settings') 4 | 5 | const run = async function (context) { 6 | if (settings.autocloakingEnabled()) { 7 | await settings.mask() 8 | } else { 9 | await settings.unmask() 10 | } 11 | 12 | decorateMasking(context) 13 | buildToggle(context) 14 | 15 | const toggleAutocloaking = vscode.commands.registerCommand('dotenv.toggleAutocloaking', async function () { await dotenvToggleAutocloaking() }) 16 | 17 | context.subscriptions.push(toggleAutocloaking) 18 | } 19 | 20 | function decorateMasking (context) { 21 | decorations.decorate(context, vscode.window.activeTextEditor) 22 | 23 | // Update when a file opens 24 | vscode.window.onDidChangeActiveTextEditor(function (editor) { 25 | decorations.decorate(context, editor) 26 | }) 27 | vscode.workspace.onDidOpenTextDocument(function (event) { 28 | const openEditor = vscode.window.visibleTextEditors.filter(function (editor) { 29 | try { 30 | return editor.document.uri === event.document.uri 31 | } catch (e) { 32 | console.log(e) 33 | return false 34 | } 35 | })[0] 36 | decorations.decorate(context, openEditor) 37 | }) 38 | 39 | // Update when moving around the editor 40 | // vscode.window.onDidChangeTextEditorSelection(function () { 41 | // decorations.decorate(context, vscode.window.activeTextEditor) 42 | // }) 43 | 44 | // Update if the config was changed 45 | vscode.workspace.onDidChangeConfiguration(function (event) { 46 | if (event.affectsConfiguration('dotenv.enableAutocloaking')) { 47 | decorations.decorate(context, vscode.window.activeTextEditor) 48 | } 49 | }) 50 | } 51 | 52 | const toggleLink = { 53 | provideCodeLenses: function (document, token) { 54 | const range = new vscode.Range(0, 1, 10, 10) // place at top of file 55 | const lens = new vscode.CodeLens(range, { 56 | command: 'dotenv.toggleAutocloaking', 57 | title: 'Toggle auto-cloaking' 58 | }) 59 | return [ 60 | lens 61 | ] 62 | } 63 | } 64 | 65 | function buildToggle (context) { 66 | const codeLens = vscode.languages.registerCodeLensProvider({ pattern: '**/.env*' }, toggleLink) 67 | 68 | context.subscriptions.push(codeLens) 69 | 70 | return true 71 | } 72 | 73 | async function dotenvToggleAutocloaking () { 74 | if (settings.autocloakingEnabled()) { 75 | await settings.unmask() 76 | await settings.autocloakingOff() 77 | } else { 78 | await settings.mask() 79 | await settings.autocloakingOn() 80 | } 81 | 82 | return true 83 | } 84 | 85 | module.exports.run = run 86 | -------------------------------------------------------------------------------- /lib/autocompletion.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | const providers = require('./providers') 3 | 4 | const run = function (context) { 5 | const javascript = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'javascript' }, providers.javascriptCompletion, '.') 6 | const typescript = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'typescript' }, providers.javascriptCompletion, '.') 7 | const javascriptreact = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'javascriptreact' }, providers.javascriptCompletion, '.') 8 | const typescriptreact = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'typescriptreact' }, providers.javascriptCompletion, '.') 9 | const vue = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'vue' }, providers.javascriptCompletion, '.') 10 | const ruby = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'ruby' }, providers.rubyCompletion, '[') 11 | const python = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'python' }, providers.pythonCompletion, '(') 12 | const pythonArray = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'python' }, providers.pythonArrayCompletion, '[') 13 | const php = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'php' }, providers.phpCompletion, '[') 14 | const phpGetEnv = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'php' }, providers.phpGetEnvCompletion, '(') 15 | const go = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'go' }, providers.goCompletion, '(') 16 | const java = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'java' }, providers.javaCompletion, '(') 17 | const csharp = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'csharp' }, providers.csharpCompletion, '(') 18 | const rust = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'rust' }, providers.rustCompletion, '(') 19 | const dart = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'dart' }, providers.dartCompletion, '(') 20 | const kotlin = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'kotlin' }, providers.kotlinCompletion, '(') 21 | const elixir = vscode.languages.registerCompletionItemProvider({ scheme: 'file', language: 'elixir' }, providers.elixirCompletion, '(') 22 | 23 | context.subscriptions.push(javascript) 24 | context.subscriptions.push(typescript) 25 | context.subscriptions.push(javascriptreact) 26 | context.subscriptions.push(typescriptreact) 27 | context.subscriptions.push(vue) 28 | context.subscriptions.push(ruby) 29 | context.subscriptions.push(python) 30 | context.subscriptions.push(pythonArray) 31 | context.subscriptions.push(php) 32 | context.subscriptions.push(phpGetEnv) 33 | context.subscriptions.push(go) 34 | context.subscriptions.push(java) 35 | context.subscriptions.push(csharp) 36 | context.subscriptions.push(rust) 37 | context.subscriptions.push(dart) 38 | context.subscriptions.push(kotlin) 39 | context.subscriptions.push(elixir) 40 | return true 41 | } 42 | 43 | module.exports.run = run 44 | -------------------------------------------------------------------------------- /lib/commands.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | 3 | const DOTENV_VAULT_VERSION = '1.24.0' 4 | const TERMINAL_NAME = 'Dotenv' 5 | 6 | // commands 7 | function dotenvLogin () { 8 | const command = 'login' 9 | promptCommand(command) 10 | } 11 | 12 | function dotenvLogout () { 13 | const command = 'logout' 14 | promptCommand(command) 15 | } 16 | 17 | function dotenvNew () { 18 | const command = 'new' 19 | promptCommand(command) 20 | } 21 | 22 | function dotenvOpen () { 23 | const command = 'open' 24 | promptCommand(command) 25 | } 26 | 27 | function dotenvPull () { 28 | const command = 'pull' 29 | promptCommand(command) 30 | } 31 | 32 | function dotenvPush () { 33 | const command = 'push' 34 | promptCommand(command) 35 | } 36 | 37 | function dotenvStatus () { 38 | const command = 'status' 39 | promptCommand(command) 40 | } 41 | 42 | function dotenvVersions () { 43 | const command = 'versions' 44 | promptCommand(command) 45 | } 46 | 47 | function dotenvWhoami () { 48 | const command = 'whoami' 49 | 50 | infoMessage(command, function (yes) { 51 | if (yes) { 52 | const terminal = getTerminal() 53 | terminal.sendText(`npx --yes dotenv-vault@${DOTENV_VAULT_VERSION} ${command}`) 54 | terminal.show() 55 | } 56 | }) 57 | } 58 | 59 | function promptCommand (command) { 60 | infoMessage(command, function (yes) { 61 | if (yes) { 62 | const terminal = getTerminal() 63 | runCommand(terminal, command) 64 | } 65 | }) 66 | } 67 | 68 | function infoMessage (command, callback) { 69 | const msg = `$ npx dotenv-vault ${command}` 70 | const details = commandDetails(command) 71 | const docsUrl = commandDocsUrl(command) 72 | const options = { detail: details, modal: true } 73 | 74 | vscode.window.showInformationMessage(msg, options, ...['Ok', 'Documentation']).then((result) => { 75 | if (result === 'Ok') { 76 | const output = true 77 | 78 | callback(output) 79 | } else { 80 | if (result === 'Documentation') { 81 | vscode.env.openExternal(docsUrl) 82 | } 83 | 84 | const output = false 85 | callback(output) 86 | } 87 | }) 88 | } 89 | 90 | function getTerminal () { 91 | let terminal = vscode.window.activeTerminal 92 | if (!terminal) { 93 | terminal = vscode.window.createTerminal(TERMINAL_NAME) 94 | } 95 | 96 | return terminal 97 | } 98 | 99 | function runCommand (terminal, command) { 100 | terminal.sendText(`npx --yes dotenv-vault@${DOTENV_VAULT_VERSION} ${command} --yes`) 101 | terminal.show() 102 | } 103 | 104 | function commandDetails (command) { 105 | switch (command) { 106 | case 'new': 107 | return 'Create your project' 108 | case 'login': 109 | return 'Log in to Dotenv Vault' 110 | case 'logout': 111 | return 'Log out of Dotenv Vault' 112 | case 'open': 113 | return 'Open project page' 114 | case 'push': 115 | return 'Push .env securely' 116 | case 'pull': 117 | return 'Pull .env securely' 118 | case 'versions': 119 | return 'List version history' 120 | case 'whoami': 121 | return 'Display the current logged in user' 122 | case 'status': 123 | return 'Check Dotenv Vault operational status' 124 | default: 125 | return '' 126 | } 127 | } 128 | 129 | function commandDocsUrl (command) { 130 | switch (command) { 131 | case 'new': 132 | return 'https://www.dotenv.org/docs/dotenv-vault/new' 133 | case 'login': 134 | return 'https://www.dotenv.org/docs/dotenv-vault/login' 135 | case 'logout': 136 | return 'https://www.dotenv.org/docs/dotenv-vault/logout' 137 | case 'open': 138 | return 'https://www.dotenv.org/docs/dotenv-vault/open' 139 | case 'push': 140 | return 'https://www.dotenv.org/docs/dotenv-vault/push' 141 | case 'pull': 142 | return 'https://www.dotenv.org/docs/dotenv-vault/pull' 143 | case 'versions': 144 | return 'https://www.dotenv.org/docs/dotenv-vault/versions' 145 | case 'whoami': 146 | return 'https://www.dotenv.org/docs/dotenv-vault/whoami' 147 | case 'status': 148 | return 'https://www.dotenv.org/docs/dotenv-vault/status' 149 | default: 150 | return 'https://www.dotenv.org/docs' 151 | } 152 | } 153 | 154 | const run = function (context) { 155 | const login = vscode.commands.registerCommand('dotenv.login', function () { dotenvLogin() }) 156 | const logout = vscode.commands.registerCommand('dotenv.logout', function () { dotenvLogout() }) 157 | const neww = vscode.commands.registerCommand('dotenv.new', function () { dotenvNew() }) 158 | const open = vscode.commands.registerCommand('dotenv.open', function () { dotenvOpen() }) 159 | const pull = vscode.commands.registerCommand('dotenv.pull', function () { dotenvPull() }) 160 | const push = vscode.commands.registerCommand('dotenv.push', function () { dotenvPush() }) 161 | const status = vscode.commands.registerCommand('dotenv.status', function () { dotenvStatus() }) 162 | const versions = vscode.commands.registerCommand('dotenv.versions', function () { dotenvVersions() }) 163 | const whoami = vscode.commands.registerCommand('dotenv.whoami', function () { dotenvWhoami() }) 164 | 165 | context.subscriptions.push(login) 166 | context.subscriptions.push(logout) 167 | context.subscriptions.push(neww) 168 | context.subscriptions.push(open) 169 | context.subscriptions.push(pull) 170 | context.subscriptions.push(push) 171 | context.subscriptions.push(status) 172 | context.subscriptions.push(versions) 173 | context.subscriptions.push(whoami) 174 | 175 | return true 176 | } 177 | 178 | module.exports.run = run 179 | -------------------------------------------------------------------------------- /lib/decorations.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | const path = require('path') 3 | const settings = require('./settings') 4 | 5 | const maskDecoration = vscode.window.createTextEditorDecorationType({ 6 | letterSpacing: '-1ch', 7 | opacity: '0' 8 | }) 9 | 10 | const parse = function (sourceCode) { 11 | const arr = [] 12 | // const stillDisplayCommentsRegex = /((=|:)\s?".+"|(=|:)\s?'.+'|(=|:)\s?`.+`|(=|:).*\s?(\s#)?)/ 13 | const regex = /=.+/ 14 | let lineIndex = 0 15 | 16 | const lines = sourceCode.split('\n') 17 | for (const line of lines) { 18 | lineIndex += 1 19 | 20 | const r = new RegExp(regex, 'g') 21 | const matches = r.exec(line) 22 | 23 | if (matches) { 24 | const firstMatch = matches[0] 25 | 26 | if (firstMatch) { 27 | const startIndex = line.indexOf(firstMatch) 28 | const endIndex = startIndex + firstMatch.length 29 | 30 | // build line and column start and ends 31 | arr.push({ 32 | maskedText: settings.cloakIcon().repeat(firstMatch.length), 33 | start: { line: lineIndex, column: startIndex }, 34 | end: { line: lineIndex, column: endIndex } 35 | }) 36 | } 37 | } 38 | } 39 | 40 | return arr 41 | } 42 | 43 | const applyDecorations = function (_ctx, editor, patches) { 44 | const decorationsArray = patches 45 | .map(function (patch) { 46 | const range = new vscode.Range( 47 | new vscode.Position(patch.start.line - 1, patch.start.column), 48 | new vscode.Position(patch.end.line - 1, patch.end.column) 49 | ) 50 | return { 51 | range, 52 | renderOptions: { 53 | letterSpacing: '-1ch', // squishes them together 54 | opacity: '0', 55 | after: { 56 | color: settings.cloakColor(), 57 | contentText: `=${patch.maskedText}` 58 | } 59 | } 60 | } 61 | }) 62 | 63 | editor.setDecorations(maskDecoration, decorationsArray) 64 | } 65 | 66 | const decorate = (context, editor) => { 67 | if (!editor) { 68 | return 69 | } 70 | 71 | try { 72 | // only apply to .env* files 73 | const filename = path.basename(editor.document.uri.fsPath) 74 | if (!filename.startsWith('.env') && !filename.startsWith('.flaskenv')) { 75 | return 76 | } 77 | 78 | if (!settings.autocloakingEnabled()) { 79 | applyDecorations(context, editor, []) 80 | } else { 81 | const sourceCode = editor.document.getText() 82 | const patches = parse(sourceCode) 83 | applyDecorations(context, editor, patches) 84 | } 85 | } catch (e) { 86 | console.log(e) 87 | } 88 | } 89 | 90 | module.exports.decorate = decorate 91 | -------------------------------------------------------------------------------- /lib/fileAssociations.js: -------------------------------------------------------------------------------- 1 | const settings = require('./settings') 2 | 3 | const run = function () { 4 | settings.populateFileAssociations() 5 | 6 | return true 7 | } 8 | 9 | module.exports.run = run 10 | -------------------------------------------------------------------------------- /lib/helpers.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | const dotenv = require('dotenv') 3 | const settings = require('./settings') 4 | 5 | function envEntries () { 6 | const parsed = envParsed() 7 | 8 | if (parsed) { 9 | const entries = Object.entries(parsed) // converts key: value to [key, value] 10 | 11 | return entries 12 | } else { 13 | return [['KEY', 'VALUE']] // serves as example 14 | } 15 | } 16 | 17 | function envParsed () { 18 | const workspacePath = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath.replace(/\\/g, '/') : undefined // /path/to/project/folder 19 | 20 | let parsed = {} 21 | 22 | if (workspacePath) { 23 | parsed = dotenv.config({ path: `${workspacePath}/.env` }).parsed 24 | } else { 25 | parsed = dotenv.config().parsed 26 | } 27 | 28 | return parsed 29 | } 30 | 31 | function hover (language, document, position) { 32 | const regexDict = { 33 | javascript: /(?:process|import\.meta)\.env\.([A-Z]{1}[A-Z_0123456789]+)/, 34 | ruby: /ENV\[['"]([A-Z]{1}[A-Z_0123456789]+)['"]\]/, 35 | python: /os\.(?:(?:environ(?:(?:\.get\(["']([A-Z]{1}[A-Z_0123456789]+)["']\))|(?:\[["']([A-Z]{1}[A-Z_0123456789]+)["']\])))|(?:getenv\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)))/, 36 | php: /(?:(?:\$_(?:SERVER|ENV)\[["']([A-Z]{1}[A-Z_0123456789]+)["']\])|(?:getenv\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)))/, 37 | go: /os.Getenv\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/, 38 | java: /dotenv.get\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/, 39 | csharp: /Environment.GetEnvironmentVariable\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/, 40 | rust: /std::env::(?:var|var_os)\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/, 41 | dart: /String.fromEnvironment\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/, 42 | kotlin: /System.getenv\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/, 43 | elixir: /System.get_env\(["']([A-Z]{1}[A-Z_0123456789]+)["']\)/ 44 | } 45 | const reg = regexDict[language] 46 | const line = document.lineAt(position).text 47 | const matches = line.match(reg) 48 | 49 | if (!matches) { 50 | return undefined 51 | } else { 52 | const key = matches.filter(item => item !== undefined)[1] 53 | 54 | const start = line.indexOf(key) 55 | const end = start + key.length 56 | if (position.character >= start && position.character <= end) { 57 | const parsed = envParsed() 58 | const value = parsed[key] 59 | 60 | if (settings.secretpeekingEnabled()) { 61 | return new vscode.Hover(value) 62 | } else { 63 | return new vscode.Hover(_partialMask(value)) 64 | } 65 | } else { 66 | return new vscode.Hover(settings.missingText()) 67 | } 68 | } 69 | } 70 | 71 | function _partialMask (str) { 72 | const lastTwoChars = str.slice(-2) 73 | const maskChars = settings.cloakIcon().repeat(str.length - 2) 74 | 75 | return `${maskChars}${lastTwoChars}` 76 | } 77 | 78 | function autocomplete (triggerCharacter, document, position) { 79 | const entries = envEntries() 80 | const quote = triggerCharacter === '.' ? '' : '"' // for javascript, doesn't use quotation in env reference so make sure not to add to insert/filter text 81 | return entries.map(function (env) { 82 | const key = env[0].trim() 83 | const value = env[1].trim() 84 | let formattedValue = settings.missingText() 85 | 86 | if (value) { 87 | if (settings.secretpeekingEnabled()) { 88 | formattedValue = value 89 | } else { 90 | formattedValue = _partialMask(value) 91 | } 92 | } 93 | 94 | // https://code.visualstudio.com/api/references/vscode-api#CompletionItemLabel 95 | const completionItemLabel = { 96 | label: key, 97 | // detail: ` ${value}` 98 | detail: ` ${formattedValue}` 99 | } 100 | const item = new vscode.CompletionItem(completionItemLabel, vscode.CompletionItemKind.Variable) 101 | item.insertText = `${triggerCharacter}${quote}${key}${quote}` 102 | item.filterText = `${triggerCharacter}${quote}${key}${quote}` 103 | item.range = new vscode.Range(new vscode.Position(position.line, position.character - 1), position) // Picks up trigger character as prefix to fix the scoring it does when sorting 104 | item.sortText = '0' // Make this the sortText so that any ENV variables will go to the top of the list above anything else 105 | 106 | const s = `.env 107 |
108 | 109 | **${key}** 110 | 111 |
${formattedValue}
112 | ` 113 | const doc = new vscode.MarkdownString(s) 114 | doc.value = s 115 | doc.supportHtml = true 116 | // item.documentation = value // update with more details 117 | item.documentation = doc // more details 118 | 119 | return item 120 | }) 121 | } 122 | 123 | module.exports.envEntries = envEntries 124 | module.exports.envParsed = envParsed 125 | module.exports.hover = hover 126 | module.exports.autocomplete = autocomplete 127 | -------------------------------------------------------------------------------- /lib/peeking.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | const providers = require('./providers') 3 | 4 | const run = function (context) { 5 | const javascriptHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'javascript' }, providers.javascriptHover) 6 | const typescriptHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'typescript' }, providers.javascriptHover) 7 | const javascriptreactHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'javascriptreact' }, providers.javascriptHover) 8 | const typescriptreactHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'typescriptreact' }, providers.javascriptHover) 9 | const vueHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'vue' }, providers.javascriptHover) 10 | const rubyHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'ruby' }, providers.rubyHover) 11 | const pythonHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'python' }, providers.pythonHover) 12 | const phpHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'php' }, providers.phpHover) 13 | const goHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'go' }, providers.goHover) 14 | const javaHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'java' }, providers.javaHover) 15 | const csharpHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'csharp' }, providers.csharpHover) 16 | const rustHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'rust' }, providers.rustHover) 17 | const dartHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'dart' }, providers.dartHover) 18 | const kotlinHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'kotlin' }, providers.kotlinHover) 19 | const elixirHover = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'elixir' }, providers.elixirHover) 20 | 21 | context.subscriptions.push(javascriptHover) 22 | context.subscriptions.push(typescriptHover) 23 | context.subscriptions.push(javascriptreactHover) 24 | context.subscriptions.push(typescriptreactHover) 25 | context.subscriptions.push(vueHover) 26 | context.subscriptions.push(rubyHover) 27 | context.subscriptions.push(pythonHover) 28 | context.subscriptions.push(phpHover) 29 | context.subscriptions.push(goHover) 30 | context.subscriptions.push(javaHover) 31 | context.subscriptions.push(csharpHover) 32 | context.subscriptions.push(rustHover) 33 | context.subscriptions.push(dartHover) 34 | context.subscriptions.push(kotlinHover) 35 | context.subscriptions.push(elixirHover) 36 | return true 37 | } 38 | 39 | module.exports.run = run 40 | -------------------------------------------------------------------------------- /lib/providers.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | 3 | const helpers = require('./helpers') 4 | 5 | const javascriptHover = { 6 | provideHover: function (document, position, token) { 7 | return helpers.hover('javascript', document, position) 8 | } 9 | } 10 | 11 | const rubyHover = { 12 | provideHover: function (document, position, token) { 13 | return helpers.hover('ruby', document, position) 14 | } 15 | } 16 | 17 | const pythonHover = { 18 | provideHover: function (document, position, token) { 19 | return helpers.hover('python', document, position) 20 | } 21 | } 22 | 23 | const phpHover = { 24 | provideHover: function (document, position, token) { 25 | return helpers.hover('php', document, position) 26 | } 27 | } 28 | 29 | const goHover = { 30 | provideHover: function (document, position, token) { 31 | return helpers.hover('go', document, position) 32 | } 33 | } 34 | 35 | const javaHover = { 36 | provideHover: function (document, position, token) { 37 | return helpers.hover('java', document, position) 38 | } 39 | } 40 | 41 | const csharpHover = { 42 | provideHover: function (document, position, token) { 43 | return helpers.hover('csharp', document, position) 44 | } 45 | } 46 | 47 | const rustHover = { 48 | provideHover: function (document, position, token) { 49 | return helpers.hover('rust', document, position) 50 | } 51 | } 52 | 53 | const dartHover = { 54 | provideHover: function (document, position, token) { 55 | return helpers.hover('dart', document, position) 56 | } 57 | } 58 | 59 | const kotlinHover = { 60 | provideHover: function (document, position, token) { 61 | return helpers.hover('kotlin', document, position) 62 | } 63 | } 64 | 65 | const elixirHover = { 66 | provideHover: function (document, position, token) { 67 | return helpers.hover('elixir', document, position) 68 | } 69 | } 70 | 71 | const javascriptCompletion = { 72 | provideCompletionItems: function (document, position) { 73 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 74 | if (!linePrefix.endsWith('process.env.') && !linePrefix.endsWith('import.meta.env.')) { 75 | return undefined 76 | } 77 | 78 | return helpers.autocomplete('.', document, position) 79 | } 80 | } 81 | 82 | const rubyCompletion = { 83 | provideCompletionItems: function (document, position) { 84 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 85 | if (!linePrefix.endsWith('ENV[')) { 86 | return undefined 87 | } 88 | 89 | return helpers.autocomplete('[', document, position) 90 | } 91 | } 92 | 93 | const pythonCompletion = { 94 | provideCompletionItems: function (document, position) { 95 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 96 | if (!linePrefix.endsWith('os.environ.get(') && !linePrefix.endsWith('os.getenv(')) { 97 | return undefined 98 | } 99 | 100 | return helpers.autocomplete('(', document, position) 101 | } 102 | } 103 | 104 | const pythonArrayCompletion = { 105 | provideCompletionItems: function (document, position) { 106 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 107 | if (!linePrefix.endsWith('os.environ[')) { 108 | return undefined 109 | } 110 | 111 | return helpers.autocomplete('[', document, position) 112 | } 113 | } 114 | 115 | const phpCompletion = { 116 | provideCompletionItems: function (document, position) { 117 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 118 | if (!linePrefix.endsWith('$_SERVER[') && !linePrefix.endsWith('$_ENV[')) { 119 | return undefined 120 | } 121 | 122 | return helpers.autocomplete('[', document, position) 123 | } 124 | } 125 | 126 | const phpGetEnvCompletion = { 127 | provideCompletionItems: function (document, position) { 128 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 129 | if (!linePrefix.endsWith('getenv(')) { 130 | return undefined 131 | } 132 | 133 | return helpers.autocomplete('(', document, position) 134 | } 135 | } 136 | 137 | const goCompletion = { 138 | provideCompletionItems: function (document, position) { 139 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 140 | if (!linePrefix.endsWith('os.Getenv(')) { 141 | return undefined 142 | } 143 | 144 | return helpers.autocomplete('(', document, position) 145 | } 146 | } 147 | 148 | const javaCompletion = { 149 | provideCompletionItems: function (document, position) { 150 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 151 | if (!linePrefix.endsWith('dotenv.get(')) { 152 | return undefined 153 | } 154 | 155 | return helpers.autocomplete('(', document, position) 156 | } 157 | } 158 | 159 | const csharpCompletion = { 160 | provideCompletionItems: function (document, position) { 161 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 162 | if (!linePrefix.endsWith('Environment.GetEnvironmentVariable(')) { 163 | return undefined 164 | } 165 | 166 | return helpers.autocomplete('(', document, position) 167 | } 168 | } 169 | 170 | const rustCompletion = { 171 | provideCompletionItems: function (document, position) { 172 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 173 | if (!linePrefix.endsWith('std::env::var(') && !linePrefix.endsWith('std::env::var_os(')) { 174 | return undefined 175 | } 176 | 177 | return helpers.autocomplete('(', document, position) 178 | } 179 | } 180 | 181 | const dartCompletion = { 182 | provideCompletionItems: function (document, position) { 183 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 184 | if (!linePrefix.endsWith('String.fromEnvironment(')) { 185 | return undefined 186 | } 187 | 188 | return helpers.autocomplete('(', document, position) 189 | } 190 | } 191 | 192 | const kotlinCompletion = { 193 | provideCompletionItems: function (document, position) { 194 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 195 | if (!linePrefix.endsWith('System.getenv(')) { 196 | return undefined 197 | } 198 | 199 | return helpers.autocomplete('(', document, position) 200 | } 201 | } 202 | 203 | const elixirCompletion = { 204 | provideCompletionItems: function (document, position) { 205 | const linePrefix = document.lineAt(position).text.slice(0, position.character) 206 | if (!linePrefix.endsWith('System.get_env(')) { 207 | return undefined 208 | } 209 | 210 | return helpers.autocomplete('(', document, position) 211 | } 212 | } 213 | 214 | const viewDotenvNew = { 215 | refresh: function () { 216 | return null 217 | }, 218 | 219 | getTreeItem: function (element) { 220 | vscode.window.showInformationMessage('get tree item') 221 | return element 222 | }, 223 | 224 | getChildren: function (element) { 225 | vscode.window.showInformationMessage('get children dude') 226 | return [] 227 | } 228 | } 229 | 230 | module.exports.javascriptHover = javascriptHover 231 | module.exports.rubyHover = rubyHover 232 | module.exports.pythonHover = pythonHover 233 | module.exports.phpHover = phpHover 234 | module.exports.goHover = goHover 235 | module.exports.javaHover = javaHover 236 | module.exports.csharpHover = csharpHover 237 | module.exports.rustHover = rustHover 238 | module.exports.dartHover = dartHover 239 | module.exports.kotlinHover = kotlinHover 240 | module.exports.elixirHover = elixirHover 241 | module.exports.javascriptCompletion = javascriptCompletion 242 | module.exports.rubyCompletion = rubyCompletion 243 | module.exports.pythonCompletion = pythonCompletion 244 | module.exports.pythonArrayCompletion = pythonArrayCompletion 245 | module.exports.phpCompletion = phpCompletion 246 | module.exports.phpGetEnvCompletion = phpGetEnvCompletion 247 | module.exports.goCompletion = goCompletion 248 | module.exports.javaCompletion = javaCompletion 249 | module.exports.csharpCompletion = csharpCompletion 250 | module.exports.rustCompletion = rustCompletion 251 | module.exports.dartCompletion = dartCompletion 252 | module.exports.kotlinCompletion = kotlinCompletion 253 | module.exports.elixirCompletion = elixirCompletion 254 | module.exports.viewDotenvNew = viewDotenvNew 255 | -------------------------------------------------------------------------------- /lib/settings.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode') 2 | const scope = 'keyword.other.dotenv' 3 | 4 | // WARNING. Do not change these without also adjusting package.json 5 | const enableAutocloakingKey = 'dotenv.enableAutocloaking' 6 | const cloakColorKey = 'dotenv.cloakColor' 7 | const cloakIconKey = 'dotenv.cloakIcon' 8 | const enableSecretpeekingKey = 'dotenv.enableSecretpeeking' 9 | 10 | // other settings from vscode or other extensions 11 | const editorTokenColorCustomizationsKey = 'editor.tokenColorCustomizations' 12 | 13 | // actions 14 | async function populateFileAssociations () { 15 | const fileAssociationsKeys = 'files.associations' 16 | 17 | const existingFileAssociations = userConfig().get(fileAssociationsKeys) || {} 18 | 19 | existingFileAssociations['.env*'] = 'dotenv' 20 | 21 | await userConfig().update(fileAssociationsKeys, existingFileAssociations, vscode.ConfigurationTarget.Global) 22 | 23 | return true 24 | } 25 | 26 | async function autocloakingOff () { 27 | await userConfig().update(enableAutocloakingKey, false, vscode.ConfigurationTarget.Global) 28 | return false 29 | } 30 | 31 | async function mask () { 32 | const value = _editorTokenColorCustomizations() || {} 33 | value.textMateRules = _textMateRules(true) 34 | 35 | await userConfig().update(editorTokenColorCustomizationsKey, value, vscode.ConfigurationTarget.Global) 36 | 37 | return true 38 | } 39 | 40 | async function unmask () { 41 | const value = _editorTokenColorCustomizations() || {} 42 | value.textMateRules = _textMateRules(false) 43 | 44 | await userConfig().update(editorTokenColorCustomizationsKey, value, vscode.ConfigurationTarget.Global) 45 | 46 | return false 47 | } 48 | 49 | async function autocloakingOn () { 50 | await userConfig().update(enableAutocloakingKey, true, vscode.ConfigurationTarget.Global) 51 | return true 52 | } 53 | 54 | function userConfig () { 55 | return vscode.workspace.getConfiguration() 56 | } 57 | 58 | // settings 59 | function autocloakingEnabled () { 60 | return !!userConfig().get(enableAutocloakingKey) 61 | } 62 | 63 | function secretpeekingEnabled () { 64 | return !!userConfig().get(enableSecretpeekingKey) 65 | } 66 | 67 | function cloakColor () { 68 | return userConfig().get(cloakColorKey) 69 | } 70 | 71 | function cloakIcon () { 72 | return userConfig().get(cloakIconKey) 73 | } 74 | 75 | // other settings 76 | function _editorTokenColorCustomizations () { 77 | return userConfig().get(editorTokenColorCustomizationsKey) 78 | } 79 | 80 | function _existingTextMateRules () { 81 | const tokenColorCustomizations = _editorTokenColorCustomizations() 82 | 83 | if (tokenColorCustomizations) { 84 | if (tokenColorCustomizations.textMateRules) { 85 | return tokenColorCustomizations.textMateRules 86 | } else { 87 | return [] 88 | } 89 | } else { 90 | return [] 91 | } 92 | } 93 | 94 | function _textMateRules (enableMask) { 95 | const rules = _existingTextMateRules() 96 | const newRules = [] 97 | 98 | for (const rule of rules) { 99 | if (rule.scope === scope) { 100 | // removes the hide rule. re-set in next few lines. 101 | } else { 102 | newRules.push(rule) // preserve any other rules 103 | } 104 | } 105 | 106 | if (enableMask) { 107 | const maskRule = { 108 | scope, 109 | settings: { foreground: '#FF000000' } // set transparency to 0 110 | } 111 | newRules.push(maskRule) // add new rule 112 | } 113 | 114 | return newRules 115 | } 116 | 117 | function missingText () { 118 | return 'MISSING from .env file' 119 | } 120 | 121 | module.exports.userConfig = userConfig 122 | 123 | // actions 124 | module.exports.autocloakingOff = autocloakingOff 125 | module.exports.autocloakingOn = autocloakingOn 126 | module.exports.mask = mask 127 | module.exports.unmask = unmask 128 | module.exports.populateFileAssociations = populateFileAssociations 129 | 130 | // settings 131 | module.exports.autocloakingEnabled = autocloakingEnabled 132 | module.exports.secretpeekingEnabled = secretpeekingEnabled 133 | module.exports.cloakColor = cloakColor 134 | module.exports.cloakIcon = cloakIcon 135 | 136 | // other 137 | module.exports.missingText = missingText 138 | -------------------------------------------------------------------------------- /media/install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotenv-org/dotenv-vscode/01dc12141d059cc4aad5dbfcbb7a321af6462de0/media/install.png -------------------------------------------------------------------------------- /media/sidebar-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | original 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /overview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotenv-org/dotenv-vscode/01dc12141d059cc4aad5dbfcbb7a321af6462de0/overview.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dotenv-vscode", 3 | "displayName": "Dotenv Official +Vault", 4 | "description": "Official Dotenv. Syntax highlighting, auto-cloaking, auto-completion, in-code secret peeking, and optionally dotenv-vault.", 5 | "author": "Mot @motdotla", 6 | "version": "0.28.1", 7 | "license": "MIT", 8 | "homepage": "https://github.com/dotenv-org/dotenv-vscode", 9 | "icon": "dotenv.png", 10 | "galleryBanner": { 11 | "color": "#ECD53F", 12 | "theme": "highContrast" 13 | }, 14 | "qna": false, 15 | "bugs": { 16 | "url": "https://github.com/dotenv-org/dotenv-vscode/issues" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/dotenv-org/dotenv-vscode.git" 21 | }, 22 | "engines": { 23 | "vscode": "^1.65.0" 24 | }, 25 | "categories": [ 26 | "Languages", 27 | "Formatters", 28 | "SCM Providers", 29 | "Other" 30 | ], 31 | "activationEvents": [ 32 | "*" 33 | ], 34 | "main": "./extension.js", 35 | "contributes": { 36 | "configuration": { 37 | "type": "object", 38 | "title": "Dotenv Official +Vault", 39 | "properties": { 40 | "dotenv.enableAutocloaking": { 41 | "scope": "resource", 42 | "type": "boolean", 43 | "default": true, 44 | "description": "Enable auto-cloaking for your .env files" 45 | }, 46 | "dotenv.enableSecretpeeking": { 47 | "scope": "resource", 48 | "type": "boolean", 49 | "default": true, 50 | "description": "Enable in-code secret peeking for your environment variables" 51 | }, 52 | "dotenv.cloakColor": { 53 | "scope": "resource", 54 | "type": "string", 55 | "default": "#000000", 56 | "description": "Change the color of the cloak for your .env files" 57 | }, 58 | "dotenv.cloakIcon": { 59 | "scope": "resource", 60 | "type": "string", 61 | "default": "█", 62 | "description": "Change the icon of the cloak for your .env files" 63 | } 64 | } 65 | }, 66 | "viewsContainers": { 67 | "activitybar": [ 68 | { 69 | "id": "dotenv", 70 | "title": "Dotenv", 71 | "icon": "media/sidebar-icon.svg" 72 | } 73 | ] 74 | }, 75 | "views": { 76 | "dotenv": [ 77 | { 78 | "id": "dotenv.view.vault", 79 | "icon": "media/dotenv-icon.png", 80 | "name": "Vault" 81 | } 82 | ] 83 | }, 84 | "viewsWelcome": [ 85 | { 86 | "view": "dotenv.view.vault", 87 | "contents": "Getting Started with dotenv-vault [learn more](https://www.dotenv.org/docs/getting-started/with-dotenv-vault)\nStep 1: Create your project\n[Dotenv: new](command:dotenv.new)\nStep 2: Authenticate against it\n[Dotenv: login](command:dotenv.login)\nStep 3: View it\n[Dotenv: open](command:dotenv.open)\nThat's it! Thanks for using dotenv-vault.\n---\nCommands [learn more](https://www.dotenv.org/docs/dotenv-vault)\n[Dotenv: push](command:dotenv.push)\n[Dotenv: pull](command:dotenv.pull)\n[Dotenv: whoami](command:dotenv.whoami)\n[Dotenv: logout](command:dotenv.logout)\n[Dotenv: versions](command:dotenv.versions)\n[Dotenv: status](command:dotenv.status)\n\nProTip: You can run any of these commands by typing 'Ctrl+Shift+P', then 'Dotenv'." 88 | } 89 | ], 90 | "languages": [ 91 | { 92 | "id": "dotenv", 93 | "aliases": [ 94 | ".env", 95 | "env", 96 | "environment variables", 97 | "secrets", 98 | "vault", 99 | "encrypt", 100 | "password", 101 | "api", 102 | "key", 103 | "cloak", 104 | "mask", 105 | "hide", 106 | "blur", 107 | "dotenv-vault" 108 | ], 109 | "extensions": [ 110 | ".env", 111 | ".env.vault", 112 | ".env.me", 113 | ".flaskenv", 114 | ".env-sample", 115 | ".env.sample", 116 | ".env.example", 117 | ".env.local", 118 | ".env.dev", 119 | ".env.dev.local", 120 | ".env.build", 121 | ".env.build.local", 122 | ".env.development", 123 | ".env.development.local", 124 | ".env.test", 125 | ".env.test.local", 126 | ".env.testing", 127 | ".env.qa", 128 | ".env.qa.local", 129 | ".env.ci", 130 | ".env.ci.local", 131 | ".env.fart", 132 | ".env.uat", 133 | ".env.uat.local", 134 | ".env.stag", 135 | ".env.stag.local", 136 | ".env.stage", 137 | ".env.stage.local", 138 | ".env.staging", 139 | ".env.staging.local", 140 | ".env.live", 141 | ".env.live.local", 142 | ".env.production", 143 | ".env.production.local", 144 | ".env.prod", 145 | ".env.prod.local", 146 | ".env.previous", 147 | ".env.staging.previous", 148 | ".env.production.previous", 149 | ".env.fat", 150 | ".fart", 151 | ".vault", 152 | ".project", 153 | ".me", 154 | ".secret", 155 | ".env.secret", 156 | ".env.secrets", 157 | ".env.sync", 158 | ".sync", 159 | ".flaskenv", 160 | ".env.deploy", 161 | ".env.deployment" 162 | ], 163 | "configuration": "./syntaxes/language-configuration.json" 164 | } 165 | ], 166 | "grammars": [ 167 | { 168 | "language": "dotenv", 169 | "scopeName": "source.dotenv", 170 | "path": "./syntaxes/dotenv.tmLanguage.json" 171 | } 172 | ], 173 | "commands": [ 174 | { 175 | "command": "dotenv.login", 176 | "category": "Dotenv", 177 | "title": "login" 178 | }, 179 | { 180 | "command": "dotenv.logout", 181 | "category": "Dotenv", 182 | "title": "logout" 183 | }, 184 | { 185 | "command": "dotenv.new", 186 | "category": "Dotenv", 187 | "title": "new" 188 | }, 189 | { 190 | "command": "dotenv.open", 191 | "category": "Dotenv", 192 | "title": "open" 193 | }, 194 | { 195 | "command": "dotenv.pull", 196 | "category": "Dotenv", 197 | "title": "pull" 198 | }, 199 | { 200 | "command": "dotenv.push", 201 | "category": "Dotenv", 202 | "title": "push" 203 | }, 204 | { 205 | "command": "dotenv.status", 206 | "category": "Dotenv", 207 | "title": "status" 208 | }, 209 | { 210 | "command": "dotenv.versions", 211 | "category": "Dotenv", 212 | "title": "versions" 213 | }, 214 | { 215 | "command": "dotenv.whoami", 216 | "category": "Dotenv", 217 | "title": "whoami" 218 | }, 219 | { 220 | "command": "dotenv.toggleAutocloaking", 221 | "category": "Dotenv", 222 | "title": "Toggle auto-cloaking" 223 | } 224 | ] 225 | }, 226 | "scripts": { 227 | "lint": "standard --fix", 228 | "pretest": "npm run lint", 229 | "test": "node ./test/runTest.js", 230 | "package": "npm run lint && vsce package", 231 | "install-package": "code --install-extension", 232 | "login": "vsce login", 233 | "publish": "npm install && npm run lint && vsce package && vsce publish" 234 | }, 235 | "publisher": "dotenv", 236 | "devDependencies": { 237 | "@types/glob": "^7.2.0", 238 | "@types/mocha": "^9.1.1", 239 | "@types/node": "16.x", 240 | "@types/vscode": "^1.65.0", 241 | "@vscode/test-electron": "^2.1.5", 242 | "eslint": "^8.18.0", 243 | "glob": "^8.0.3", 244 | "mocha": "^10.0.0", 245 | "standard": "^17.0.0", 246 | "typescript": "^4.7.4", 247 | "vsce": "^2.10.0" 248 | }, 249 | "standard": { 250 | "ignore": [ 251 | "/test/suite/examples/**" 252 | ] 253 | }, 254 | "keywords": [ 255 | "dotenv", 256 | "dotenv-vault", 257 | "environment variables", 258 | "vault", 259 | "env", 260 | ".env", 261 | "environment", 262 | "variables", 263 | "config", 264 | "settings", 265 | "official", 266 | "development", 267 | "productivity", 268 | "secrets", 269 | "sync", 270 | "cloak", 271 | "mask", 272 | "hide", 273 | "blur" 274 | ], 275 | "dependencies": { 276 | "dotenv": "^16.0.2" 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /syntaxes/dotenv-legacy.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopeName": "source.dotenv", 3 | "patterns": [ 4 | { 5 | "comment": "Comments", 6 | "match": "^\\s?(#.*$)\\n", 7 | "captures": { 8 | "1": { 9 | "patterns": [ 10 | { 11 | "include": "#reminder" 12 | } 13 | ] 14 | } 15 | } 16 | }, 17 | { 18 | "comment": "Entries", 19 | "match": "^\\s?(export\\s?)*([\\w]+)\\s?(\\=)(.*)$", 20 | "captures": { 21 | "1": { 22 | "name": "keyword.other.dotenv" 23 | }, 24 | "2": { 25 | "name": "variable.other.dotenv" 26 | }, 27 | "3": { 28 | "name": "keyword.operator.assignment.dotenv" 29 | }, 30 | "4": { 31 | "patterns": [ 32 | { 33 | "include": "#boolean" 34 | }, 35 | { 36 | "include": "#numeric" 37 | }, 38 | { 39 | "include": "#string" 40 | }, 41 | { 42 | "include": "#interpolated" 43 | }, 44 | { 45 | "include": "#unquoted" 46 | } 47 | ] 48 | } 49 | } 50 | } 51 | ], 52 | "repository": { 53 | "reminder": { 54 | "comment": "Reminder - starts with #", 55 | "match": "(#).*", 56 | "name": "comment.line.number-sign.dotenv", 57 | "captures": { 58 | "1": { 59 | "name": "punctuation.definition.comment.dotenv" 60 | } 61 | } 62 | }, 63 | "boolean": { 64 | "comment": "Boolean Constants", 65 | "match": "(?i)\\b(true|false|null)\\b(.*)", 66 | "captures": { 67 | "1": { 68 | "name": "constant.language.dotenv" 69 | }, 70 | "2": { 71 | "patterns": [ 72 | { 73 | "include": "#reminder" 74 | } 75 | ] 76 | } 77 | } 78 | }, 79 | "numeric": { 80 | "comment": "Numeric", 81 | "match": "(?:\\+|-)?\\b((?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b(.*)", 82 | "captures": { 83 | "1": { 84 | "name": "constant.numeric.dotenv" 85 | }, 86 | "2": { 87 | "patterns": [ 88 | { 89 | "include": "#reminder" 90 | } 91 | ] 92 | } 93 | } 94 | }, 95 | "string": { 96 | "comment": "Strings (single)", 97 | "name": "string.quoted.single.dotenv", 98 | "begin": "(? 2 | 3 | 4 | { 12 | vscode.window.showInformationMessage('Start all tests.') 13 | 14 | it('Sample test', async function () { 15 | assert.strictEqual(-1, [1, 2, 3].indexOf(5)) 16 | assert.strictEqual(-1, [1, 2, 3].indexOf(0)) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /test/suite/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const Mocha = require('mocha') 3 | const glob = require('glob') 4 | 5 | function run () { 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 | 14 | return new Promise((resolve, reject) => { 15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 16 | if (err) { 17 | return reject(err) 18 | } 19 | 20 | // Add files to the test suite 21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))) 22 | 23 | try { 24 | // Run the mocha test 25 | mocha.run(failures => { 26 | if (failures > 0) { 27 | reject(new Error(`${failures} tests failed.`)) 28 | } else { 29 | resolve() 30 | } 31 | }) 32 | } catch (err) { 33 | console.error(err) 34 | reject(err) 35 | } 36 | }) 37 | }) 38 | } 39 | 40 | module.exports = { 41 | run 42 | } 43 | -------------------------------------------------------------------------------- /test/suite/lib/helpers.test.js: -------------------------------------------------------------------------------- 1 | const mocha = require('mocha') 2 | const describe = mocha.describe 3 | const it = mocha.it 4 | const assert = require('assert') 5 | 6 | const helpers = require('../../../lib/helpers') 7 | 8 | describe('helpers', function () { 9 | describe('#envParsed', function () { 10 | it('returns envParsed', function () { 11 | const result = helpers.envParsed() 12 | 13 | assert.equal(result.HELLO, 'World') 14 | }) 15 | }) 16 | 17 | describe('#envEntries', function () { 18 | it('returns', function () { 19 | const result = helpers.envEntries() 20 | 21 | assert.deepEqual(result[0], ['HELLO', 'World']) 22 | }) 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /test/suite/lib/providers.test.js: -------------------------------------------------------------------------------- 1 | const mocha = require('mocha') 2 | const describe = mocha.describe 3 | const it = mocha.it 4 | const assert = require('assert') 5 | const path = require('path') 6 | const vscode = require('vscode') 7 | 8 | const settings = require('../../../lib/settings') 9 | const providers = require('../../../lib/providers') 10 | 11 | describe('providers', function () { 12 | describe('#javascriptCompletion', function () { 13 | it('returns undefined at line 0 and wrong position for process', async function () { 14 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 15 | const document = await vscode.workspace.openTextDocument(javascriptFile) 16 | const position = new vscode.Position(1, 22) 17 | 18 | const result = providers.javascriptCompletion.provideCompletionItems(document, position) 19 | 20 | assert.equal(result, undefined) 21 | }) 22 | 23 | it('returns value at line 1 and correct position for process', async function () { 24 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 25 | const document = await vscode.workspace.openTextDocument(javascriptFile) 26 | const position = new vscode.Position(1, 24) 27 | 28 | const result = providers.javascriptCompletion.provideCompletionItems(document, position) 29 | 30 | assert.equal(result[0].insertText, '.HELLO') 31 | assert.equal(result[0].label.label, 'HELLO') 32 | assert.equal(result[0].label.detail, ' World') 33 | }) 34 | 35 | it('returns undefined at line 0 and wrong position for import.meta', async function () { 36 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 37 | const document = await vscode.workspace.openTextDocument(javascriptFile) 38 | const position = new vscode.Position(3, 27) 39 | 40 | const result = providers.javascriptCompletion.provideCompletionItems(document, position) 41 | 42 | assert.equal(result, undefined) 43 | }) 44 | 45 | it('returns value at line 1 and correct position for import.meta', async function () { 46 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 47 | const document = await vscode.workspace.openTextDocument(javascriptFile) 48 | const position = new vscode.Position(3, 28) 49 | 50 | const result = providers.javascriptCompletion.provideCompletionItems(document, position) 51 | 52 | assert.equal(result[0].insertText, '.HELLO') 53 | assert.equal(result[0].label.label, 'HELLO') 54 | assert.equal(result[0].label.detail, ' World') 55 | }) 56 | }) 57 | 58 | describe('#rubyCompletion', function () { 59 | it('returns undefined at line 0 and wrong position', async function () { 60 | const rubyFile = path.join(__dirname, '..', 'examples', 'ruby.rb') 61 | const document = await vscode.workspace.openTextDocument(rubyFile) 62 | const position = new vscode.Position(1, 7) 63 | 64 | const result = providers.rubyCompletion.provideCompletionItems(document, position) 65 | 66 | assert.equal(result, undefined) 67 | }) 68 | 69 | it('returns value at line 1 and correct position', async function () { 70 | const rubyFile = path.join(__dirname, '..', 'examples', 'ruby.rb') 71 | const document = await vscode.workspace.openTextDocument(rubyFile) 72 | const position = new vscode.Position(1, 9) 73 | 74 | const result = providers.rubyCompletion.provideCompletionItems(document, position) 75 | 76 | assert.equal(result[0].insertText, '["HELLO"') 77 | assert.equal(result[0].label.label, 'HELLO') 78 | assert.equal(result[0].label.detail, ' World') 79 | }) 80 | }) 81 | 82 | describe('#pythonCompletion', function () { 83 | it('returns undefined at line 0 and wrong position for os.environ.get format', async function () { 84 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 85 | const document = await vscode.workspace.openTextDocument(pythonFile) 86 | const position = new vscode.Position(3, 19) 87 | 88 | const result = providers.pythonCompletion.provideCompletionItems(document, position) 89 | 90 | assert.equal(result, undefined) 91 | }) 92 | 93 | it('returns value at line 1 and correct position for os.environ.get format', async function () { 94 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 95 | const document = await vscode.workspace.openTextDocument(pythonFile) 96 | const position = new vscode.Position(3, 21) 97 | 98 | const result = providers.pythonCompletion.provideCompletionItems(document, position) 99 | 100 | assert.equal(result[0].insertText, '("HELLO"') 101 | assert.equal(result[0].label.label, 'HELLO') 102 | assert.equal(result[0].label.detail, ' World') 103 | }) 104 | 105 | it('returns undefined at line 0 and wrong position for os.getenv format', async function () { 106 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 107 | const document = await vscode.workspace.openTextDocument(pythonFile) 108 | const position = new vscode.Position(4, 13) 109 | 110 | const result = providers.pythonCompletion.provideCompletionItems(document, position) 111 | 112 | assert.equal(result, undefined) 113 | }) 114 | 115 | it('returns value at line 1 and correct position for os.getenv format', async function () { 116 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 117 | const document = await vscode.workspace.openTextDocument(pythonFile) 118 | const position = new vscode.Position(4, 16) 119 | 120 | const result = providers.pythonCompletion.provideCompletionItems(document, position) 121 | 122 | assert.equal(result[0].insertText, '("HELLO"') 123 | assert.equal(result[0].label.label, 'HELLO') 124 | assert.equal(result[0].label.detail, ' World') 125 | }) 126 | 127 | it('returns undefined at line 0 and wrong position for os.environ[] format', async function () { 128 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 129 | const document = await vscode.workspace.openTextDocument(pythonFile) 130 | const position = new vscode.Position(5, 15) 131 | 132 | const result = providers.pythonArrayCompletion.provideCompletionItems(document, position) 133 | 134 | assert.equal(result, undefined) 135 | }) 136 | 137 | it('returns value at line 1 and correct position for os.environ[] format', async function () { 138 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 139 | const document = await vscode.workspace.openTextDocument(pythonFile) 140 | const position = new vscode.Position(5, 17) 141 | 142 | const result = providers.pythonArrayCompletion.provideCompletionItems(document, position) 143 | 144 | assert.equal(result[0].insertText, '["HELLO"') 145 | assert.equal(result[0].label.label, 'HELLO') 146 | assert.equal(result[0].label.detail, ' World') 147 | }) 148 | }) 149 | 150 | describe('#phpCompletion', function () { 151 | it('returns undefined at line 0 and wrong position for $_ENV[] format', async function () { 152 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 153 | const document = await vscode.workspace.openTextDocument(phpFile) 154 | const position = new vscode.Position(3, 15) 155 | 156 | const result = providers.phpCompletion.provideCompletionItems(document, position) 157 | 158 | assert.equal(result, undefined) 159 | }) 160 | 161 | it('returns value at line 1 and correct position for $_ENV[] format', async function () { 162 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 163 | const document = await vscode.workspace.openTextDocument(phpFile) 164 | const position = new vscode.Position(3, 17) 165 | 166 | const result = providers.phpCompletion.provideCompletionItems(document, position) 167 | 168 | assert.equal(result[0].insertText, '["HELLO"') 169 | assert.equal(result[0].label.label, 'HELLO') 170 | assert.equal(result[0].label.detail, ' World') 171 | }) 172 | 173 | it('returns undefined at line 0 and wrong position for $_SERVER[] format', async function () { 174 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 175 | const document = await vscode.workspace.openTextDocument(phpFile) 176 | const position = new vscode.Position(4, 18) 177 | 178 | const result = providers.phpCompletion.provideCompletionItems(document, position) 179 | 180 | assert.equal(result, undefined) 181 | }) 182 | 183 | it('returns value at line 1 and correct position for $_SERVER[] format', async function () { 184 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 185 | const document = await vscode.workspace.openTextDocument(phpFile) 186 | const position = new vscode.Position(4, 20) 187 | 188 | const result = providers.phpCompletion.provideCompletionItems(document, position) 189 | 190 | assert.equal(result[0].insertText, '["HELLO"') 191 | assert.equal(result[0].label.label, 'HELLO') 192 | assert.equal(result[0].label.detail, ' World') 193 | }) 194 | 195 | it('returns undefined at line 0 and wrong position for getenv() format', async function () { 196 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 197 | const document = await vscode.workspace.openTextDocument(phpFile) 198 | const position = new vscode.Position(5, 16) 199 | 200 | const result = providers.phpGetEnvCompletion.provideCompletionItems(document, position) 201 | 202 | assert.equal(result, undefined) 203 | }) 204 | 205 | it('returns value at line 1 and correct position for getenv() format', async function () { 206 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 207 | const document = await vscode.workspace.openTextDocument(phpFile) 208 | const position = new vscode.Position(5, 18) 209 | 210 | const result = providers.phpGetEnvCompletion.provideCompletionItems(document, position) 211 | 212 | assert.equal(result[0].insertText, '("HELLO"') 213 | assert.equal(result[0].label.label, 'HELLO') 214 | assert.equal(result[0].label.detail, ' World') 215 | }) 216 | }) 217 | 218 | describe('#goCompletion', function () { 219 | it('returns undefined at line 0 and wrong position', async function () { 220 | const goFile = path.join(__dirname, '..', 'examples', 'go.go') 221 | const document = await vscode.workspace.openTextDocument(goFile) 222 | const position = new vscode.Position(1, 8) 223 | 224 | const result = providers.goCompletion.provideCompletionItems(document, position) 225 | 226 | assert.equal(result, undefined) 227 | }) 228 | 229 | it('returns value at line 1 and correct position', async function () { 230 | const goFile = path.join(__dirname, '..', 'examples', 'go.go') 231 | const document = await vscode.workspace.openTextDocument(goFile) 232 | const position = new vscode.Position(1, 10) 233 | 234 | const result = providers.goCompletion.provideCompletionItems(document, position) 235 | 236 | assert.equal(result[0].insertText, '("HELLO"') 237 | assert.equal(result[0].label.label, 'HELLO') 238 | assert.equal(result[0].label.detail, ' World') 239 | }) 240 | }) 241 | 242 | describe('#javaCompletion', function () { 243 | it('returns undefined at line 0 and wrong position', async function () { 244 | const javaFile = path.join(__dirname, '..', 'examples', 'java.java') 245 | const document = await vscode.workspace.openTextDocument(javaFile) 246 | const position = new vscode.Position(1, 8) 247 | 248 | const result = providers.javaCompletion.provideCompletionItems(document, position) 249 | 250 | assert.equal(result, undefined) 251 | }) 252 | 253 | it('returns value at line 1 and correct position', async function () { 254 | const javaFile = path.join(__dirname, '..', 'examples', 'java.java') 255 | const document = await vscode.workspace.openTextDocument(javaFile) 256 | const position = new vscode.Position(1, 11) 257 | 258 | const result = providers.javaCompletion.provideCompletionItems(document, position) 259 | 260 | assert.equal(result[0].insertText, '("HELLO"') 261 | assert.equal(result[0].label.label, 'HELLO') 262 | assert.equal(result[0].label.detail, ' World') 263 | }) 264 | }) 265 | 266 | describe('#csharpCompletion', function () { 267 | it('returns undefined at line 0 and wrong position', async function () { 268 | const csharpFile = path.join(__dirname, '..', 'examples', 'csharp.cs') 269 | const document = await vscode.workspace.openTextDocument(csharpFile) 270 | const position = new vscode.Position(1, 32) 271 | 272 | const result = providers.csharpCompletion.provideCompletionItems(document, position) 273 | 274 | assert.equal(result, undefined) 275 | }) 276 | 277 | it('returns value at line 1 and correct position', async function () { 278 | const csharpFile = path.join(__dirname, '..', 'examples', 'csharp.cs') 279 | const document = await vscode.workspace.openTextDocument(csharpFile) 280 | const position = new vscode.Position(1, 35) 281 | 282 | const result = providers.csharpCompletion.provideCompletionItems(document, position) 283 | 284 | assert.equal(result[0].insertText, '("HELLO"') 285 | assert.equal(result[0].label.label, 'HELLO') 286 | assert.equal(result[0].label.detail, ' World') 287 | }) 288 | }) 289 | 290 | describe('#rustCompletion', function () { 291 | it('returns undefined at line 0 and wrong position with var format', async function () { 292 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 293 | const document = await vscode.workspace.openTextDocument(rustFile) 294 | const position = new vscode.Position(1, 12) 295 | 296 | const result = providers.rustCompletion.provideCompletionItems(document, position) 297 | 298 | assert.equal(result, undefined) 299 | }) 300 | 301 | it('returns value at line 1 and correct position with var format', async function () { 302 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 303 | const document = await vscode.workspace.openTextDocument(rustFile) 304 | const position = new vscode.Position(1, 14) 305 | 306 | const result = providers.rustCompletion.provideCompletionItems(document, position) 307 | 308 | assert.equal(result[0].insertText, '("HELLO"') 309 | assert.equal(result[0].label.label, 'HELLO') 310 | assert.equal(result[0].label.detail, ' World') 311 | }) 312 | 313 | it('returns undefined at line 0 and wrong position with var_os format', async function () { 314 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 315 | const document = await vscode.workspace.openTextDocument(rustFile) 316 | const position = new vscode.Position(3, 15) 317 | 318 | const result = providers.rustCompletion.provideCompletionItems(document, position) 319 | 320 | assert.equal(result, undefined) 321 | }) 322 | 323 | it('returns value at line 1 and correct position with var_os format', async function () { 324 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 325 | const document = await vscode.workspace.openTextDocument(rustFile) 326 | const position = new vscode.Position(3, 17) 327 | 328 | const result = providers.rustCompletion.provideCompletionItems(document, position) 329 | 330 | assert.equal(result[0].insertText, '("HELLO"') 331 | assert.equal(result[0].label.label, 'HELLO') 332 | assert.equal(result[0].label.detail, ' World') 333 | }) 334 | }) 335 | 336 | describe('#dartCompletion', function () { 337 | it('returns undefined at line 0 and wrong position', async function () { 338 | const dartFile = path.join(__dirname, '..', 'examples', 'dart.dart') 339 | const document = await vscode.workspace.openTextDocument(dartFile) 340 | const position = new vscode.Position(1, 21) 341 | 342 | const result = providers.dartCompletion.provideCompletionItems(document, position) 343 | 344 | assert.equal(result, undefined) 345 | }) 346 | 347 | it('returns value at line 1 and correct position', async function () { 348 | const dartFile = path.join(__dirname, '..', 'examples', 'dart.dart') 349 | const document = await vscode.workspace.openTextDocument(dartFile) 350 | const position = new vscode.Position(1, 23) 351 | 352 | const result = providers.dartCompletion.provideCompletionItems(document, position) 353 | 354 | assert.equal(result[0].insertText, '("HELLO"') 355 | assert.equal(result[0].label.label, 'HELLO') 356 | assert.equal(result[0].label.detail, ' World') 357 | }) 358 | }) 359 | 360 | describe('#kotlinCompletion', function () { 361 | it('returns undefined at line 0 and wrong position', async function () { 362 | const kotlinFile = path.join(__dirname, '..', 'examples', 'kotlin.kt') 363 | const document = await vscode.workspace.openTextDocument(kotlinFile) 364 | const position = new vscode.Position(1, 12) 365 | 366 | const result = providers.kotlinCompletion.provideCompletionItems(document, position) 367 | 368 | assert.equal(result, undefined) 369 | }) 370 | 371 | it('returns value at line 1 and correct position', async function () { 372 | const kotlinFile = path.join(__dirname, '..', 'examples', 'kotlin.kt') 373 | const document = await vscode.workspace.openTextDocument(kotlinFile) 374 | const position = new vscode.Position(1, 14) 375 | 376 | const result = providers.kotlinCompletion.provideCompletionItems(document, position) 377 | 378 | assert.equal(result[0].insertText, '("HELLO"') 379 | assert.equal(result[0].label.label, 'HELLO') 380 | assert.equal(result[0].label.detail, ' World') 381 | }) 382 | }) 383 | 384 | describe('#elixirCompletion', function () { 385 | it('returns undefined at line 0 and wrong position', async function () { 386 | const elixirFile = path.join(__dirname, '..', 'examples', 'elixir.exs') 387 | const document = await vscode.workspace.openTextDocument(elixirFile) 388 | const position = new vscode.Position(1, 13) 389 | 390 | const result = providers.elixirCompletion.provideCompletionItems(document, position) 391 | 392 | assert.equal(result, undefined) 393 | }) 394 | 395 | it('returns value at line 1 and correct position', async function () { 396 | const elixirFile = path.join(__dirname, '..', 'examples', 'elixir.exs') 397 | const document = await vscode.workspace.openTextDocument(elixirFile) 398 | const position = new vscode.Position(1, 15) 399 | 400 | const result = providers.elixirCompletion.provideCompletionItems(document, position) 401 | 402 | assert.equal(result[0].insertText, '("HELLO"') 403 | assert.equal(result[0].label.label, 'HELLO') 404 | assert.equal(result[0].label.detail, ' World') 405 | }) 406 | }) 407 | 408 | describe('#javascriptHover', function () { 409 | it('returns undefined at 0 line for process', async function () { 410 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 411 | const document = await vscode.workspace.openTextDocument(javascriptFile) 412 | const position = new vscode.Position(0, 22) 413 | 414 | const result = providers.javascriptHover.provideHover(document, position) 415 | 416 | assert.equal(result.contents[0], settings.missingText()) 417 | }) 418 | 419 | it('returns value at 0 line and correct position for process', async function () { 420 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 421 | const document = await vscode.workspace.openTextDocument(javascriptFile) 422 | const position = new vscode.Position(0, 26) 423 | 424 | const result = providers.javascriptHover.provideHover(document, position) 425 | 426 | assert.equal(result.contents[0], 'World') 427 | }) 428 | 429 | it('returns undefined at 0 line for import.meta', async function () { 430 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 431 | const document = await vscode.workspace.openTextDocument(javascriptFile) 432 | const position = new vscode.Position(2, 27) 433 | 434 | const result = providers.javascriptHover.provideHover(document, position) 435 | 436 | assert.equal(result.contents[0], settings.missingText()) 437 | }) 438 | 439 | it('returns value at 0 line and correct position for import.meta', async function () { 440 | const javascriptFile = path.join(__dirname, '..', 'examples', 'javascript.js') 441 | const document = await vscode.workspace.openTextDocument(javascriptFile) 442 | const position = new vscode.Position(2, 30) 443 | 444 | const result = providers.javascriptHover.provideHover(document, position) 445 | 446 | assert.equal(result.contents[0], 'World') 447 | }) 448 | }) 449 | 450 | describe('#rubyHover', function () { 451 | it('returns undefined at 0 line', async function () { 452 | const rubyFile = path.join(__dirname, '..', 'examples', 'ruby.rb') 453 | const document = await vscode.workspace.openTextDocument(rubyFile) 454 | const position = new vscode.Position(0, 9) 455 | 456 | const result = providers.rubyHover.provideHover(document, position) 457 | 458 | assert.equal(result.contents[0], settings.missingText()) 459 | }) 460 | 461 | it('returns value at 0 line and correct position', async function () { 462 | const rubyFile = path.join(__dirname, '..', 'examples', 'ruby.rb') 463 | const document = await vscode.workspace.openTextDocument(rubyFile) 464 | const position = new vscode.Position(0, 13) 465 | 466 | const result = providers.rubyHover.provideHover(document, position) 467 | 468 | assert.equal(result.contents[0], 'World') 469 | }) 470 | }) 471 | 472 | describe('#pythonHover', function () { 473 | it('returns undefined at 0 line for os.environ.get format', async function () { 474 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 475 | const document = await vscode.workspace.openTextDocument(pythonFile) 476 | const position = new vscode.Position(0, 19) 477 | 478 | const result = providers.pythonHover.provideHover(document, position) 479 | 480 | assert.equal(result.contents[0], settings.missingText()) 481 | }) 482 | 483 | it('returns value at 0 line and correct position for os.environ.get format', async function () { 484 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 485 | const document = await vscode.workspace.openTextDocument(pythonFile) 486 | const position = new vscode.Position(0, 23) 487 | 488 | const result = providers.pythonHover.provideHover(document, position) 489 | 490 | assert.equal(result.contents[0], 'World') 491 | }) 492 | 493 | it('returns undefined at 0 line for os.getenv format', async function () { 494 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 495 | const document = await vscode.workspace.openTextDocument(pythonFile) 496 | const position = new vscode.Position(1, 13) 497 | 498 | const result = providers.pythonHover.provideHover(document, position) 499 | 500 | assert.equal(result.contents[0], settings.missingText()) 501 | }) 502 | 503 | it('returns value at 0 line and correct position for os.getenv format', async function () { 504 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 505 | const document = await vscode.workspace.openTextDocument(pythonFile) 506 | const position = new vscode.Position(1, 17) 507 | 508 | const result = providers.pythonHover.provideHover(document, position) 509 | 510 | assert.equal(result.contents[0], 'World') 511 | }) 512 | 513 | it('returns undefined at 0 line for os.environ[] format', async function () { 514 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 515 | const document = await vscode.workspace.openTextDocument(pythonFile) 516 | const position = new vscode.Position(2, 14) 517 | 518 | const result = providers.pythonHover.provideHover(document, position) 519 | 520 | assert.equal(result.contents[0], settings.missingText()) 521 | }) 522 | 523 | it('returns value at 0 line and correct position for os.environ[] format', async function () { 524 | const pythonFile = path.join(__dirname, '..', 'examples', 'python.py') 525 | const document = await vscode.workspace.openTextDocument(pythonFile) 526 | const position = new vscode.Position(2, 18) 527 | 528 | const result = providers.pythonHover.provideHover(document, position) 529 | 530 | assert.equal(result.contents[0], 'World') 531 | }) 532 | }) 533 | 534 | describe('#phpHover', function () { 535 | it('returns undefined at 0 line for $_ENV[] format', async function () { 536 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 537 | const document = await vscode.workspace.openTextDocument(phpFile) 538 | const position = new vscode.Position(0, 15) 539 | 540 | const result = providers.phpHover.provideHover(document, position) 541 | 542 | assert.equal(result.contents[0], settings.missingText()) 543 | }) 544 | 545 | it('returns value at 0 line and correct position for $_ENV[] format', async function () { 546 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 547 | const document = await vscode.workspace.openTextDocument(phpFile) 548 | const position = new vscode.Position(0, 20) 549 | 550 | const result = providers.phpHover.provideHover(document, position) 551 | 552 | assert.equal(result.contents[0], 'World') 553 | }) 554 | 555 | it('returns undefined at 0 line for $_SERVER[] format', async function () { 556 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 557 | const document = await vscode.workspace.openTextDocument(phpFile) 558 | const position = new vscode.Position(1, 17) 559 | 560 | const result = providers.phpHover.provideHover(document, position) 561 | 562 | assert.equal(result.contents[0], settings.missingText()) 563 | }) 564 | 565 | it('returns value at 0 line and correct position for $_SERVER[] format', async function () { 566 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 567 | const document = await vscode.workspace.openTextDocument(phpFile) 568 | const position = new vscode.Position(1, 22) 569 | 570 | const result = providers.phpHover.provideHover(document, position) 571 | 572 | assert.equal(result.contents[0], 'World') 573 | }) 574 | 575 | it('returns undefined at 0 line for getenv() format', async function () { 576 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 577 | const document = await vscode.workspace.openTextDocument(phpFile) 578 | const position = new vscode.Position(2, 16) 579 | 580 | const result = providers.phpHover.provideHover(document, position) 581 | 582 | assert.equal(result.contents[0], settings.missingText()) 583 | }) 584 | 585 | it('returns value at 0 line and correct position for getenv() format', async function () { 586 | const phpFile = path.join(__dirname, '..', 'examples', 'php.php') 587 | const document = await vscode.workspace.openTextDocument(phpFile) 588 | const position = new vscode.Position(2, 22) 589 | 590 | const result = providers.phpHover.provideHover(document, position) 591 | 592 | assert.equal(result.contents[0], 'World') 593 | }) 594 | }) 595 | 596 | describe('#goHover', function () { 597 | it('returns undefined at 0 line', async function () { 598 | const goFile = path.join(__dirname, '..', 'examples', 'go.go') 599 | const document = await vscode.workspace.openTextDocument(goFile) 600 | const position = new vscode.Position(0, 9) 601 | 602 | const result = providers.goHover.provideHover(document, position) 603 | 604 | assert.equal(result.contents[0], settings.missingText()) 605 | }) 606 | 607 | it('returns value at 0 line and correct position', async function () { 608 | const goFile = path.join(__dirname, '..', 'examples', 'go.go') 609 | const document = await vscode.workspace.openTextDocument(goFile) 610 | const position = new vscode.Position(0, 13) 611 | 612 | const result = providers.goHover.provideHover(document, position) 613 | 614 | assert.equal(result.contents[0], 'World') 615 | }) 616 | }) 617 | 618 | describe('#javaHover', function () { 619 | it('returns undefined at 0 line', async function () { 620 | const javaFile = path.join(__dirname, '..', 'examples', 'java.java') 621 | const document = await vscode.workspace.openTextDocument(javaFile) 622 | const position = new vscode.Position(0, 9) 623 | 624 | const result = providers.javaHover.provideHover(document, position) 625 | 626 | assert.equal(result.contents[0], settings.missingText()) 627 | }) 628 | 629 | it('returns value at 0 line and correct position', async function () { 630 | const javaFile = path.join(__dirname, '..', 'examples', 'java.java') 631 | const document = await vscode.workspace.openTextDocument(javaFile) 632 | const position = new vscode.Position(0, 16) 633 | 634 | const result = providers.javaHover.provideHover(document, position) 635 | 636 | assert.equal(result.contents[0], 'World') 637 | }) 638 | }) 639 | 640 | describe('#csharpHover', function () { 641 | it('returns undefined at 0 line', async function () { 642 | const csharpFile = path.join(__dirname, '..', 'examples', 'csharp.cs') 643 | const document = await vscode.workspace.openTextDocument(csharpFile) 644 | const position = new vscode.Position(0, 32) 645 | 646 | const result = providers.csharpHover.provideHover(document, position) 647 | 648 | assert.equal(result.contents[0], settings.missingText()) 649 | }) 650 | 651 | it('returns value at 0 line and correct position', async function () { 652 | const csharpFile = path.join(__dirname, '..', 'examples', 'csharp.cs') 653 | const document = await vscode.workspace.openTextDocument(csharpFile) 654 | const position = new vscode.Position(0, 37) 655 | 656 | const result = providers.csharpHover.provideHover(document, position) 657 | 658 | assert.equal(result.contents[0], 'World') 659 | }) 660 | }) 661 | 662 | describe('#rustHover', function () { 663 | it('returns undefined at 0 line with var format', async function () { 664 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 665 | const document = await vscode.workspace.openTextDocument(rustFile) 666 | const position = new vscode.Position(0, 12) 667 | 668 | const result = providers.rustHover.provideHover(document, position) 669 | 670 | assert.equal(result.contents[0], settings.missingText()) 671 | }) 672 | 673 | it('returns value at 0 line and correct position with var format', async function () { 674 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 675 | const document = await vscode.workspace.openTextDocument(rustFile) 676 | const position = new vscode.Position(0, 16) 677 | 678 | const result = providers.rustHover.provideHover(document, position) 679 | 680 | assert.equal(result.contents[0], 'World') 681 | }) 682 | 683 | it('returns undefined at 0 line with var_os format', async function () { 684 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 685 | const document = await vscode.workspace.openTextDocument(rustFile) 686 | const position = new vscode.Position(2, 12) 687 | 688 | const result = providers.rustHover.provideHover(document, position) 689 | 690 | assert.equal(result.contents[0], settings.missingText()) 691 | }) 692 | 693 | it('returns value at 0 line and correct position with var_os format', async function () { 694 | const rustFile = path.join(__dirname, '..', 'examples', 'rust.rs') 695 | const document = await vscode.workspace.openTextDocument(rustFile) 696 | const position = new vscode.Position(2, 22) 697 | 698 | const result = providers.rustHover.provideHover(document, position) 699 | 700 | assert.equal(result.contents[0], 'World') 701 | }) 702 | }) 703 | 704 | describe('#dartHover', function () { 705 | it('returns undefined at 0 line with var format', async function () { 706 | const dartFile = path.join(__dirname, '..', 'examples', 'dart.dart') 707 | const document = await vscode.workspace.openTextDocument(dartFile) 708 | const position = new vscode.Position(0, 21) 709 | 710 | const result = providers.dartHover.provideHover(document, position) 711 | 712 | assert.equal(result.contents[0], settings.missingText()) 713 | }) 714 | 715 | it('returns value at 0 line and correct position', async function () { 716 | const dartFile = path.join(__dirname, '..', 'examples', 'dart.dart') 717 | const document = await vscode.workspace.openTextDocument(dartFile) 718 | const position = new vscode.Position(0, 27) 719 | 720 | const result = providers.dartHover.provideHover(document, position) 721 | 722 | assert.equal(result.contents[0], 'World') 723 | }) 724 | }) 725 | 726 | describe('#kotlinHover', function () { 727 | it('returns undefined at 0 line with var format', async function () { 728 | const kotlinFile = path.join(__dirname, '..', 'examples', 'kotlin.kt') 729 | const document = await vscode.workspace.openTextDocument(kotlinFile) 730 | const position = new vscode.Position(0, 12) 731 | 732 | const result = providers.kotlinHover.provideHover(document, position) 733 | 734 | assert.equal(result.contents[0], settings.missingText()) 735 | }) 736 | 737 | it('returns value at 0 line and correct position', async function () { 738 | const kotlinFile = path.join(__dirname, '..', 'examples', 'kotlin.kt') 739 | const document = await vscode.workspace.openTextDocument(kotlinFile) 740 | const position = new vscode.Position(0, 17) 741 | 742 | const result = providers.kotlinHover.provideHover(document, position) 743 | 744 | assert.equal(result.contents[0], 'World') 745 | }) 746 | }) 747 | 748 | describe('#elixirHover', function () { 749 | it('returns undefined at 0 line with var format', async function () { 750 | const elixirFile = path.join(__dirname, '..', 'examples', 'elixir.exs') 751 | const document = await vscode.workspace.openTextDocument(elixirFile) 752 | const position = new vscode.Position(0, 12) 753 | 754 | const result = providers.elixirHover.provideHover(document, position) 755 | 756 | assert.equal(result.contents[0], settings.missingText()) 757 | }) 758 | 759 | it('returns value at 0 line and correct position', async function () { 760 | const elixirFile = path.join(__dirname, '..', 'examples', 'elixir.exs') 761 | const document = await vscode.workspace.openTextDocument(elixirFile) 762 | const position = new vscode.Position(0, 17) 763 | 764 | const result = providers.elixirHover.provideHover(document, position) 765 | 766 | assert.equal(result.contents[0], 'World') 767 | }) 768 | }) 769 | }) 770 | -------------------------------------------------------------------------------- /test/suite/lib/settings.test.js: -------------------------------------------------------------------------------- 1 | const mocha = require('mocha') 2 | const describe = mocha.describe 3 | const it = mocha.it 4 | const assert = require('assert') 5 | 6 | const settings = require('../../../lib/settings') 7 | 8 | describe('settings', function () { 9 | describe('#userConfig', function () { 10 | it('returns user configuration', function () { 11 | const result = settings.userConfig() 12 | 13 | assert.strictEqual(typeof result, 'object') 14 | }) 15 | }) 16 | 17 | describe('#autocloakingEnabled', function () { 18 | it('is true by default', function () { 19 | const result = settings.autocloakingEnabled() 20 | 21 | assert.equal(result, true) 22 | }) 23 | 24 | it('can be turned on and off', async function () { 25 | await settings.autocloakingOff() 26 | let result = settings.autocloakingEnabled() 27 | assert.equal(result, false) 28 | 29 | await settings.autocloakingOn() 30 | result = settings.autocloakingEnabled() 31 | assert.equal(result, true) 32 | }) 33 | }) 34 | 35 | describe('#secretpeekingEnabled', function () { 36 | it('is true by default', function () { 37 | const result = settings.secretpeekingEnabled() 38 | 39 | assert.equal(result, true) 40 | }) 41 | }) 42 | 43 | describe('#cloakColor', function () { 44 | it('is 000000 by default', function () { 45 | const result = settings.cloakColor() 46 | 47 | assert.equal(result, '#000000') 48 | }) 49 | }) 50 | 51 | describe('#cloakIcon', function () { 52 | it('is █ by default', function () { 53 | const result = settings.cloakIcon() 54 | 55 | assert.equal(result, '█') 56 | }) 57 | }) 58 | 59 | describe('#missingText', function () { 60 | it('is █ by default', function () { 61 | const result = settings.missingText() 62 | 63 | assert.equal(result, 'MISSING from .env file') 64 | }) 65 | }) 66 | }) 67 | --------------------------------------------------------------------------------