├── .eslintignore ├── .gitignore ├── .travis.yml ├── tests ├── .eslintrc.json ├── src │ ├── utils.js │ └── rules │ │ ├── no-case-curly.js │ │ └── newline-between-switch-case.js └── index.js ├── .eslintrc.json ├── CHANGELOG.md ├── src ├── index.js └── rules │ ├── no-case-curly.js │ └── newline-between-switch-case.js ├── docs └── rules │ ├── no-case-curly.md │ └── newline-between-switch-case.md ├── package.json └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | /lib 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | .idea 4 | /lib 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "18" 5 | -------------------------------------------------------------------------------- /tests/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "rules": {} 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": "2018" 4 | }, 5 | "env": { 6 | "node": true 7 | }, 8 | "rules": {} 9 | } 10 | -------------------------------------------------------------------------------- /tests/src/utils.js: -------------------------------------------------------------------------------- 1 | exports.test = function test(t) { 2 | return { 3 | ...t, 4 | languageOptions: { 5 | sourceType: "module", 6 | ecmaVersion: 2018, 7 | }, 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [1.1.2] - 2016-08-01 6 | - Fix recommended config 7 | 8 | ## [1.1.1] - 2016-07-23 9 | - Remove extraneous files from published package 10 | 11 | ## [1.1.0] - 2016-07-17 12 | - Add autofixing 13 | 14 | ## [1.0.1] - 2016-07-17 15 | - fix typo in readme 16 | 17 | ## [1.0.0] - 2016-07-17 18 | ### Added 19 | - Initial release 20 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const rules = fs 5 | .readdirSync(path.resolve(__dirname, "rules")) 6 | .map((f) => f.replace(/\.js$/, "")) 7 | .reduce((rules, ruleName) => { 8 | return { 9 | ...rules, 10 | [ruleName]: require(`./rules/${ruleName}`), 11 | }; 12 | }, {}); 13 | 14 | module.exports = { 15 | rules: rules, 16 | configs: { 17 | recommended: { 18 | rules: { 19 | "switch-case/newline-between-switch-case": "error", 20 | "switch-case/no-case-curly": "error", 21 | }, 22 | }, 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /tests/index.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | const fs = require("fs"); 3 | const path = require("path"); 4 | const plugin = require("../src/index"); 5 | 6 | const rules = fs 7 | .readdirSync(path.resolve(__dirname, "../src/rules/")) 8 | .map((f) => path.basename(f, ".js")); 9 | 10 | describe("all rule files should be exported by the plugin", () => { 11 | it("should export all rules", () => { 12 | rules.forEach((ruleName) => { 13 | assert.equal( 14 | plugin.rules[ruleName], 15 | // eslint-disable-next-line global-require 16 | require(path.join("../src/rules", ruleName)), 17 | `rule ${ruleName} is not exported` 18 | ); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/rules/no-case-curly.js: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Rule Definition 3 | //------------------------------------------------------------------------------ 4 | 5 | module.exports = { 6 | meta: { 7 | docs: {}, 8 | 9 | schema: [], 10 | }, 11 | 12 | create: function noCaseCurly(context) { 13 | return { 14 | SwitchCase(node) { 15 | if ( 16 | node.consequent.length && 17 | node.consequent[0].type === "BlockStatement" 18 | ) { 19 | context.report( 20 | node, 21 | "Do not use braces in a case - extract the case to a" + 22 | " function if it requires its own variables." 23 | ); 24 | } 25 | }, 26 | }; 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /docs/rules/no-case-curly.md: -------------------------------------------------------------------------------- 1 | # no-case-curly 2 | 3 | Long switch statements containing unrelated code for each case can get messy. One sign that you have unrelated code is if you need curly braces because you are initialising variables. This rule prevents this and recommends pulling out the code to a seperate function. 4 | 5 | ## Rule Details 6 | 7 | The following patterns are considered problems: 8 | 9 | ```js 10 | /*eslint switch-case/no-case-curly: "error"*/ 11 | 12 | switch (a) { 13 | case 1: { 14 | let b = a + c; 15 | let d = g(b); 16 | return h(b, d); 17 | break; 18 | } 19 | } 20 | 21 | ``` 22 | 23 | The following patterns are not considered warnings: 24 | 25 | ```js 26 | /*eslint switch-case: "error"*/ 27 | 28 | switch(a) { 29 | case 1: 30 | return descriptive(a); 31 | } 32 | 33 | ``` 34 | 35 | ## When Not To Use It 36 | 37 | If you need switch statement cases to have their own variables/scope. 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-plugin-switch-case", 3 | "version": "3.0.1", 4 | "author": "Luke Page", 5 | "description": "switch-case specific linting rules for ESLint", 6 | "main": "src/index.js", 7 | "scripts": { 8 | "lint": "eslint ./", 9 | "lint-fix": "eslint --fix ./", 10 | "test": "mocha tests/**/*.js --reporter dot" 11 | }, 12 | "files": [ 13 | "LICENSE", 14 | "README.md", 15 | "src" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/lukeapage/eslint-plugin-switch-case" 20 | }, 21 | "homepage": "https://github.com/lukeapage/eslint-plugin-switch-case", 22 | "bugs": "https://github.com/lukeapage/eslint-plugin-switch-case/issues", 23 | "peerDependencies": { 24 | "eslint": "^9.8.0" 25 | }, 26 | "devDependencies": { 27 | "eslint": "^9.8.0", 28 | "mocha": "^9.2.2" 29 | }, 30 | "engines": { 31 | "node": ">=18.18" 32 | }, 33 | "keywords": [ 34 | "eslint", 35 | "eslint-plugin", 36 | "eslintplugin", 37 | "destructuring" 38 | ], 39 | "license": "MIT" 40 | } 41 | -------------------------------------------------------------------------------- /tests/src/rules/no-case-curly.js: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // Requirements 3 | // ------------------------------------------------------------------------------ 4 | 5 | const { RuleTester } = require("eslint"); 6 | const rule = require("../../../src/rules/no-case-curly"); 7 | const { test } = require("../utils"); 8 | 9 | // ------------------------------------------------------------------------------ 10 | // Tests 11 | // ------------------------------------------------------------------------------ 12 | 13 | const ruleTester = new RuleTester(); 14 | const errors = [ 15 | { 16 | message: 17 | "Do not use braces in a case - extract the case to a" + 18 | " function if it requires its own variables.", 19 | }, 20 | ]; 21 | ruleTester.run("no-case-curly", rule, { 22 | valid: [ 23 | test({ code: "switch(a) { case 1: break; }" }), 24 | test({ code: "switch(a) { case 1: case 2: }" }), 25 | test({ code: "switch(a) { case 1: }" }), 26 | ], 27 | invalid: [ 28 | test({ 29 | code: "switch(a) { case 1: { break; } }", 30 | errors, 31 | }), 32 | test({ 33 | code: "switch(a) { case 1: default: { break; } break; }", 34 | errors, 35 | }), 36 | ], 37 | }); 38 | -------------------------------------------------------------------------------- /docs/rules/newline-between-switch-case.md: -------------------------------------------------------------------------------- 1 | # newline-between-switch-case 2 | 3 | Require newlines between switch cases. 4 | 5 | ## Options 6 | 7 | The rule takes a first option of either "always" or "never" as to whether there should be a newline between cases. It also takes an object with the following options: 8 | 9 | * fallthrough - "always" or "never" - whether or not to have newlines between cases that fallthrough to each other. 10 | 11 | ## Rule Details 12 | 13 | The following patterns are considered problems: 14 | 15 | ```js 16 | /*eslint switch-case/newline-between-switch-case: ["error", "always"]*/ 17 | 18 | switch (a) { 19 | case 0: 20 | case 1: 21 | doSomething(); 22 | break; 23 | case 2: 24 | doSomething(); 25 | break; 26 | } 27 | 28 | ``` 29 | 30 | The following patterns are not considered warnings: 31 | 32 | ```js 33 | /*eslint switch-case: "error"*/ 34 | 35 | /*eslint switch-case/newline-between-switch-case: ["error", "always"]*/ 36 | 37 | switch (a) { 38 | case 0: 39 | 40 | case 1: 41 | doSomething(); 42 | break; 43 | 44 | case 2: 45 | doSomething(); 46 | break; 47 | } 48 | 49 | ``` 50 | 51 | ## fallthrough option 52 | 53 | The following patterns are considered problems: 54 | 55 | ```js 56 | /*eslint switch-case/newline-between-switch-case: ["error", "always", { "fallthrough": "never"}]*/ 57 | 58 | switch (a) { 59 | case 0: 60 | 61 | case 1: 62 | doSomething(); 63 | break; 64 | } 65 | 66 | ``` 67 | 68 | The following patterns are not considered warnings: 69 | 70 | ```js 71 | /*eslint switch-case: "error"*/ 72 | 73 | /*eslint switch-case/newline-between-switch-case: ["error", "always", { "fallthrough": "never"}]*/ 74 | 75 | switch (a) { 76 | case 0: 77 | case 1: 78 | doSomething(); 79 | break; 80 | } 81 | 82 | ``` 83 | 84 | ## When Not To Use It 85 | 86 | If you don't want to enforce newlines between switch cases. 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ESLint-Plugin-Switch-Case 2 | ========================= 3 | 4 | [![Maintenance Status][status-image]][status-url] [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] 5 | 6 | Switch-case-specific linting rules for ESLint. 7 | 8 | # Installation 9 | 10 | Install [ESLint](https://www.github.com/eslint/eslint) either locally or globally. 11 | 12 | $ npm install eslint 13 | 14 | If you installed `ESLint` globally, you have to install the plugin globally too. Otherwise, install it locally. 15 | 16 | $ npm install eslint-plugin-switch-case 17 | 18 | # Configuration 19 | 20 | Add a `plugins` section and specify eslint-plugin-switch-case as a plugin. 21 | 22 | Then, enable all of the rules that you would like to use. 23 | 24 | ## Recommended configuration 25 | This plugin exports a `recommended` configuration that enforces all the rules. You can configure the plugin as follows: 26 | 27 | ```json 28 | { 29 | "plugins": ["switch-case"], 30 | "extends": ["plugin:switch-case/recommended"] 31 | } 32 | ``` 33 | # List of provided rules 34 | Rules are divided into categories for your convenience. All rules are off by default, unless you use one of the plugin's configurations which turn all relevant rules on. 35 | 36 | ### Stylistic Issues 37 | These rules are purely matters of style and are quite subjective. 38 | * [no-case-curly](docs/rules/no-case-curly.md): Forbid curly brackets around case statements. 39 | * [newline-between-switch-case](docs/rules/newline-between-switch-case.md): Configure newlines around switch cases. 40 | 41 | # Contributing 42 | Contributions are always welcome!. 43 | 44 | # License 45 | 46 | eslint-plugin-switch-case is licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php). 47 | 48 | [npm-url]: https://npmjs.org/package/eslint-plugin-switch-case 49 | [npm-image]: http://img.shields.io/npm/v/eslint-plugin-switch-case.svg?style=flat-square 50 | 51 | [travis-url]: https://travis-ci.org/lukeapage/eslint-plugin-switch-case 52 | [travis-image]: http://img.shields.io/travis/lukeapage/eslint-plugin-switch-case/master.svg?style=flat-square 53 | 54 | [deps-url]: https://david-dm.org/lukeapage/eslint-plugin-switch-case 55 | [deps-image]: https://img.shields.io/david/dev/lukeapage/eslint-plugin-switch-case.svg?style=flat-square 56 | 57 | [status-url]: https://github.com/lukeapage/eslint-plugin-switch-case/pulse 58 | [status-image]: http://img.shields.io/badge/status-maintained-brightgreen.svg?style=flat-square 59 | -------------------------------------------------------------------------------- /src/rules/newline-between-switch-case.js: -------------------------------------------------------------------------------- 1 | function last(array) { 2 | return array[array.length - 1]; 3 | } 4 | 5 | //------------------------------------------------------------------------------ 6 | // Rule Definition 7 | //------------------------------------------------------------------------------ 8 | 9 | /** 10 | * Checks whether or not a given code path segment is reachable. 11 | * @param {CodePathSegment} segment - A CodePathSegment to check. 12 | * @returns {boolean} `true` if the segment is reachable. 13 | */ 14 | function isReachable(segment) { 15 | return segment.reachable; 16 | } 17 | 18 | /** 19 | * Checks if there is a blank line between tokens 20 | */ 21 | function getTokensWithNewlineBetween(sourceCode, startNode, endNode) { 22 | const endLine = endNode.loc.start.line; 23 | 24 | let next = startNode; 25 | let previous = startNode; 26 | do { 27 | previous = next; 28 | next = sourceCode.getTokenOrCommentAfter(next); 29 | 30 | if (next.loc.start.line > previous.loc.end.line + 1) { 31 | return [previous, next]; 32 | } 33 | } while (next.loc.start.line < endLine); 34 | 35 | return null; 36 | } 37 | 38 | module.exports = { 39 | meta: { 40 | docs: {}, 41 | 42 | fixable: "whitespace", 43 | 44 | schema: [ 45 | { 46 | enum: ["always", "never"], 47 | }, 48 | { 49 | type: "object", 50 | properties: { 51 | fallthrough: { 52 | enum: ["always", "never"], 53 | }, 54 | }, 55 | additionalProperties: false, 56 | }, 57 | ], 58 | }, 59 | 60 | create: function newlineBetweenSwitchCase(context) { 61 | const sourceCode = context.sourceCode ?? context.getSourceCode(); 62 | const optionIsNewlineBetweenSwitchCases = context.options[0] === "always"; 63 | 64 | const optionIsNewlineBetweenFallthrough = 65 | context.options[1] && context.options[1].fallthrough 66 | ? context.options[1].fallthrough === "always" 67 | : optionIsNewlineBetweenSwitchCases; 68 | 69 | let currentCodePath = null; 70 | // tracks the segments we've traversed in the current code path 71 | let currentSegments; 72 | 73 | // tracks all current segments for all open paths 74 | const allCurrentSegments = []; 75 | 76 | return { 77 | onCodePathStart(codePath) { 78 | currentCodePath = codePath; 79 | allCurrentSegments.push(currentSegments); 80 | currentSegments = new Set(); 81 | }, 82 | 83 | onCodePathEnd() { 84 | currentCodePath = currentCodePath.upper; 85 | currentSegments = allCurrentSegments.pop(); 86 | }, 87 | 88 | onCodePathSegmentStart(segment) { 89 | currentSegments.add(segment); 90 | }, 91 | 92 | onCodePathSegmentEnd(segment) { 93 | currentSegments.delete(segment); 94 | }, 95 | 96 | onUnreachableCodePathSegmentStart(segment) { 97 | currentSegments.add(segment); 98 | }, 99 | 100 | onUnreachableCodePathSegmentEnd(segment) { 101 | currentSegments.delete(segment); 102 | }, 103 | 104 | "SwitchCase:exit": (node) => { 105 | // ignore the last switch case 106 | if (last(node.parent.cases) === node) { 107 | return; 108 | } 109 | 110 | let isFallthrough = false; 111 | 112 | /* 113 | * A fallthrough is either if we are empty or if the end of the case is reachable 114 | */ 115 | if ( 116 | node.consequent.length === 0 || 117 | [...currentSegments].some(isReachable) 118 | ) { 119 | isFallthrough = true; 120 | } 121 | 122 | const nextToken = sourceCode.getTokenAfter(node); 123 | 124 | const tokensWithBlankLinesBetween = getTokensWithNewlineBetween( 125 | sourceCode, 126 | node, 127 | nextToken 128 | ); 129 | const hasBlankLinesBetween = Boolean(tokensWithBlankLinesBetween); 130 | const isNewlineRequired = isFallthrough 131 | ? optionIsNewlineBetweenFallthrough 132 | : optionIsNewlineBetweenSwitchCases; 133 | 134 | if (hasBlankLinesBetween && !isNewlineRequired) { 135 | context.report({ 136 | node, 137 | fix(fixer) { 138 | const [previous, next] = tokensWithBlankLinesBetween; 139 | return fixer.replaceTextRange( 140 | [previous.range[1], next.range[0] - next.loc.start.column], 141 | "\n" 142 | ); 143 | }, 144 | message: "Extraneous newlines between switch cases.", 145 | }); 146 | } else if (!hasBlankLinesBetween && isNewlineRequired) { 147 | context.report({ 148 | node, 149 | fix(fixer) { 150 | return fixer.insertTextAfter(node, "\n"); 151 | }, 152 | message: "Newline required between switch cases.", 153 | }); 154 | } 155 | }, 156 | }; 157 | }, 158 | }; 159 | -------------------------------------------------------------------------------- /tests/src/rules/newline-between-switch-case.js: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // Requirements 3 | // ------------------------------------------------------------------------------ 4 | 5 | const { RuleTester } = require("eslint"); 6 | const rule = require("../../../src/rules/newline-between-switch-case"); 7 | const { test } = require("../utils"); 8 | 9 | // ------------------------------------------------------------------------------ 10 | // Tests 11 | // ------------------------------------------------------------------------------ 12 | 13 | const ruleTester = new RuleTester(); 14 | const errorsExtraneous = [ 15 | { message: "Extraneous newlines between switch cases." }, 16 | ]; 17 | const errorsMissing = [{ message: "Newline required between switch cases." }]; 18 | ruleTester.run("newline-between-switch-case", rule, { 19 | valid: [ 20 | test({ 21 | code: ` 22 | switch(a) { 23 | case 1:break; 24 | } 25 | `, 26 | options: ["always", { fallthrough: "always" }], 27 | }), 28 | test({ 29 | code: ` 30 | switch(a) { 31 | case 2: 32 | 33 | case 1:break; 34 | } 35 | `, 36 | options: ["always", { fallthrough: "always" }], 37 | }), 38 | test({ 39 | code: ` 40 | switch(a) { 41 | case 2:break; 42 | 43 | case 1:break; 44 | } 45 | `, 46 | options: ["always", { fallthrough: "always" }], 47 | }), 48 | test({ 49 | code: ` 50 | switch(a) { 51 | case 2:break; 52 | 53 | // comment 54 | case 1:break; 55 | } 56 | `, 57 | options: ["always", { fallthrough: "always" }], 58 | }), 59 | test({ 60 | code: ` 61 | switch(a) { 62 | case 2:break; 63 | // comment 64 | 65 | case 1:break; 66 | } 67 | `, 68 | options: ["always", { fallthrough: "always" }], 69 | }), 70 | test({ 71 | code: ` 72 | switch(a) { 73 | case 1:break; 74 | } 75 | `, 76 | options: ["never", { fallthrough: "never" }], 77 | }), 78 | test({ 79 | code: ` 80 | switch(a) { 81 | case 2: 82 | case 1:break; 83 | } 84 | `, 85 | options: ["never", { fallthrough: "never" }], 86 | }), 87 | test({ 88 | code: ` 89 | switch(a) { 90 | case 2:break; 91 | case 1:break; 92 | } 93 | `, 94 | options: ["never", { fallthrough: "never" }], 95 | }), 96 | test({ 97 | code: ` 98 | switch(a) { 99 | case 2:break; 100 | // comment 101 | case 1:break; 102 | } 103 | `, 104 | options: ["never", { fallthrough: "never" }], 105 | }), 106 | test({ 107 | code: ` 108 | switch(a) { 109 | case 2: 110 | case 1:break; 111 | 112 | case 3: 113 | } 114 | `, 115 | options: ["always", { fallthrough: "never" }], 116 | }), 117 | test({ 118 | code: ` 119 | switch(a) { 120 | case 2: 121 | f(); 122 | case 1:break; 123 | 124 | case 3: 125 | } 126 | `, 127 | options: ["always", { fallthrough: "never" }], 128 | }), 129 | test({ 130 | code: ` 131 | switch(a) { 132 | case 2: { 133 | f(); 134 | } 135 | case 1:break; 136 | 137 | case 3: 138 | } 139 | `, 140 | options: ["always", { fallthrough: "never" }], 141 | }), 142 | test({ 143 | code: ` 144 | switch(a) { 145 | case 2: { 146 | f(); 147 | break; 148 | } 149 | 150 | case 1:break; 151 | 152 | case 3: 153 | } 154 | `, 155 | options: ["always", { fallthrough: "never" }], 156 | }), 157 | test({ 158 | code: `var f = () => { 159 | switch(a) { 160 | case 2: { 161 | const b = true; 162 | if (a) { 163 | return a; 164 | } else { 165 | return b; 166 | } 167 | } 168 | 169 | case 1:break; 170 | 171 | case 3: 172 | }}; 173 | `, 174 | options: ["always", { fallthrough: "never" }], 175 | }), 176 | ], 177 | invalid: [ 178 | test({ 179 | code: ` 180 | switch(a) { 181 | case 2: 182 | case 1:break; 183 | } 184 | `, 185 | output: ` 186 | switch(a) { 187 | case 2: 188 | 189 | case 1:break; 190 | } 191 | `, 192 | options: ["always", { fallthrough: "always" }], 193 | errors: errorsMissing, 194 | }), 195 | test({ 196 | code: ` 197 | switch(a) { 198 | case 2:break; 199 | case 1:break; 200 | } 201 | `, 202 | output: ` 203 | switch(a) { 204 | case 2:break; 205 | 206 | case 1:break; 207 | } 208 | `, 209 | options: ["always", { fallthrough: "always" }], 210 | errors: errorsMissing, 211 | }), 212 | test({ 213 | code: ` 214 | switch(a) { 215 | case 2:break; 216 | // comment 217 | case 1:break; 218 | } 219 | `, 220 | output: ` 221 | switch(a) { 222 | case 2:break; 223 | 224 | // comment 225 | case 1:break; 226 | } 227 | `, 228 | options: ["always", { fallthrough: "always" }], 229 | errors: errorsMissing, 230 | }), 231 | test({ 232 | code: ` 233 | switch(a) { 234 | case 2: 235 | // comment 236 | case 1:break; 237 | } 238 | `, 239 | output: ` 240 | switch(a) { 241 | case 2: 242 | 243 | // comment 244 | case 1:break; 245 | } 246 | `, 247 | options: ["always", { fallthrough: "always" }], 248 | errors: errorsMissing, 249 | }), 250 | test({ 251 | code: ` 252 | switch(a) { 253 | case 2: 254 | 255 | case 1:break; 256 | } 257 | `, 258 | output: ` 259 | switch(a) { 260 | case 2: 261 | case 1:break; 262 | } 263 | `, 264 | options: ["never", { fallthrough: "never" }], 265 | errors: errorsExtraneous, 266 | }), 267 | test({ 268 | code: ` 269 | switch(a) { 270 | case 2:break; 271 | 272 | case 1:break; 273 | } 274 | `, 275 | output: ` 276 | switch(a) { 277 | case 2:break; 278 | case 1:break; 279 | } 280 | `, 281 | options: ["never", { fallthrough: "never" }], 282 | errors: errorsExtraneous, 283 | }), 284 | test({ 285 | code: ` 286 | switch(a) { 287 | case 2:break; 288 | 289 | // comment 290 | case 1:break; 291 | } 292 | `, 293 | output: ` 294 | switch(a) { 295 | case 2:break; 296 | // comment 297 | case 1:break; 298 | } 299 | `, 300 | options: ["never", { fallthrough: "never" }], 301 | errors: errorsExtraneous, 302 | }), 303 | test({ 304 | code: ` 305 | switch(a) { 306 | case 2:break; 307 | // comment 308 | 309 | case 1:break; 310 | } 311 | `, 312 | output: ` 313 | switch(a) { 314 | case 2:break; 315 | // comment 316 | case 1:break; 317 | } 318 | `, 319 | options: ["never", { fallthrough: "never" }], 320 | errors: errorsExtraneous, 321 | }), 322 | test({ 323 | code: ` 324 | switch(a) { 325 | case 2: 326 | case 1:break; 327 | case 3: 328 | } 329 | `, 330 | output: ` 331 | switch(a) { 332 | case 2: 333 | case 1:break; 334 | 335 | case 3: 336 | } 337 | `, 338 | options: ["always", { fallthrough: "never" }], 339 | errors: errorsMissing, 340 | }), 341 | test({ 342 | code: ` 343 | switch(a) { 344 | case 2: 345 | f(); 346 | 347 | case 1:break; 348 | 349 | case 3: 350 | } 351 | `, 352 | output: ` 353 | switch(a) { 354 | case 2: 355 | f(); 356 | case 1:break; 357 | 358 | case 3: 359 | } 360 | `, 361 | options: ["always", { fallthrough: "never" }], 362 | errors: errorsExtraneous, 363 | }), 364 | test({ 365 | code: ` 366 | switch(a) { 367 | case 2: { 368 | f(); 369 | } 370 | 371 | case 1:break; 372 | 373 | case 3: 374 | } 375 | `, 376 | output: ` 377 | switch(a) { 378 | case 2: { 379 | f(); 380 | } 381 | case 1:break; 382 | 383 | case 3: 384 | } 385 | `, 386 | options: ["always", { fallthrough: "never" }], 387 | errors: errorsExtraneous, 388 | }), 389 | ], 390 | }); 391 | --------------------------------------------------------------------------------