]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Rule to flag use of unary increment and decrement operators. | |
3 | * @author Ian Christian Myers | |
4 | * @author Brody McKee (github.com/mrmckeb) | |
5 | */ | |
6 | ||
7 | "use strict"; | |
8 | ||
9 | //------------------------------------------------------------------------------ | |
10 | // Helpers | |
11 | //------------------------------------------------------------------------------ | |
12 | ||
13 | /** | |
14 | * Determines whether the given node is the update node of a `ForStatement`. | |
15 | * @param {ASTNode} node The node to check. | |
16 | * @returns {boolean} `true` if the node is `ForStatement` update. | |
17 | */ | |
18 | function isForStatementUpdate(node) { | |
19 | const parent = node.parent; | |
20 | ||
21 | return parent.type === "ForStatement" && parent.update === node; | |
22 | } | |
23 | ||
24 | /** | |
25 | * Determines whether the given node is considered to be a for loop "afterthought" by the logic of this rule. | |
26 | * In particular, it returns `true` if the given node is either: | |
27 | * - The update node of a `ForStatement`: for (;; i++) {} | |
28 | * - An operand of a sequence expression that is the update node: for (;; foo(), i++) {} | |
29 | * - An operand of a sequence expression that is child of another sequence expression, etc., | |
30 | * up to the sequence expression that is the update node: for (;; foo(), (bar(), (baz(), i++))) {} | |
31 | * @param {ASTNode} node The node to check. | |
32 | * @returns {boolean} `true` if the node is a for loop afterthought. | |
33 | */ | |
34 | function isForLoopAfterthought(node) { | |
35 | const parent = node.parent; | |
36 | ||
37 | if (parent.type === "SequenceExpression") { | |
38 | return isForLoopAfterthought(parent); | |
39 | } | |
40 | ||
41 | return isForStatementUpdate(node); | |
42 | } | |
43 | ||
44 | //------------------------------------------------------------------------------ | |
45 | // Rule Definition | |
46 | //------------------------------------------------------------------------------ | |
47 | ||
34eeec05 | 48 | /** @type {import('../shared/types').Rule} */ |
eb39fafa DC |
49 | module.exports = { |
50 | meta: { | |
51 | type: "suggestion", | |
52 | ||
53 | docs: { | |
54 | description: "disallow the unary operators `++` and `--`", | |
eb39fafa DC |
55 | recommended: false, |
56 | url: "https://eslint.org/docs/rules/no-plusplus" | |
57 | }, | |
58 | ||
59 | schema: [ | |
60 | { | |
61 | type: "object", | |
62 | properties: { | |
63 | allowForLoopAfterthoughts: { | |
64 | type: "boolean", | |
65 | default: false | |
66 | } | |
67 | }, | |
68 | additionalProperties: false | |
69 | } | |
70 | ], | |
71 | ||
72 | messages: { | |
73 | unexpectedUnaryOp: "Unary operator '{{operator}}' used." | |
74 | } | |
75 | }, | |
76 | ||
77 | create(context) { | |
78 | ||
79 | const config = context.options[0]; | |
80 | let allowForLoopAfterthoughts = false; | |
81 | ||
82 | if (typeof config === "object") { | |
83 | allowForLoopAfterthoughts = config.allowForLoopAfterthoughts === true; | |
84 | } | |
85 | ||
86 | return { | |
87 | ||
88 | UpdateExpression(node) { | |
89 | if (allowForLoopAfterthoughts && isForLoopAfterthought(node)) { | |
90 | return; | |
91 | } | |
92 | ||
93 | context.report({ | |
94 | node, | |
95 | messageId: "unexpectedUnaryOp", | |
96 | data: { | |
97 | operator: node.operator | |
98 | } | |
99 | }); | |
100 | } | |
101 | ||
102 | }; | |
103 | ||
104 | } | |
105 | }; |