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

Commit 2e7830f

Browse files
no-identical-expressions: provide secondary issue locations (#102)
1 parent 26d6838 commit 2e7830f

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

src/rules/no-identical-expressions.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@ import { Rule } from "eslint";
2323
import { Node, BinaryExpression, LogicalExpression } from "estree";
2424
import { isIdentifier, isLiteral } from "../utils/nodes";
2525
import { areEquivalent } from "../utils/equivalence";
26+
import { report, issueLocation, IssueLocation } from "../utils/locations";
2627

2728
const EQUALITY_OPERATOR_TOKEN_KINDS = new Set(["==", "===", "!=", "!=="]);
2829

2930
// consider only binary expressions with these operators
3031
const RELEVANT_OPERATOR_TOKEN_KINDS = new Set(["&&", "||", "/", "-", "<<", ">>", "<", "<=", ">", ">="]);
3132

33+
const message = (operator: string) =>
34+
`Correct one of the identical sub-expressions on both sides of operator "${operator}"`;
35+
3236
function hasRelevantOperator(node: BinaryExpression | LogicalExpression) {
3337
return (
3438
RELEVANT_OPERATOR_TOKEN_KINDS.has(node.operator) ||
@@ -45,6 +49,14 @@ function isOneOntoOneShifting(node: BinaryExpression | LogicalExpression) {
4549
}
4650

4751
const rule: Rule.RuleModule = {
52+
meta: {
53+
schema: [
54+
{
55+
// internal parameter
56+
enum: ["sonar-runtime"],
57+
},
58+
],
59+
},
4860
create(context: Rule.RuleContext) {
4961
return {
5062
LogicalExpression(node: Node) {
@@ -61,13 +73,24 @@ const rule: Rule.RuleModule = {
6173
!isOneOntoOneShifting(expr) &&
6274
areEquivalent(expr.left, expr.right, context.getSourceCode())
6375
) {
64-
context.report({
65-
message: `Correct one of the identical sub-expressions on both sides of operator "{{operator}}"`,
66-
data: { operator: expr.operator },
67-
node: expr,
68-
});
76+
const secondaryLocations: IssueLocation[] = [];
77+
if (expr.left.loc) {
78+
secondaryLocations.push(issueLocation(expr.left.loc));
79+
}
80+
report(
81+
context,
82+
{
83+
message: message(expr.operator),
84+
node: isSonarRuntime() ? expr.right : expr,
85+
},
86+
secondaryLocations,
87+
);
6988
}
7089
}
90+
91+
function isSonarRuntime() {
92+
return context.options[context.options.length - 1] === "sonar-runtime";
93+
}
7194
},
7295
};
7396

tests/rules/no-identical-expressions.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,31 @@ ruleTester.run("no-identical-expressions", rule, {
6060
code: "a == b || a == b",
6161
errors: 1,
6262
},
63+
{
64+
code: `a == b || a == b
65+
// ^^^^^^> ^^^^^^`,
66+
options: ["sonar-runtime"],
67+
errors: [
68+
{
69+
message: JSON.stringify({
70+
secondaryLocations: [
71+
{
72+
line: 1,
73+
column: 0,
74+
endLine: 1,
75+
endColumn: 6,
76+
message: "",
77+
},
78+
],
79+
message: `Correct one of the identical sub-expressions on both sides of operator "||"`,
80+
}),
81+
line: 1,
82+
endLine: 1,
83+
column: 11,
84+
endColumn: 17,
85+
},
86+
],
87+
},
6388
{
6489
code: "a > a",
6590
errors: 1,

0 commit comments

Comments
 (0)