diff --git a/demo/example.js b/demo/example.js index d06ea6b..b273698 100644 --- a/demo/example.js +++ b/demo/example.js @@ -87,6 +87,7 @@ switch (1) { case 1: break case 2: + case 3: switch (2) { case 1: duplicateFunction() @@ -116,6 +117,16 @@ switch (1) { break case 11: break + case 12: + break + case 13: + break + case 14: + break + case 15: + break + case 16: + break default: break } diff --git a/demo/test/snapshots/linting-config.test.js.md b/demo/test/snapshots/linting-config.test.js.md index d441bed..7e8e442 100644 --- a/demo/test/snapshots/linting-config.test.js.md +++ b/demo/test/snapshots/linting-config.test.js.md @@ -136,7 +136,8 @@ Generated by [AVA](https://ava.li). "error",␊ {␊ "allowImplicit": true,␊ - "checkForEach": false␊ + "checkForEach": false,␊ + "allowVoid": false␊ }␊ ],␊ "array-element-newline": [␊ @@ -614,7 +615,7 @@ Generated by [AVA](https://ava.li). }␊ ],␊ "import/prefer-default-export": [␊ - "error"␊ + "off"␊ ],␊ "import/unambiguous": [␊ "off"␊ @@ -2693,11 +2694,14 @@ Generated by [AVA](https://ava.li). ],␊ "sonarjs/cognitive-complexity": [␊ "warn",␊ - 25␊ + 30␊ + ],␊ + "sonarjs/elseif-without-else": [␊ + "off"␊ ],␊ "sonarjs/max-switch-cases": [␊ "warn",␊ - 10␊ + 15␊ ],␊ "sonarjs/no-all-duplicated-branches": [␊ "warn"␊ @@ -2705,9 +2709,16 @@ Generated by [AVA](https://ava.li). "sonarjs/no-collapsible-if": [␊ "warn"␊ ],␊ - "sonarjs/no-duplicate-string": [␊ + "sonarjs/no-collection-size-mischeck": [␊ "warn"␊ ],␊ + "sonarjs/no-duplicate-string": [␊ + "warn",␊ + {␊ + "threshold": 4,␊ + "ignoreStrings": "application/json"␊ + }␊ + ],␊ "sonarjs/no-duplicated-branches": [␊ "warn"␊ ],␊ @@ -2730,13 +2741,20 @@ Generated by [AVA](https://ava.li). "warn"␊ ],␊ "sonarjs/no-identical-functions": [␊ + "warn",␊ + 4␊ + ],␊ + "sonarjs/no-ignored-return": [␊ + "warn"␊ + ],␊ + "sonarjs/no-inverted-boolean-check": [␊ "warn"␊ ],␊ "sonarjs/no-nested-switch": [␊ "warn"␊ ],␊ "sonarjs/no-nested-template-literals": [␊ - "warn"␊ + "off"␊ ],␊ "sonarjs/no-one-iteration-loop": [␊ "warn"␊ @@ -2766,13 +2784,13 @@ Generated by [AVA](https://ava.li). "warn"␊ ],␊ "sonarjs/prefer-immediate-return": [␊ - "warn"␊ + "off"␊ ],␊ "sonarjs/prefer-object-literal": [␊ "warn"␊ ],␊ "sonarjs/prefer-single-boolean-return": [␊ - "warn"␊ + "off"␊ ],␊ "sonarjs/prefer-while": [␊ "warn"␊ @@ -2982,7 +3000,7 @@ Generated by [AVA](https://ava.li). }␊ ],␊ "unicode-bom": [␊ - "off",␊ + "error",␊ "never"␊ ],␊ "unicorn/empty-brace-spaces": [␊ @@ -2994,6 +3012,9 @@ Generated by [AVA](https://ava.li). "unicorn/number-literal-case": [␊ "off"␊ ],␊ + "unicorn/template-indent": [␊ + 0␊ + ],␊ "use-isnan": [␊ "error"␊ ],␊ @@ -3155,6 +3176,9 @@ Generated by [AVA](https://ava.li). "you-dont-need-lodash-underscore/bind": [␊ 2␊ ],␊ + "you-dont-need-lodash-underscore/capitalize": [␊ + 2␊ + ],␊ "you-dont-need-lodash-underscore/cast-array": [␊ 2␊ ],␊ @@ -3173,6 +3197,9 @@ Generated by [AVA](https://ava.li). "you-dont-need-lodash-underscore/debounce": [␊ "off"␊ ],␊ + "you-dont-need-lodash-underscore/defaults": [␊ + 2␊ + ],␊ "you-dont-need-lodash-underscore/detect": [␊ 2␊ ],␊ @@ -3239,6 +3266,9 @@ Generated by [AVA](https://ava.li). "you-dont-need-lodash-underscore/groupBy": [␊ "off"␊ ],␊ + "you-dont-need-lodash-underscore/head": [␊ + 2␊ + ],␊ "you-dont-need-lodash-underscore/includes": [␊ 1␊ ],␊ @@ -3254,6 +3284,12 @@ Generated by [AVA](https://ava.li). "you-dont-need-lodash-underscore/is-array": [␊ 2␊ ],␊ + "you-dont-need-lodash-underscore/is-array-buffer": [␊ + 1␊ + ],␊ + "you-dont-need-lodash-underscore/is-date": [␊ + 2␊ + ],␊ "you-dont-need-lodash-underscore/is-finite": [␊ 2␊ ],␊ @@ -3368,6 +3404,9 @@ Generated by [AVA](https://ava.li). "you-dont-need-lodash-underscore/trim": [␊ 2␊ ],␊ + "you-dont-need-lodash-underscore/union-by": [␊ + 1␊ + ],␊ "you-dont-need-lodash-underscore/uniq": [␊ 2␊ ],␊ @@ -3381,6 +3420,8 @@ Generated by [AVA](https://ava.li). },␊ "import/extensions": [␊ ".ts",␊ + ".cts",␊ + ".mts",␊ ".tsx",␊ ".js",␊ ".jsx"␊ @@ -3392,6 +3433,8 @@ Generated by [AVA](https://ava.li). "import/parsers": {␊ "@typescript-eslint/parser": [␊ ".ts",␊ + ".cts",␊ + ".mts",␊ ".tsx"␊ ]␊ },␊ @@ -3399,6 +3442,8 @@ Generated by [AVA](https://ava.li). "node": {␊ "extensions": [␊ ".ts",␊ + ".cts",␊ + ".mts",␊ ".tsx",␊ ".js",␊ ".jsx"␊ @@ -3429,58 +3474,61 @@ Generated by [AVA](https://ava.li). `␊ example.js␊ - 8:0 error Found eslint-disable without " -- comment" bestpractices/no-eslint-disable␊ - 10:1 warning Unexpected 'FIXME' comment: 'fixMe: Actually make this work' no-warning-comments␊ - 11:1 warning Unexpected 'TODO' comment: 'todo: Add documentation' no-warning-comments␊ - 12:1 warning Unexpected 'HACK' comment: 'Hack: Note that these work, regardless...' no-warning-comments␊ - 19:10 error 'functionWithoutJSDocWarningsBecauseTheSectionWasCompletelyExcluded' is defined but never used no-unused-vars␊ - 24:1 warning Remove the @description tag to leave a plain block description or add additional description text above the @description line jsdoc/require-description␊ - 24:1 warning JSDoc @returns declaration present but return expression not available in function jsdoc/require-returns-check␊ - 24:1 warning JSDoc type missing brace valid-jsdoc␊ - 26:1 warning Expected @param names to be "params". Got "a, params, b" jsdoc/check-param-names␊ - 26:1 warning Missing JSDoc @param "a" description jsdoc/require-param-description␊ - 27:1 warning Missing JSDoc @param "params" description jsdoc/require-param-description␊ - 27:1 warning Missing JSDoc @param "params" type jsdoc/require-param-type␊ - 28:1 warning Missing JSDoc @param "b" description jsdoc/require-param-description␊ - 28:1 warning Missing JSDoc @param "b" type jsdoc/require-param-type␊ - 29:1 warning Missing JSDoc @returns description jsdoc/require-returns-description␊ - 29:1 warning Missing JSDoc @returns type jsdoc/require-returns-type␊ - 31:71 error 'params' is defined but never used no-unused-vars␊ - 36:1 warning Invalid JSDoc tag name "note" jsdoc/check-tag-names␊ - 38:1 warning Expected catch() or return promise/catch-or-return␊ - 38:17 error 'a' is defined but never used no-unused-vars␊ - 38:20 error Expected to return a value at the end of arrow function consistent-return␊ - 39:3 warning Each then() should return a value or throw promise/always-return␊ - 39:7 warning Unexpected constant condition no-constant-condition␊ - 40:5 warning Avoid wrapping return values in Promise.resolve promise/no-return-wrap␊ - 41:10 error Unnecessary 'else' after 'return' no-else-return␊ - 42:5 error 'forgotToDefine' is not defined no-undef␊ - 46:7 error 'variable' is assigned a value but never used no-unused-vars␊ - 46:18 warning This conditional operation returns the same value whether the condition is "true" or "false" sonarjs/no-all-duplicated-branches␊ - 46:18 error Unnecessary use of boolean literals in conditional expression no-unneeded-ternary␊ - 46:18 warning Unexpected constant condition no-constant-condition␊ - 48:1 error Prefer default export on a file with single export import/prefer-default-export␊ - 49:7 warning Correct one of the identical sub-expressions on both sides of operator "&&" sonarjs/no-identical-expressions␊ - 49:55 error 'params' is not defined no-undef␊ - 50:5 warning This function expects 1 argument, but 2 were provided sonarjs/no-extra-arguments␊ - 51:30 error Module path/to/legacyModule is deprecated. Use module x instead deprecate/import␊ - 51:30 error Unexpected require() global-require␊ - 51:38 error Unable to resolve path to module 'path/to/legacyModule' import/no-unresolved␊ - 53:5 error Function deprecatedFunction is deprecated. Use function x from package y instead deprecate/function␊ - 53:5 error 'deprecatedFunction' is not defined no-undef␊ - 55:5 error Member expression $.each is deprecated. Use native forEach instead deprecate/member-expression␊ - 55:5 error '$' is not defined no-undef␊ - 57:5 error Unexpected 'debugger' statement no-debugger␊ - 57:5 error Unreachable code no-unreachable␊ - 71:10 warning Update this function so that its implementation is not identical to the one on line 63 sonarjs/no-identical-functions␊ - 79:1 warning Remove this conditional structure or edit its code blocks so that they're not all the same sonarjs/no-all-duplicated-branches␊ - 79:5 warning This always evaluates to truthy. Consider refactoring this code sonarjs/no-gratuitous-expressions␊ - 79:5 warning Unexpected constant condition no-constant-condition␊ - 86:1 warning Reduce the number of non-empty switch cases from 11 to at most 10 sonarjs/max-switch-cases␊ - 90:5 error Expected a default case default-case␊ - 90:5 warning Refactor the code to eliminate this nested "switch" sonarjs/no-nested-switch␊ - 95:7 error This case's code block is the same as the block for the case on line 91 sonarjs/no-duplicated-branches␊ - 95:7 error Duplicate case label no-duplicate-case␊ + 8:0 error Found eslint-disable without " -- comment" bestpractices/no-eslint-disable␊ + 10:1 warning Unexpected 'FIXME' comment: 'fixMe: Actually make this work' no-warning-comments␊ + 11:1 warning Unexpected 'TODO' comment: 'todo: Add documentation' no-warning-comments␊ + 12:1 warning Unexpected 'HACK' comment: 'Hack: Note that these work, regardless...' no-warning-comments␊ + 19:10 error 'functionWithoutJSDocWarningsBecauseTheSectionWasCompletelyExcluded' is defined but never used no-unused-vars␊ + 24:1 warning Remove the @description tag to leave a plain block description or add additional description text above the @description line jsdoc/require-description␊ + 24:1 warning JSDoc @returns declaration present but return expression not available in function jsdoc/require-returns-check␊ + 24:1 warning JSDoc type missing brace valid-jsdoc␊ + 25:1 warning JSDoc description does not satisfy the regex pattern jsdoc/match-description␊ + 26:1 warning Expected @param names to be "params". Got "a, params, b" jsdoc/check-param-names␊ + 26:1 warning Missing JSDoc @param "a" description jsdoc/require-param-description␊ + 27:1 warning Missing JSDoc @param "params" description jsdoc/require-param-description␊ + 27:1 warning Missing JSDoc @param "params" type jsdoc/require-param-type␊ + 28:1 warning Missing JSDoc @param "b" description jsdoc/require-param-description␊ + 28:1 warning Missing JSDoc @param "b" type jsdoc/require-param-type␊ + 29:1 warning Missing JSDoc @returns description jsdoc/require-returns-description␊ + 29:1 warning Missing JSDoc @returns type jsdoc/require-returns-type␊ + 31:71 error 'params' is defined but never used no-unused-vars␊ + 36:1 warning Invalid JSDoc tag name "note" jsdoc/check-tag-names␊ + 38:1 warning Expected catch() or return promise/catch-or-return␊ + 38:17 error 'a' is defined but never used no-unused-vars␊ + 38:20 error Expected to return a value at the end of arrow function consistent-return␊ + 39:3 warning Each then() should return a value or throw promise/always-return␊ + 39:7 warning Unexpected constant condition no-constant-condition␊ + 40:5 warning Avoid wrapping return values in Promise.resolve promise/no-return-wrap␊ + 41:10 error Unnecessary 'else' after 'return' no-else-return␊ + 42:5 error 'forgotToDefine' is not defined no-undef␊ + 46:7 error 'variable' is assigned a value but never used no-unused-vars␊ + 46:18 warning This conditional operation returns the same value whether the condition is "true" or "false" sonarjs/no-all-duplicated-branches␊ + 46:18 error Unnecessary use of boolean literals in conditional expression no-unneeded-ternary␊ + 46:18 warning Unexpected constant condition no-constant-condition␊ + 49:7 warning Correct one of the identical sub-expressions on both sides of operator "&&" sonarjs/no-identical-expressions␊ + 49:55 error 'params' is not defined no-undef␊ + 50:5 warning This function expects 1 argument, but 2 were provided sonarjs/no-extra-arguments␊ + 51:30 error Module path/to/legacyModule is deprecated. Use module x instead deprecate/import␊ + 51:30 error Unexpected require() global-require␊ + 51:38 error Unable to resolve path to module 'path/to/legacyModule' import/no-unresolved␊ + 53:5 error Function deprecatedFunction is deprecated. Use function x from package y instead deprecate/function␊ + 53:5 error 'deprecatedFunction' is not defined no-undef␊ + 55:5 error Member expression $.each is deprecated. Use native forEach instead deprecate/member-expression␊ + 55:5 error '$' is not defined no-undef␊ + 57:5 error Unexpected 'debugger' statement no-debugger␊ + 57:5 error Unreachable code no-unreachable␊ + 71:10 warning Update this function so that its implementation is not identical to the one on line 63 sonarjs/no-identical-functions␊ + 79:1 warning Remove this conditional structure or edit its code blocks so that they're not all the same sonarjs/no-all-duplicated-branches␊ + 79:5 warning This always evaluates to truthy. Consider refactoring this code sonarjs/no-gratuitous-expressions␊ + 79:5 warning Unexpected constant condition no-constant-condition␊ + 86:1 warning Reduce the number of non-empty switch cases from 16 to at most 15 sonarjs/max-switch-cases␊ + 91:5 error Expected a default case default-case␊ + 91:5 warning Refactor the code to eliminate this nested "switch" sonarjs/no-nested-switch␊ + 96:7 error This case's code block is the same as the block for the case on line 92 sonarjs/no-duplicated-branches␊ + 96:7 error Duplicate case label no-duplicate-case␊ + 96:12 warning This case duplicates the one on line 92 sonarjs/no-identical-conditions␊ + 102:3 error Duplicate case label no-duplicate-case␊ + 102:8 warning This case duplicates the one on line 90 sonarjs/no-identical-conditions␊ ␊ example.json␊ 4:6 error Property keys must be doublequoted json/*␊ @@ -3503,6 +3551,6 @@ Generated by [AVA](https://ava.li). 10:5 warning Test has no assertions jest/expect-expect␊ 10:13 error Test title is used multiple times in the same describe block jest/no-identical-title␊ ␊ - ✖ 69 problems (37 errors, 32 warnings)␊ + ✖ 72 problems (37 errors, 35 warnings)␊ 4 errors and 0 warnings potentially fixable with the `--fix` option.␊ ` diff --git a/demo/test/snapshots/linting-config.test.js.snap b/demo/test/snapshots/linting-config.test.js.snap index a1657e9..ea5665d 100644 Binary files a/demo/test/snapshots/linting-config.test.js.snap and b/demo/test/snapshots/linting-config.test.js.snap differ diff --git a/es6.js b/es6.js index c83b2b1..ea82539 100644 --- a/es6.js +++ b/es6.js @@ -40,38 +40,40 @@ module.exports = { 'promise/no-return-in-finally': 'warn', 'promise/valid-params': 'warn', - 'sonarjs/cognitive-complexity': ['warn', 25], - // sonarjs/elseif-without-else - 'sonarjs/max-switch-cases': ['warn', 10], - 'sonarjs/no-all-duplicated-branches': 'warn', - 'sonarjs/no-collapsible-if': 'warn', - // sonarjs/no-collection-size-mischeck - 'sonarjs/no-duplicate-string': 'warn', - 'sonarjs/no-duplicated-branches': 'warn', - 'sonarjs/no-element-overwrite': 'warn', - 'sonarjs/no-empty-collection': 'warn', - 'sonarjs/no-extra-arguments': 'warn', - 'sonarjs/no-gratuitous-expressions': 'warn', - 'sonarjs/no-identical-conditions': 'warn', - 'sonarjs/no-identical-expressions': 'warn', - 'sonarjs/no-identical-functions': 'warn', - // sonarjs/no-ignored-return - // sonarjs/no-inverted-boolean-check - 'sonarjs/no-nested-switch': 'warn', - 'sonarjs/no-nested-template-literals': 'warn', - 'sonarjs/no-one-iteration-loop': 'warn', - 'sonarjs/no-redundant-boolean': 'warn', - 'sonarjs/no-redundant-jump': 'warn', - 'sonarjs/no-same-line-conditional': 'warn', - 'sonarjs/no-small-switch': 'warn', - 'sonarjs/no-unused-collection': 'warn', - 'sonarjs/no-use-of-empty-return-value': 'warn', - 'sonarjs/no-useless-catch': 'warn', - 'sonarjs/non-existent-operator': 'warn', - 'sonarjs/prefer-immediate-return': 'warn', - 'sonarjs/prefer-object-literal': 'warn', - 'sonarjs/prefer-single-boolean-return': 'warn', - 'sonarjs/prefer-while': 'warn', + 'sonarjs/cognitive-complexity': ['warn', 30], // If your component or service gets beyond this point, you should consider scoping functionality differently. + 'sonarjs/max-switch-cases': ['warn', 15], // Yes, reducers are complicated, but if you have this many states, you may need to rethink your architecture. And anything else should generally be much simpler than this. + 'sonarjs/no-all-duplicated-branches': 'warn', // This is both inefficient and confusing. (ERROR in zion) + 'sonarjs/no-collapsible-if': 'warn', // This is still readable, so not high priority. + 'sonarjs/no-collection-size-mischeck': 'warn', // fixable // Unnecessary evaluation. (ERROR in zion) + 'sonarjs/no-duplicate-string': ['warn', { threshold: 4 }], // Maintainability. The more individual instances you have of a string literal, the more likely you miss/misspell one when refactoring. + 'sonarjs/no-duplicated-branches': 'warn', // This is both inefficient and confusing. NOTE: sonarjs's current implementation incorrectly flags single line duplications, sometimes. + 'sonarjs/no-element-overwrite': 'warn', // Unconditional overwrites are usually in error. (ERROR in zion) + 'sonarjs/no-empty-collection': 'warn', // You're not doing what you think you're doing. (ERROR in zion) + 'sonarjs/no-extra-arguments': 'warn', // This mismatch implies lost data somewhere. (ERROR in zion) + 'sonarjs/no-gratuitous-expressions': 'warn', // Unnecessary evaluations, often from later logic revisions. + 'sonarjs/no-identical-conditions': 'warn', // Unreachable code. (ERROR in zion) + 'sonarjs/no-identical-expressions': 'warn', // Unnecessary evaluations, often from copy+paste. (ERROR in zion) + 'sonarjs/no-identical-functions': ['warn', 4], // Inefficient and confusing. (ERROR in zion) + 'sonarjs/no-ignored-return': 'warn', // Inefficient. If you don't use a function's result, don't call it. + 'sonarjs/no-inverted-boolean-check': 'warn', // Complexity. Extra unnecessary cognitive overhead. Usually a result of logic reduction refactors. + 'sonarjs/no-nested-switch': 'warn', // There are a few limited cases where this pattern is preferable to the alternative, but it's mostly a bad idea. + 'sonarjs/no-one-iteration-loop': 'warn', // Complexity. Single loops are unnecessary complications of synchronous code execution. (ERROR in zion) + 'sonarjs/no-redundant-boolean': 'warn', // Readability. + 'sonarjs/no-redundant-jump': 'warn', // fixable // Redundant. We don't need to tell the flow what it would do anyway. (ERROR in zion) + 'sonarjs/no-same-line-conditional': 'warn', // fixable // Readability. Usually a result of an else-y path being removed/modified. (ERROR in zion) + 'sonarjs/no-small-switch': 'warn', // If your logic is not more than an if-else-if-else, it is usually more readable as such. + 'sonarjs/no-unused-collection': 'warn', // Inefficient. If you set up a collection, you should also use it. + 'sonarjs/no-use-of-empty-return-value': 'warn', // Fragility. You are not getting anything to use, so don't use it, otherwise you make your code fragile. (ERROR in zion) + 'sonarjs/no-useless-catch': 'warn', // Redundant, if all you do is re-throw a caught exception. + 'sonarjs/non-existent-operator': 'warn', // fixable // Almost always the result of a typo. (ERROR in zion) + 'sonarjs/prefer-object-literal': 'warn', // Inefficient. If this were auto-fixable, we would care more. + 'sonarjs/prefer-while': 'warn', // fixable // Readability. (ERROR in zion) + + // Disabled Rules: + 'sonarjs/elseif-without-else': 'off', // Disabled. Conflicts with our other autoformatting configuration. + 'sonarjs/no-nested-template-literals': 'off', // We do this a lot, most often with translations. + 'sonarjs/prefer-immediate-return': 'off', // fixable // Disabled. Violations can often be helpful by adhering to a consistent format, or adding a bit of additional context that would otherwise be lost. + 'sonarjs/prefer-single-boolean-return': 'off', // fixable // This is already addressed by our base configuration. 'test-selectors/anchor': testSelectorsConfiguration, 'test-selectors/button': testSelectorsConfiguration, diff --git a/package.json b/package.json index a88dd67..040c495 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fs/eslint-config-tree", - "version": "6.0.0-alpha.4", + "version": "6.0.0", "description": "Shared Tree configuration that contains overrides and enhancements on top of the base frontier configuration.", "main": "index.js", "repository": { @@ -28,15 +28,15 @@ "!.*" ], "dependencies": { - "@babel/eslint-parser": "^7.22.9", - "@fs/eslint-config-frontier-react": "^11.0.0-alpha.6", - "eslint": "^8.46.0", + "@babel/eslint-parser": "^7.23.3", + "@fs/eslint-config-frontier-react": "^11.0.0", + "eslint": "^8.55.0", "eslint-plugin-bestpractices": "github:skye2k2/eslint-plugin-bestpractices", "eslint-plugin-deprecate": "^0.7.0", "eslint-plugin-html": "^7.1.0", "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-sonarjs": "^0.18.0", - "eslint-plugin-test-selectors": "^2.0.4" + "eslint-plugin-sonarjs": "^0.22.0", + "eslint-plugin-test-selectors": "^2.1.1" }, "devDependencies": { "@fs/npm-publisher": "^1.5.2",