Skip to content
This repository was archived by the owner on Oct 3, 2024. It is now read-only.

Commit 6e95742

Browse files
Add meta.docs for each rule (#246)
Eslint does support a documentation section in rule definitions. This section allows IDE plugins to display rule descriptions and directly link to the rule documentation. Details are documentad at: https://eslint.org/docs/developer-guide/working-with-rules#rule-basics Co-authored-by: Daniel Graf Hoyos <[email protected]>
1 parent d23f065 commit 6e95742

35 files changed

+270
-38
lines changed

src/index.ts

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,50 +17,28 @@
1717
* along with this program; if not, write to the Free Software Foundation,
1818
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919
*/
20+
import * as fs from 'fs';
21+
import * as path from 'path';
2022
import { TSESLint } from '@typescript-eslint/experimental-utils';
2123

22-
const sonarjsRules: [string, TSESLint.Linter.RuleLevel][] = [
23-
['cognitive-complexity', 'error'],
24-
['elseif-without-else', 'off'],
25-
['generator-without-yield', 'error'],
26-
['max-switch-cases', 'error'],
27-
['no-all-duplicated-branches', 'error'],
28-
['no-collapsible-if', 'error'],
29-
['no-collection-size-mischeck', 'error'],
30-
['no-duplicate-string', 'error'],
31-
['no-duplicated-branches', 'error'],
32-
['no-element-overwrite', 'error'],
33-
['no-empty-collection', 'error'],
34-
['no-extra-arguments', 'error'],
35-
['no-gratuitous-expressions', 'error'],
36-
['no-identical-conditions', 'error'],
37-
['no-identical-functions', 'error'],
38-
['no-identical-expressions', 'error'],
39-
['no-inverted-boolean-check', 'error'],
40-
['no-nested-switch', 'error'],
41-
['no-nested-template-literals', 'error'],
42-
['no-one-iteration-loop', 'error'],
43-
['no-redundant-boolean', 'error'],
44-
['no-redundant-jump', 'error'],
45-
['no-same-line-conditional', 'error'],
46-
['no-small-switch', 'error'],
47-
['no-unused-collection', 'error'],
48-
['no-use-of-empty-return-value', 'error'],
49-
['no-useless-catch', 'error'],
50-
['non-existent-operator', 'error'],
51-
['prefer-immediate-return', 'error'],
52-
['prefer-object-literal', 'error'],
53-
['prefer-single-boolean-return', 'error'],
54-
['prefer-while', 'error'],
55-
];
24+
const sonarjsRules: string[] = fs
25+
.readdirSync(path.join(__dirname, 'rules'))
26+
.map(filename => filename.substr(0, filename.lastIndexOf('.ts')));
5627

5728
const sonarjsRuleModules: { [key: string]: any } = {};
5829

5930
const configs: { recommended: TSESLint.Linter.Config & { plugins: string[] } } = {
6031
recommended: { plugins: ['sonarjs'], rules: {} },
6132
};
6233

63-
sonarjsRules.forEach(rule => (sonarjsRuleModules[rule[0]] = require(`./rules/${rule[0]}`)));
64-
sonarjsRules.forEach(rule => (configs.recommended.rules![`sonarjs/${rule[0]}`] = rule[1]));
34+
sonarjsRules.forEach(rule => {
35+
sonarjsRuleModules[rule] = require(`./rules/${rule}`);
36+
const {
37+
meta: {
38+
docs: { recommended },
39+
},
40+
} = sonarjsRuleModules[rule];
41+
configs.recommended.rules![`sonarjs/${rule}`] = recommended === false ? 'off' : recommended;
42+
});
6543

6644
export { sonarjsRuleModules as rules, configs };

src/rules/cognitive-complexity.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
issueLocation,
3131
} from '../utils/locations';
3232
import { Rule } from '../utils/types';
33+
import docsUrl from '../utils/docs-url';
3334

3435
const DEFAULT_THRESHOLD = 15;
3536

@@ -47,6 +48,12 @@ type Options = [number, 'metric'];
4748
const rule: Rule.RuleModule<string, Options> = {
4849
meta: {
4950
type: 'suggestion',
51+
docs: {
52+
description: 'Cognitive Complexity of functions should not be too high',
53+
category: 'Best Practices',
54+
recommended: 'error',
55+
url: docsUrl(__filename),
56+
},
5057
schema: [
5158
{ type: 'integer', minimum: 0 },
5259
{

src/rules/elseif-without-else.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@
2121

2222
import { TSESTree } from '@typescript-eslint/experimental-utils';
2323
import { Rule } from '../utils/types';
24+
import docsUrl from '../utils/docs-url';
2425

2526
const rule: Rule.RuleModule = {
2627
meta: {
2728
type: 'suggestion',
29+
docs: {
30+
description: '"if ... else if" constructs should end with "else" clauses',
31+
category: 'Best Practices',
32+
recommended: false,
33+
url: docsUrl(__filename),
34+
},
2835
},
2936
create(context: Rule.RuleContext) {
3037
return {

src/rules/generator-without-yield.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@
2222
import { TSESTree } from '@typescript-eslint/experimental-utils';
2323
import { getMainFunctionTokenLocation } from '../utils/locations';
2424
import { Rule } from '../utils/types';
25+
import docsUrl from '../utils/docs-url';
2526

2627
const MESSAGE = 'Add a "yield" statement to this generator.';
2728

2829
const rule: Rule.RuleModule = {
2930
meta: {
3031
type: 'problem',
32+
docs: {
33+
description: 'Generators should "yield" something',
34+
category: 'Possible Errors',
35+
recommended: 'error',
36+
url: docsUrl(__filename),
37+
},
3138
},
3239
create(context: Rule.RuleContext) {
3340
const yieldStack: number[] = [];

src/rules/max-switch-cases.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import { TSESTree } from '@typescript-eslint/experimental-utils';
2323
import { Rule } from '../utils/types';
24+
import docsUrl from '../utils/docs-url';
2425

2526
const MESSAGE =
2627
'Reduce the number of non-empty switch cases from {{numSwitchCases}} to at most {{maxSwitchCases}}.';
@@ -33,6 +34,12 @@ type Options = [number];
3334
const rule: Rule.RuleModule<string, Options> = {
3435
meta: {
3536
type: 'suggestion',
37+
docs: {
38+
description: '"switch" statements should not have too many "case" clauses',
39+
category: 'Best Practices',
40+
recommended: 'error',
41+
url: docsUrl(__filename),
42+
},
3643
schema: [
3744
{
3845
type: 'integer',

src/rules/no-all-duplicated-branches.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { Rule } from '../utils/types';
2424
import { isIfStatement } from '../utils/nodes';
2525
import { areEquivalent } from '../utils/equivalence';
2626
import { collectIfBranches, collectSwitchBranches } from '../utils/conditions';
27+
import docsUrl from '../utils/docs-url';
2728

2829
const MESSAGE =
2930
"Remove this conditional structure or edit its code blocks so that they're not all the same.";
@@ -33,6 +34,13 @@ const MESSAGE_CONDITIONAL_EXPRESSION =
3334
const rule: Rule.RuleModule = {
3435
meta: {
3536
type: 'problem',
37+
docs: {
38+
description:
39+
'All branches in a conditional structure should not have exactly the same implementation',
40+
category: 'Possible Errors',
41+
recommended: 'error',
42+
url: docsUrl(__filename),
43+
},
3644
},
3745
create(context: Rule.RuleContext) {
3846
return {

src/rules/no-collapsible-if.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@ import { TSESTree } from '@typescript-eslint/experimental-utils';
2323
import { Rule } from '../utils/types';
2424
import { isIfStatement, isBlockStatement } from '../utils/nodes';
2525
import { report, issueLocation } from '../utils/locations';
26+
import docsUrl from '../utils/docs-url';
2627

2728
const rule: Rule.RuleModule = {
2829
meta: {
2930
type: 'suggestion',
31+
docs: {
32+
description: 'Collapsible "if" statements should be merged',
33+
category: 'Best Practices',
34+
recommended: 'error',
35+
url: docsUrl(__filename),
36+
},
3037
schema: [
3138
{
3239
// internal parameter

src/rules/no-collection-size-mischeck.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,20 @@
2222
import { TSESTree } from '@typescript-eslint/experimental-utils';
2323
import { Rule } from '../utils/types';
2424
import { isRequiredParserServices, RequiredParserServices } from '../utils/parser-services';
25+
import docsUrl from '../utils/docs-url';
2526

2627
const CollectionLike = ['Array', 'Map', 'Set', 'WeakMap', 'WeakSet'];
2728
const CollectionSizeLike = ['length', 'size'];
2829

2930
const rule: Rule.RuleModule = {
3031
meta: {
3132
type: 'problem',
33+
docs: {
34+
description: 'Collection sizes and array length comparisons should make sense',
35+
category: 'Possible Errors',
36+
recommended: 'error',
37+
url: docsUrl(__filename),
38+
},
3239
},
3340
create(context: Rule.RuleContext) {
3441
const services = context.parserServices;

src/rules/no-duplicate-string.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import { TSESTree } from '@typescript-eslint/experimental-utils';
2323
import { Rule } from '../utils/types';
24+
import docsUrl from '../utils/docs-url';
2425

2526
// Number of times a literal must be duplicated to trigger an issue
2627
const DEFAULT_THRESHOLD = 3;
@@ -39,6 +40,12 @@ type Options = [number];
3940
const rule: Rule.RuleModule<string, Options> = {
4041
meta: {
4142
type: 'suggestion',
43+
docs: {
44+
description: 'String literals should not be duplicated',
45+
category: 'Best Practices',
46+
recommended: 'error',
47+
url: docsUrl(__filename),
48+
},
4249
schema: [{ type: 'integer', minimum: 2 }],
4350
},
4451

src/rules/no-duplicated-branches.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,21 @@ import { isIfStatement, isBlockStatement } from '../utils/nodes';
2525
import { areEquivalent } from '../utils/equivalence';
2626
import { collectIfBranches, takeWithoutBreak, collectSwitchBranches } from '../utils/conditions';
2727
import { report, issueLocation } from '../utils/locations';
28+
import docsUrl from '../utils/docs-url';
2829

2930
const MESSAGE =
3031
"This {{type}}'s code block is the same as the block for the {{type}} on line {{line}}.";
3132

3233
const rule: Rule.RuleModule = {
3334
meta: {
3435
type: 'problem',
36+
docs: {
37+
description:
38+
'Two branches in a conditional structure should not have exactly the same implementation',
39+
category: 'Possible Errors',
40+
recommended: 'error',
41+
url: docsUrl(__filename),
42+
},
3543
schema: [
3644
{
3745
// internal parameter

0 commit comments

Comments
 (0)