After upgrading to eslint-plugin-sonarjs@2, I found a ton of new rules that duplicate existing ESLint rules, either from the base ESLint or popular plugins like typescript-eslint, eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-regexp, and eslint-plugin-unicorn.
Without knowing how exactly they differ, and not wanting to suddenly cause a bunch or lint rule name changes, invalidating many configurations and “disable comments”, I simply tested them using their documented examples to find where they overlap, and disabled them.
I would like for each of sonar’s rule duplicating an existing rule to:
- Be flagged as such, so a user can appropriately update configurations
- Explain what it changes / improves on, so that I can feel more confident that switching over to sonar’s re-implemented rules is worth over the original.
- Consider providing improvements upstream ?
If it’s just some special code to connect to SonarQube, maybe provide them as a separate preset? (such a preset could also disable base rules it replaces)
Here’s a non-exhaustive list (I noted 172 rules that I haven’t manually validated yet, because I haven’t seen a specific keyword in their description or haven’t hit them in code):
/*
* eslint-plugin-sonarjs@2 added rules that duplicate base ESLint rules or specific plugins we prefer
*/
// Duplicates no-warning-comments
"sonarjs/todo-tag": "off",
// Duplicates unicorn/prefer-string-starts-ends-with
"sonarjs/prefer-string-starts-ends-with": "off",
// Duplicates no-nested-ternary and unicorn/no-nested-ternary
"sonarjs/no-nested-conditional": "off",
// Base ESLint rules duplications (same names)
"sonarjs/default-param-last": "off",
"sonarjs/no-delete-var": "off",
"sonarjs/no-empty-function": "off",
"sonarjs/no-extend-native": "off",
"sonarjs/no-redeclare": "off",
"sonarjs/no-unreachable": "off",
"sonarjs/no-unused-expressions": "off",
"sonarjs/no-unused-private-class-members": "off",
"sonarjs/sonar-block-scoped-var": "off",
"sonarjs/sonar-max-params": "off",
"sonarjs/sonar-no-control-regex": "off",
"sonarjs/sonar-no-dupe-keys": "off",
"sonarjs/sonar-no-empty-character-class": "off", // Also regexp/no-empty-character-class
"sonarjs/sonar-no-fallthrough": "off",
"sonarjs/sonar-no-invalid-regexp": "off", // Also regexp/no-invalid-regexp
"sonarjs/sonar-no-misleading-character-class": "off",
"sonarjs/use-isnan": "off",
// eslint-plugin-autofix rules duplications (same names)
"sonarjs/no-lonely-if": "off", // Also unicorn/no-lonely-if
"sonarjs/no-throw-literal": "off",
"sonarjs/no-useless-catch": "off",
"sonarjs/no-var": "off",
"sonarjs/prefer-object-spread": "off",
"sonarjs/prefer-spread": "off", // Also unicorn/prefer-spread
"sonarjs/sonar-no-regex-spaces": "off", // Also regexp/prefer-quantifier
"sonarjs/sonar-no-unused-vars": "off",
// Other regex-related duplications
// Duplicates regexp/prefer-d, regexp/no-obscure-range and regexp/no-dupe-characters-character-class
"sonarjs/duplicates-in-character-class": "off",
// Duplicates regexp/prefer-w, regexp/prefer-d, regexp/match-any
"sonarjs/concise-regex": "off",
// Duplicates regexp/no-empty-alternative, regexp/no-trivially-nested-quantifier, regexp/no-dupe-disjunctions and regexp/no-trivially-nested-quantifier
"sonarjs/empty-string-repetition": "off",
// Duplicates regexp/no-useless-character-class
"sonarjs/single-char-in-character-classes": "off",
// Duplicates unicorn/better-regex and regexp/prefer-character-class
"sonarjs/single-character-alternation": "off",
// Duplicates regexp/no-super-linear-move
"sonarjs/slow-regex": "off",
// Duplciates regexp/prefer-regexp-exec
"sonarjs/sonar-prefer-regexp-exec": "off",
// Duplicates regexp/no-empty-alternative
"sonarjs/no-empty-alternatives": "off",
// Duplicates regexp/no-useless-dollar-replacements + regexp/no-unused-capturing-group
"sonarjs/existing-groups": "off",
// Duplicates regexp/no-empty-capturing-group and regexp/no-empty-group
"sonarjs/no-empty-group": "off",
// React/JSX-related duplications
// Duplicates react/hook-use-state
"sonarjs/hook-use-state": "off",
// Duplicates react/jsx-key
"sonarjs/jsx-key": "off",
// Duplicated react/jsx-no-constructed-context-values
"sonarjs/jsx-no-constructed-context-values": "off",
// Duplicates react/jsx-no-useless-fragment
"sonarjs/jsx-no-useless-fragment": "off",
// Duplicates react/no-array-index-key
"sonarjs/no-array-index-key": "off",
// Duplicates react/no-deprecated
"sonarjs/no-deprecated-react": "off",
// Duplicates react/no-find-dom-node
"sonarjs/no-find-dom-node": "off",
// Duplicates react/no-unknown-property
"sonarjs/no-unknown-property": "off",
// Duplicates react/no-unsafe
"sonarjs/no-unsafe": "off",
// Duplicates react/no-unstable-nested-components
"sonarjs/no-unstable-nested-components": "off",
// Duplicates react-hooks/rules-of-hooks
"sonarjs/rules-of-hooks": "off",
// Duplicates react/jsx-no-leaked-render
"sonarjs/sonar-jsx-no-leaked-render": "off",
// Duplicates react/no-unused-class-component-methods
"sonarjs/sonar-no-unused-class-component-methods": "off",
// Duplicates react/prefer-read-only-props
"sonarjs/sonar-prefer-read-only-props": "off",
/*
* SonarJS rules obsoleted by TS rules of the same name
*/
"sonarjs/no-misused-promises": "off",
"sonarjs/no-redundant-type-constituents": "off",
"sonarjs/prefer-enum-initializers": "off",
"sonarjs/prefer-nullish-coalescing": "off",
"sonarjs/sonar-prefer-optional-chain": "off",
// Redundant in TypeScript
"sonarjs/function-return-type": "off",
// [...]nobsoleted by @typescript-eslint/no-deprecated
"sonarjs/deprecation": "off",