1 | const {docsUrl} = require('../utilities');
|
2 |
|
3 | const MESSAGES = {
|
4 | always: 'You must include parentheses around a binary assignment expression.',
|
5 | never:
|
6 | 'You must not include parentheses around a binary assignment expression.',
|
7 | };
|
8 |
|
9 | const BOOLEAN_OPERATORS = ['==', '===', '!=', '!==', '>', '>=', '<', '<='];
|
10 |
|
11 | module.exports = {
|
12 | meta: {
|
13 | docs: {
|
14 | description:
|
15 | 'Enforce (or disallow) assignments of binary, boolean-producing expressions to be wrapped in parentheses.',
|
16 | category: 'Best Practices',
|
17 | recommended: false,
|
18 | uri: docsUrl('binary-assignment-parens'),
|
19 | },
|
20 |
|
21 | schema: [
|
22 | {
|
23 | enum: ['always', 'never'],
|
24 | },
|
25 | ],
|
26 | },
|
27 |
|
28 | create(context) {
|
29 | const config = context.options[0] || 'always';
|
30 | const shouldHaveParens = config === 'always';
|
31 |
|
32 | function hasParens(node) {
|
33 | const beforeToken = context.getTokenBefore(node);
|
34 | const hasBeforeParen =
|
35 | beforeToken &&
|
36 | beforeToken.type === 'Punctuator' &&
|
37 | beforeToken.value === '(';
|
38 | const afterToken = context.getTokenAfter(node);
|
39 | const hasAfterParen =
|
40 | afterToken &&
|
41 | afterToken.type === 'Punctuator' &&
|
42 | afterToken.value === ')';
|
43 |
|
44 | return hasBeforeParen && hasAfterParen;
|
45 | }
|
46 |
|
47 | function evaluateBinaryExpression(node) {
|
48 | if (BOOLEAN_OPERATORS.indexOf(node.operator) < 0) {
|
49 | return;
|
50 | }
|
51 |
|
52 | if (shouldHaveParens !== hasParens(node)) {
|
53 | context.report(node, MESSAGES[config]);
|
54 | }
|
55 | }
|
56 |
|
57 | function evaluateLogicalExpression(node) {
|
58 | [node.left, node.right].forEach(evaluateAssignmentExpression);
|
59 | }
|
60 |
|
61 | function evaluateAssignmentExpression(node) {
|
62 | if (!node) {
|
63 | return;
|
64 | }
|
65 |
|
66 | if (node.type === 'BinaryExpression') {
|
67 | evaluateBinaryExpression(node);
|
68 | }
|
69 | if (node.type === 'LogicalExpression') {
|
70 | evaluateLogicalExpression(node);
|
71 | }
|
72 | }
|
73 |
|
74 | return {
|
75 | VariableDeclarator(node) {
|
76 | evaluateAssignmentExpression(node.init);
|
77 | },
|
78 |
|
79 | AssignmentExpression(node) {
|
80 | evaluateAssignmentExpression(node.right);
|
81 | },
|
82 | };
|
83 | },
|
84 | };
|