├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── icon.png ├── package-lock.json ├── package.json ├── src └── extension.ts ├── tsconfig.json └── tslint.json /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v1 14 | 15 | - name: Use Node.js 12.x 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: 12.x 19 | 20 | - name: install 21 | run: | 22 | npm ci 23 | env: 24 | CI: 1 25 | 26 | - name: build 27 | run: | 28 | npm run compile 29 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v1 13 | 14 | - name: Use Node.js 12.x 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 12.x 18 | 19 | - name: install 20 | run: | 21 | npm ci 22 | npm i -g vsce 23 | env: 24 | CI: 1 25 | 26 | - name: Build & Package 27 | run: | 28 | npm run compile 29 | vsce package 30 | 31 | - name: Publish 32 | run: | 33 | vsce publish -p $VSCE_TOKEN 34 | cp format-code-action-*.vsix format-code-action.vsix 35 | env: 36 | VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }} 37 | 38 | - name: Create Release 39 | id: create_release 40 | uses: softprops/action-gh-release@v1 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | with: 44 | files: format-code-action.vsix 45 | draft: false 46 | prerelease: false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # build 64 | /build 65 | /out 66 | 67 | # misc 68 | .DS_Store 69 | .idea 70 | .env.local 71 | .env.development.local 72 | .env.test.local 73 | .env.production.local 74 | 75 | # Test report 76 | junit.xml 77 | reports 78 | 79 | *.vsix 80 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it 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 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/out/**/*.js" 18 | ], 19 | "preLaunchTask": "npm: watch" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": false 3 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | ## Requirements 4 | 5 | - NodeJS 6 | - VS Code 7 | 8 | ## Setup 9 | 10 | 1. Install dependencies 11 | 12 | ```sh 13 | npm i 14 | ``` 15 | 16 | 1. Open in VS Code 17 | 18 | ```sh 19 | code . 20 | ``` 21 | 22 | 1. Use the `Run Extension` command in Debugger panel to start a new instance of VS Code with extension added 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Rohit Gohri 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 | # Format Code Action 2 | 3 | [![Version](https://vsmarketplacebadges.dev/version-short/rohit-gohri.format-code-action.svg)](https://marketplace.visualstudio.com/items?itemName=rohit-gohri.format-code-action)   [![Installs](https://vsmarketplacebadges.dev/installs/rohit-gohri.format-code-action.svg)](https://marketplace.visualstudio.com/items?itemName=rohit-gohri.format-code-action)   [![Ratings](https://vsmarketplacebadges.dev/rating-star/rohit-gohri.format-code-action.svg)](https://marketplace.visualstudio.com/items?itemName=rohit-gohri.format-code-action) 4 | 5 | Run eslint extension after the prettier extension in VS Code. Or the other way around, whatever way you want. 6 | 7 | ## Installation 8 | 9 | > Requires VS Code 1.44+ 10 | 11 | Install through VS Code extensions: [Visual Studio Code Market Place: Format Code Action](https://marketplace.visualstudio.com/items?itemName=rohit-gohri.format-code-action) 12 | 13 | Or install from within VS Code: Launch VS Code Quick Open (Ctrl+P or cmd+P), paste the following command, and press enter. 14 | 15 | ext install rohit-gohri.format-code-action 16 | 17 | Or on the command line: 18 | 19 | code --install-extension rohit-gohri.format-code-action 20 | 21 | ## Usage 22 | 23 | Disable `formatOnSave` and use the `source.formatDocument` codeAction in whatever order you want with VS Code settings: 24 | 25 | ```json 26 | "editor.formatOnSave": false, 27 | "editor.defaultFormatter": "esbenp.prettier-vscode", 28 | "editor.codeActionsOnSave": [ 29 | "source.formatDocument", 30 | "source.fixAll.eslint" 31 | ] 32 | ``` 33 | 34 | > NOTE: This was first released with `source.fixAll.format` as the codeAction, that still works for legacy purposes. 35 | 36 | This runs 'Format Document' with the default formatter (in this case prettier). 37 | 38 | Or for specific lanuage only: 39 | 40 | ```json 41 | "editor.formatOnSave": true, 42 | "editor.defaultFormatter": "esbenp.prettier-vscode", 43 | "[javascript]": { 44 | "editor.formatOnSave": false, 45 | "editor.codeActionsOnSave": ["source.formatDocument", "source.fixAll.eslint"] 46 | }, 47 | ``` 48 | 49 | This would run prettier by default, but for javascript files would run prettier and then eslint. If you want to reverse the order then just reverse the array. 50 | 51 | ### Format Modified (EXPERIMENTAL) 52 | 53 | Alternatively you may want to format only the modified part of the file, in that case use `source.formatModified`: 54 | 55 | ```json 56 | "editor.formatOnSave": false, 57 | "editor.defaultFormatter": "esbenp.prettier-vscode", 58 | "editor.codeActionsOnSave": [ 59 | "source.formatModified", 60 | "source.fixAll.eslint" 61 | ] 62 | ``` 63 | 64 | This is experimentally supported right now, if you face any problems please report them at: 65 | 66 | ## Motivation 67 | 68 | I created this so I could use prettier and eslint together in the editor, in a specific order (eslint after prettier). Earlier prettier was setup to run on save and eslint as a codeAction with: 69 | 70 | ```json 71 | "editor.formatOnSave": true, 72 | "editor.defaultFormatter": "esbenp.prettier-vscode", 73 | "editor.codeActionsOnSave": { 74 | "source.fixAll.eslint": true 75 | } 76 | ``` 77 | 78 | This would often lead to prettier being run after eslint and eslint errors still being present. 79 | 80 | Since the [March 2020 (v1.44)](https://code.visualstudio.com/updates/v1_44#_explicit-ordering-for-code-actions-on-save) update, VS Code allows setting `codeActionsOnSave` as an array. This allows setting the order of the codeActions. 81 | 82 | The extension uses the [`CodeActionProvider`](https://code.visualstudio.com/api/references/vscode-api#CodeActionProvider) api to implement a simple code action that runs 'Format Document' on the current file. This allows us to disable `formatOnSave` and use it as a codeAction instead in a specific order with other extensions. 83 | 84 | Read More on my blog: [How to get ESlint and Prettier to play nicely in VS Code?](https://rohit.page/blog/posts/how-to-get-prettier-eslint-play-nicely-with-vscode/?utm_source=github&utm_medium=repo&utm_campaign=hf) 85 | 86 | ## VS Code API 87 | 88 | ### `vscode` module 89 | 90 | - [`languages.registerCodeActionsProvider`](https://code.visualstudio.com/api/references/vscode-api#languages.registerCodeActionsProvider) 91 | 92 | ## Credits 93 | 94 | Based on [Microsoft's code-actions-sample](https://github.com/microsoft/vscode-extension-samples/tree/master/code-actions-sample) 95 | 96 | ### Icon 97 | 98 | [formatting by Danil Polshin from the Noun Project](https://thenounproject.com/search/?q=format&i=627383). 99 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohit-gohri/vscode-format-code-action/4356df8a166125a5fff2162c2213620579a157c2/icon.png -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "format-code-action", 3 | "version": "0.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.8.3", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", 10 | "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.8.3" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.9.5", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", 19 | "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.9.0", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", 25 | "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.9.0", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | } 32 | }, 33 | "@types/node": { 34 | "version": "12.12.35", 35 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.35.tgz", 36 | "integrity": "sha512-ASYsaKecA7TUsDrqIGPNk3JeEox0z/0XR/WsJJ8BIX/9+SkMSImQXKWfU/yBrSyc7ZSE/NPqLu36Nur0miCFfQ==", 37 | "dev": true 38 | }, 39 | "@types/vscode": { 40 | "version": "1.33.0", 41 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.33.0.tgz", 42 | "integrity": "sha512-JSmGiValbrcG5g20jjCfKakLiuWyrcjVezj+SEAEZ4klXQktE5EtowuGlkLVqbkiBK4iY5wy/4yW8OjecuHnjQ==", 43 | "dev": true 44 | }, 45 | "ansi-styles": { 46 | "version": "3.2.1", 47 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 48 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 49 | "dev": true, 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "argparse": { 55 | "version": "1.0.10", 56 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 57 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 58 | "dev": true, 59 | "requires": { 60 | "sprintf-js": "~1.0.2" 61 | } 62 | }, 63 | "balanced-match": { 64 | "version": "1.0.0", 65 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 66 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 67 | "dev": true 68 | }, 69 | "brace-expansion": { 70 | "version": "1.1.11", 71 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 72 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 73 | "dev": true, 74 | "requires": { 75 | "balanced-match": "^1.0.0", 76 | "concat-map": "0.0.1" 77 | } 78 | }, 79 | "builtin-modules": { 80 | "version": "1.1.1", 81 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 82 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 83 | "dev": true 84 | }, 85 | "chalk": { 86 | "version": "2.4.2", 87 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 88 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 89 | "dev": true, 90 | "requires": { 91 | "ansi-styles": "^3.2.1", 92 | "escape-string-regexp": "^1.0.5", 93 | "supports-color": "^5.3.0" 94 | } 95 | }, 96 | "color-convert": { 97 | "version": "1.9.3", 98 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 99 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 100 | "dev": true, 101 | "requires": { 102 | "color-name": "1.1.3" 103 | } 104 | }, 105 | "color-name": { 106 | "version": "1.1.3", 107 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 108 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 109 | "dev": true 110 | }, 111 | "commander": { 112 | "version": "2.20.3", 113 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 114 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 115 | "dev": true 116 | }, 117 | "concat-map": { 118 | "version": "0.0.1", 119 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 120 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 121 | "dev": true 122 | }, 123 | "diff": { 124 | "version": "4.0.2", 125 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 126 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 127 | "dev": true 128 | }, 129 | "escape-string-regexp": { 130 | "version": "1.0.5", 131 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 132 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 133 | "dev": true 134 | }, 135 | "esprima": { 136 | "version": "4.0.1", 137 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 138 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 139 | "dev": true 140 | }, 141 | "fs.realpath": { 142 | "version": "1.0.0", 143 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 144 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 145 | "dev": true 146 | }, 147 | "glob": { 148 | "version": "7.1.6", 149 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 150 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 151 | "dev": true, 152 | "requires": { 153 | "fs.realpath": "^1.0.0", 154 | "inflight": "^1.0.4", 155 | "inherits": "2", 156 | "minimatch": "^3.0.4", 157 | "once": "^1.3.0", 158 | "path-is-absolute": "^1.0.0" 159 | } 160 | }, 161 | "has-flag": { 162 | "version": "3.0.0", 163 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 164 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 165 | "dev": true 166 | }, 167 | "inflight": { 168 | "version": "1.0.6", 169 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 170 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 171 | "dev": true, 172 | "requires": { 173 | "once": "^1.3.0", 174 | "wrappy": "1" 175 | } 176 | }, 177 | "inherits": { 178 | "version": "2.0.4", 179 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 180 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 181 | "dev": true 182 | }, 183 | "js-tokens": { 184 | "version": "4.0.0", 185 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 186 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 187 | "dev": true 188 | }, 189 | "js-yaml": { 190 | "version": "3.13.1", 191 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 192 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 193 | "dev": true, 194 | "requires": { 195 | "argparse": "^1.0.7", 196 | "esprima": "^4.0.0" 197 | } 198 | }, 199 | "minimatch": { 200 | "version": "3.0.4", 201 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 202 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 203 | "dev": true, 204 | "requires": { 205 | "brace-expansion": "^1.1.7" 206 | } 207 | }, 208 | "minimist": { 209 | "version": "1.2.5", 210 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 211 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 212 | "dev": true 213 | }, 214 | "mkdirp": { 215 | "version": "0.5.5", 216 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 217 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 218 | "dev": true, 219 | "requires": { 220 | "minimist": "^1.2.5" 221 | } 222 | }, 223 | "once": { 224 | "version": "1.4.0", 225 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 226 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 227 | "dev": true, 228 | "requires": { 229 | "wrappy": "1" 230 | } 231 | }, 232 | "path-is-absolute": { 233 | "version": "1.0.1", 234 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 235 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 236 | "dev": true 237 | }, 238 | "path-parse": { 239 | "version": "1.0.6", 240 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 241 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 242 | "dev": true 243 | }, 244 | "resolve": { 245 | "version": "1.15.1", 246 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", 247 | "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", 248 | "dev": true, 249 | "requires": { 250 | "path-parse": "^1.0.6" 251 | } 252 | }, 253 | "semver": { 254 | "version": "5.7.1", 255 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 256 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 257 | "dev": true 258 | }, 259 | "sprintf-js": { 260 | "version": "1.0.3", 261 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 262 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 263 | "dev": true 264 | }, 265 | "supports-color": { 266 | "version": "5.5.0", 267 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 268 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 269 | "dev": true, 270 | "requires": { 271 | "has-flag": "^3.0.0" 272 | } 273 | }, 274 | "tslib": { 275 | "version": "1.11.1", 276 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", 277 | "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", 278 | "dev": true 279 | }, 280 | "tslint": { 281 | "version": "5.20.1", 282 | "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", 283 | "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", 284 | "dev": true, 285 | "requires": { 286 | "@babel/code-frame": "^7.0.0", 287 | "builtin-modules": "^1.1.1", 288 | "chalk": "^2.3.0", 289 | "commander": "^2.12.1", 290 | "diff": "^4.0.1", 291 | "glob": "^7.1.1", 292 | "js-yaml": "^3.13.1", 293 | "minimatch": "^3.0.4", 294 | "mkdirp": "^0.5.1", 295 | "resolve": "^1.3.2", 296 | "semver": "^5.3.0", 297 | "tslib": "^1.8.0", 298 | "tsutils": "^2.29.0" 299 | } 300 | }, 301 | "tsutils": { 302 | "version": "2.29.0", 303 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", 304 | "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", 305 | "dev": true, 306 | "requires": { 307 | "tslib": "^1.8.1" 308 | } 309 | }, 310 | "typescript": { 311 | "version": "3.8.3", 312 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", 313 | "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", 314 | "dev": true 315 | }, 316 | "wrappy": { 317 | "version": "1.0.2", 318 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 319 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 320 | "dev": true 321 | } 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "format-code-action", 3 | "private": true, 4 | "displayName": "Format Code Action", 5 | "version": "0.1.0", 6 | "publisher": "rohit-gohri", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/rohit-gohri/vscode-format-code-action" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/rohit-gohri/vscode-format-code-action/issues" 13 | }, 14 | "engines": { 15 | "vscode": "^1.44.0" 16 | }, 17 | "icon": "icon.png", 18 | "categories": [ 19 | "Other", 20 | "Formatters" 21 | ], 22 | "activationEvents": [ 23 | "*" 24 | ], 25 | "main": "./out/extension.js", 26 | "scripts": { 27 | "vscode:prepublish": "npm run compile", 28 | "compile": "tsc -p ./", 29 | "lint": "tslint -p ./", 30 | "watch": "tsc -watch -p ./" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "^12.12.0", 34 | "tslint": "^5.19.0", 35 | "typescript": "^3.8.3", 36 | "@types/vscode": "^1.32.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------- 2 | * Copyright (C) Rohit Gohri (https://rohit.page). All rights reserved. 3 | *--------------------------------------------------------*/ 4 | 5 | import * as vscode from "vscode"; 6 | 7 | const FORMAT_DOCUMENT = "editor.action.formatDocument"; 8 | const FORMAT_MODIFIED = "editor.action.formatChanges"; 9 | 10 | /** 11 | * @deprecated 12 | */ 13 | const DOCUMENT_CODE_ACTION_KIND_LEGACY = vscode.CodeActionKind.SourceFixAll.append( 14 | "format" 15 | ); 16 | 17 | const DOCUMENT_CODE_ACTION_KIND = vscode.CodeActionKind.Source.append( 18 | "formatDocument" 19 | ); 20 | const MODIFIED_CODE_ACTION_KIND = vscode.CodeActionKind.Source.append( 21 | "formatModified" 22 | ); 23 | 24 | export function activate(context: vscode.ExtensionContext) { 25 | context.subscriptions.push( 26 | vscode.languages.registerCodeActionsProvider("*", new FormatActions(), { 27 | providedCodeActionKinds: FormatActions.providedCodeActionKinds, 28 | }) 29 | ); 30 | } 31 | 32 | let cache: vscode.CodeAction[] | undefined; 33 | 34 | /** 35 | * Provides code actions for calling format document and format modified 36 | */ 37 | export class FormatActions implements vscode.CodeActionProvider { 38 | public static readonly providedCodeActionKinds = [ 39 | DOCUMENT_CODE_ACTION_KIND_LEGACY, 40 | DOCUMENT_CODE_ACTION_KIND, 41 | MODIFIED_CODE_ACTION_KIND, 42 | ]; 43 | 44 | public provideCodeActions( 45 | document: vscode.TextDocument, 46 | range: vscode.Range 47 | ): vscode.CodeAction[] | undefined { 48 | if (cache) return cache; 49 | const formatDocumentActionLegacy = this.getFormatDocumentAction( 50 | DOCUMENT_CODE_ACTION_KIND_LEGACY 51 | ); 52 | const formatDocumentAction = this.getFormatDocumentAction(); 53 | const formatModifiedAction = this.getFormatModifiedAction(); 54 | 55 | cache = [ 56 | formatDocumentActionLegacy, 57 | formatDocumentAction, 58 | formatModifiedAction, 59 | ]; 60 | return cache; 61 | } 62 | 63 | private getFormatDocumentAction( 64 | actionKind: vscode.CodeActionKind = DOCUMENT_CODE_ACTION_KIND 65 | ): vscode.CodeAction { 66 | const action = new vscode.CodeAction("Format Document", actionKind); 67 | action.command = { 68 | command: FORMAT_DOCUMENT, 69 | title: "Format Document", 70 | tooltip: "This will format the document with the default formatter.", 71 | }; 72 | return action; 73 | } 74 | 75 | private getFormatModifiedAction(): vscode.CodeAction { 76 | const action = new vscode.CodeAction( 77 | "Format Modified", 78 | MODIFIED_CODE_ACTION_KIND 79 | ); 80 | action.command = { 81 | command: FORMAT_MODIFIED, 82 | title: "Format Modified", 83 | tooltip: 84 | "This will format the document's modified content (requires version control) with the default formatter.", 85 | }; 86 | return action; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "sourceMap": true, 7 | "strict": true, 8 | "rootDir": "src" 9 | }, 10 | "exclude": [ 11 | "node_modules", 12 | ".vscode-test" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, "tabs"], 4 | "semicolon": [true, "always"] 5 | } 6 | } --------------------------------------------------------------------------------