Skip to content

Commit

Permalink
feat(eslint-plugin): [restrict-plus-operands] check += (#892)
Browse files Browse the repository at this point in the history
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
  • Loading branch information
a-tarasyuk and bradzacher committed Nov 21, 2019
1 parent d97f809 commit fa88cb9
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 30 deletions.
31 changes: 31 additions & 0 deletions packages/eslint-plugin/docs/rules/restrict-plus-operands.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,37 @@ var foo = 1n + 1;

## Options

This rule has an object option:

- `"checkCompoundAssignments": false`: (default) does not check compound assignments (`+=`)
- `"checkCompoundAssignments": true`

### checkCompoundAssignments

Examples of **incorrect** code for the `{ "checkCompoundAssignments": true }` option:

```ts
/*eslint @typescript-eslint/restrict-plus-operands: ["error", { "checkCompoundAssignments": true }]*/

let foo: string | undefined;
foo += 'some data';

let bar: string = '';
bar += 0;
```

Examples of **correct** code for the `{ "checkCompoundAssignments": true }` option:

```ts
/*eslint @typescript-eslint/restrict-plus-operands: ["error", { "checkCompoundAssignments": true }]*/

let foo: number = 0;
foo += 1;

let bar = '';
bar += 'test';
```

```json
{
"@typescript-eslint/restrict-plus-operands": "error"
Expand Down
89 changes: 59 additions & 30 deletions packages/eslint-plugin/src/rules/restrict-plus-operands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import { TSESTree } from '@typescript-eslint/experimental-utils';
import ts from 'typescript';
import * as util from '../util';

export default util.createRule({
type Options = [
{
checkCompoundAssignments?: boolean;
},
];
type MessageIds = 'notNumbers' | 'notStrings' | 'notBigInts';

export default util.createRule<Options, MessageIds>({
name: 'restrict-plus-operands',
meta: {
type: 'problem',
Expand All @@ -20,12 +27,25 @@ export default util.createRule({
"Operands of '+' operation must either be both strings or both numbers. Consider using a template literal.",
notBigInts: "Operands of '+' operation must be both bigints.",
},
schema: [],
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
checkCompoundAssignments: {
type: 'boolean',
},
},
},
],
},
defaultOptions: [],
create(context) {
defaultOptions: [
{
checkCompoundAssignments: false,
},
],
create(context, [{ checkCompoundAssignments }]) {
const service = util.getParserServices(context);

const typeChecker = service.program.getTypeChecker();

type BaseLiteral = 'string' | 'number' | 'bigint' | 'invalid';
Expand Down Expand Up @@ -83,32 +103,41 @@ export default util.createRule({
return getBaseTypeOfLiteralType(type);
}

return {
"BinaryExpression[operator='+']"(node: TSESTree.BinaryExpression): void {
const leftType = getNodeType(node.left);
const rightType = getNodeType(node.right);
function checkPlusOperands(
node: TSESTree.BinaryExpression | TSESTree.AssignmentExpression,
): void {
const leftType = getNodeType(node.left);
const rightType = getNodeType(node.right);

if (
leftType === 'invalid' ||
rightType === 'invalid' ||
leftType !== rightType
) {
if (leftType === 'string' || rightType === 'string') {
context.report({
node,
messageId: 'notStrings',
});
} else if (leftType === 'bigint' || rightType === 'bigint') {
context.report({
node,
messageId: 'notBigInts',
});
} else {
context.report({
node,
messageId: 'notNumbers',
});
}
if (
leftType === 'invalid' ||
rightType === 'invalid' ||
leftType !== rightType
) {
if (leftType === 'string' || rightType === 'string') {
context.report({
node,
messageId: 'notStrings',
});
} else if (leftType === 'bigint' || rightType === 'bigint') {
context.report({
node,
messageId: 'notBigInts',
});
} else {
context.report({
node,
messageId: 'notNumbers',
});
}
}
}

return {
"BinaryExpression[operator='+']": checkPlusOperands,
"AssignmentExpression[operator='+=']"(node): void {
if (checkCompoundAssignments) {
checkPlusOperands(node);
}
},
};
Expand Down
58 changes: 58 additions & 0 deletions packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,28 @@ function foo<T extends 1>(a: T) {
return a + 1;
}
`,
{
code: `
let foo: number = 0;
foo += 1;
`,
options: [
{
checkCompoundAssignments: false,
},
],
},
{
code: `
let foo: number = 0;
foo += "string";
`,
options: [
{
checkCompoundAssignments: false,
},
],
},
],
invalid: [
{
Expand Down Expand Up @@ -383,5 +405,41 @@ function foo<T extends 1>(a: T) {
},
],
},
{
code: `
let foo: string | undefined;
foo += "some data";
`,
options: [
{
checkCompoundAssignments: true,
},
],
errors: [
{
messageId: 'notStrings',
line: 3,
column: 1,
},
],
},
{
code: `
let foo = '';
foo += 0;
`,
options: [
{
checkCompoundAssignments: true,
},
],
errors: [
{
messageId: 'notStrings',
line: 3,
column: 1,
},
],
},
],
});

0 comments on commit fa88cb9

Please sign in to comment.