diff --git a/README.md b/README.md index ec963b9f..b8a4655a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Rules in this category aim to find places in code which have a high chance of be * Return values from functions without side effects should not be ignored ([`no-ignored-return`]) (*uses-types*) * Loops with at most one iteration should be refactored ([`no-one-iteration-loop`]) * The output of functions that don't return anything should not be used ([`no-use-of-empty-return-value`]) -* Non-existent operators '=+', '=-' and '=!' should not be used ([`non-existent-operator`]) +* Non-existent operators '=+', '=-' and '=!' should not be used ([`non-existent-operator`]) (:wrench: *fixable*) ### Code Smell Detection :pig: diff --git a/docs/rules/non-existent-operator.md b/docs/rules/non-existent-operator.md index 01ad49b2..678eec43 100644 --- a/docs/rules/non-existent-operator.md +++ b/docs/rules/non-existent-operator.md @@ -1,5 +1,7 @@ # non-existent-operator +:wrench: *fixable* + The use of operators pairs (`=+`, `=-` or `=!`) where the reversed, single operator was meant (`+=`, `-=` or `!=`) will compile and run, but not produce the expected results. This rule raises an issue when `=+`, `=-` and `=!` are used without any space between the two operators and when there is at least one whitespace after. diff --git a/src/rules/non-existent-operator.ts b/src/rules/non-existent-operator.ts index 39eb2ffd..b7b99c69 100644 --- a/src/rules/non-existent-operator.ts +++ b/src/rules/non-existent-operator.ts @@ -26,9 +26,11 @@ const rule: TSESLint.RuleModule = { meta: { messages: { useExistingOperator: 'Was "{{operator}}=" meant instead?', + suggestExistingOperator: 'Replace with "{{operator}}" operator', }, schema: [], type: 'problem', + hasSuggestions: true, docs: { description: 'Non-existent operators "=+", "=-" and "=!" should not be used', recommended: 'error', @@ -75,12 +77,28 @@ function checkOperator( areAdjacent(assignmentOperatorToken, unaryOperatorToken) && !areAdjacent(unaryOperatorToken, expressionFirstToken) ) { + const suggest: TSESLint.ReportSuggestionArray = []; + if (unaryNode.parent?.type === 'AssignmentExpression') { + const range: [number, number] = [ + assignmentOperatorToken.range[0], + unaryOperatorToken.range[1], + ]; + const invertedOperators = unaryOperatorToken.value + assignmentOperatorToken.value; + suggest.push({ + messageId: 'suggestExistingOperator', + data: { + operator: invertedOperators, + }, + fix: fixer => fixer.replaceTextRange(range, invertedOperators), + }); + } context.report({ messageId: 'useExistingOperator', data: { operator: unaryNode.operator, }, loc: { start: assignmentOperatorToken.loc.start, end: unaryOperatorToken.loc.end }, + suggest, }); } } diff --git a/tests/rules/non-existent-operator.test.ts b/tests/rules/non-existent-operator.test.ts index 8d2b7a45..aebe56f6 100644 --- a/tests/rules/non-existent-operator.test.ts +++ b/tests/rules/non-existent-operator.test.ts @@ -53,6 +53,15 @@ ruleTester.run("Non-existent operators '=+', '=-' and '=!' should not be used", endLine: 1, column: 3, endColumn: 5, + suggestions: [ + { + messageId: 'suggestExistingOperator', + data: { + operator: '+=', + }, + output: `x += y;`, + }, + ], }, ], }, @@ -114,6 +123,7 @@ ruleTester.run("Non-existent operators '=+', '=-' and '=!' should not be used", endLine: 1, column: 7, endColumn: 9, + suggestions: [], }, ], },