eslint-plugin-sonarjs 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,20 +19,21 @@
19
19
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
  */
21
21
  // https://sonarsource.github.io/rspec/#/rspec/S1862
22
- const nodes_1 = require("../utils/nodes");
23
22
  const equivalence_1 = require("../utils/equivalence");
24
23
  const locations_1 = require("../utils/locations");
25
24
  const docs_url_1 = require("../utils/docs-url");
26
- const message = 'This branch duplicates the one on line {{line}}';
25
+ const duplicatedConditionMessage = 'This condition is covered by the one on line {{line}}';
26
+ const duplicatedCaseMessage = 'This case duplicates the one on line {{line}}';
27
27
  const rule = {
28
28
  meta: {
29
29
  messages: {
30
- duplicatedBranch: message,
30
+ duplicatedCondition: duplicatedConditionMessage,
31
+ duplicatedCase: duplicatedCaseMessage,
31
32
  sonarRuntime: '{{sonarRuntimeData}}',
32
33
  },
33
34
  type: 'problem',
34
35
  docs: {
35
- description: 'Related "if/else if" statements should not have the same condition',
36
+ description: 'Related "if-else-if" and "switch-case" statements should not have the same condition',
36
37
  recommended: 'error',
37
38
  url: (0, docs_url_1.default)(__filename),
38
39
  },
@@ -44,34 +45,84 @@ const rule = {
44
45
  ],
45
46
  },
46
47
  create(context) {
48
+ const sourceCode = context.getSourceCode();
47
49
  return {
48
50
  IfStatement(node) {
49
- const ifStmt = node;
50
- const condition = ifStmt.test;
51
- let statement = ifStmt.alternate;
52
- while (statement) {
53
- if ((0, nodes_1.isIfStatement)(statement)) {
54
- if ((0, equivalence_1.areEquivalent)(condition, statement.test, context.getSourceCode())) {
55
- const line = ifStmt.loc && ifStmt.loc.start.line;
56
- if (line && condition.loc) {
57
- (0, locations_1.report)(context, {
58
- messageId: 'duplicatedBranch',
59
- data: {
60
- line,
61
- },
62
- node: statement.test,
63
- }, [(0, locations_1.issueLocation)(condition.loc, condition.loc, 'Original')], message);
64
- }
65
- }
66
- statement = statement.alternate;
67
- }
68
- else {
51
+ var _a;
52
+ const { test } = node;
53
+ const conditionsToCheck = test.type === 'LogicalExpression' && test.operator === '&&'
54
+ ? [test, ...splitByAnd(test)]
55
+ : [test];
56
+ let current = node;
57
+ let operandsToCheck = conditionsToCheck.map(c => splitByOr(c).map(splitByAnd));
58
+ while (((_a = current.parent) === null || _a === void 0 ? void 0 : _a.type) === 'IfStatement' && current.parent.alternate === current) {
59
+ current = current.parent;
60
+ const currentOrOperands = splitByOr(current.test).map(splitByAnd);
61
+ operandsToCheck = operandsToCheck.map(orOperands => orOperands.filter(orOperand => !currentOrOperands.some(currentOrOperand => isSubset(currentOrOperand, orOperand, sourceCode))));
62
+ if (operandsToCheck.some(orOperands => orOperands.length === 0)) {
63
+ (0, locations_1.report)(context, {
64
+ messageId: 'duplicatedCondition',
65
+ data: { line: current.test.loc.start.line },
66
+ node: test,
67
+ }, [(0, locations_1.issueLocation)(current.test.loc, current.test.loc, 'Covering')], duplicatedConditionMessage);
69
68
  break;
70
69
  }
71
70
  }
72
71
  },
72
+ SwitchStatement(node) {
73
+ const switchStmt = node;
74
+ const previousTests = [];
75
+ for (const switchCase of switchStmt.cases) {
76
+ if (switchCase.test) {
77
+ const { test } = switchCase;
78
+ const duplicateTest = previousTests.find(previousTest => (0, equivalence_1.areEquivalent)(test, previousTest, sourceCode));
79
+ if (duplicateTest) {
80
+ (0, locations_1.report)(context, {
81
+ messageId: 'duplicatedCase',
82
+ data: {
83
+ line: duplicateTest.loc.start.line,
84
+ },
85
+ node: test,
86
+ }, [(0, locations_1.issueLocation)(duplicateTest.loc, duplicateTest.loc, 'Original')], duplicatedCaseMessage);
87
+ }
88
+ else {
89
+ previousTests.push(test);
90
+ }
91
+ }
92
+ }
93
+ },
73
94
  };
74
95
  },
75
96
  };
97
+ const splitByOr = splitByLogicalOperator.bind(null, '||');
98
+ const splitByAnd = splitByLogicalOperator.bind(null, '&&');
99
+ function splitByLogicalOperator(operator, node) {
100
+ if (node.type === 'LogicalExpression' && node.operator === operator) {
101
+ return [
102
+ ...splitByLogicalOperator(operator, node.left),
103
+ ...splitByLogicalOperator(operator, node.right),
104
+ ];
105
+ }
106
+ return [node];
107
+ }
108
+ function isSubset(first, second, sourceCode) {
109
+ return first.every(fst => second.some(snd => isSubsetOf(fst, snd, sourceCode)));
110
+ function isSubsetOf(first, second, sourceCode) {
111
+ if (first.type !== second.type) {
112
+ return false;
113
+ }
114
+ if (first.type === 'LogicalExpression') {
115
+ const second1 = second;
116
+ if ((first.operator === '||' || first.operator === '&&') &&
117
+ first.operator === second1.operator) {
118
+ return ((isSubsetOf(first.left, second1.left, sourceCode) &&
119
+ isSubsetOf(first.right, second1.right, sourceCode)) ||
120
+ (isSubsetOf(first.left, second1.right, sourceCode) &&
121
+ isSubsetOf(first.right, second1.left, sourceCode)));
122
+ }
123
+ }
124
+ return (0, equivalence_1.areEquivalent)(first, second, sourceCode);
125
+ }
126
+ }
76
127
  module.exports = rule;
77
128
  //# sourceMappingURL=no-identical-conditions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"no-identical-conditions.js","sourceRoot":"","sources":["../../src/rules/no-identical-conditions.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,oDAAoD;AAGpD,0CAA+C;AAC/C,sDAAqD;AACrD,kDAA2D;AAC3D,gDAAwC;AAExC,MAAM,OAAO,GAAG,iDAAiD,CAAC;AAElE,MAAM,IAAI,GAA0C;IAClD,IAAI,EAAE;QACJ,QAAQ,EAAE;YACR,gBAAgB,EAAE,OAAO;YACzB,YAAY,EAAE,sBAAsB;SACrC;QACD,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,oEAAoE;YACjF,WAAW,EAAE,OAAO;YACpB,GAAG,EAAE,IAAA,kBAAO,EAAC,UAAU,CAAC;SACzB;QACD,MAAM,EAAE;YACN;gBACE,qBAAqB;gBACrB,IAAI,EAAE,CAAC,eAAe,CAAC;aACxB;SACF;KACF;IACD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,WAAW,CAAC,IAAmB;gBAC7B,MAAM,MAAM,GAAG,IAA4B,CAAC;gBAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;gBAC9B,IAAI,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;gBACjC,OAAO,SAAS,EAAE;oBAChB,IAAI,IAAA,qBAAa,EAAC,SAAS,CAAC,EAAE;wBAC5B,IAAI,IAAA,2BAAa,EAAC,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,EAAE;4BACrE,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;4BACjD,IAAI,IAAI,IAAI,SAAS,CAAC,GAAG,EAAE;gCACzB,IAAA,kBAAM,EACJ,OAAO,EACP;oCACE,SAAS,EAAE,kBAAkB;oCAC7B,IAAI,EAAE;wCACJ,IAAI;qCACL;oCACD,IAAI,EAAE,SAAS,CAAC,IAAI;iCACrB,EACD,CAAC,IAAA,yBAAa,EAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,EACzD,OAAO,CACR,CAAC;6BACH;yBACF;wBACD,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;qBACjC;yBAAM;wBACL,MAAM;qBACP;iBACF;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,iBAAS,IAAI,CAAC"}
1
+ {"version":3,"file":"no-identical-conditions.js","sourceRoot":"","sources":["../../src/rules/no-identical-conditions.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-sonarjs",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "SonarJS rules for ESLint",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -51,7 +51,7 @@
51
51
  "eslint-config-prettier": "8.5.0",
52
52
  "eslint-plugin-import": "2.26.0",
53
53
  "eslint-plugin-notice": "0.9.10",
54
- "eslint-plugin-sonarjs": "0.17.0",
54
+ "eslint-plugin-sonarjs": "0.18.0",
55
55
  "jest": "28.1.3",
56
56
  "jest-sonar-reporter": "2.0.0",
57
57
  "lint-staged": "13.0.3",