Skip to content
Permalink
Newer
Older
100644 138 lines (115 sloc) 4.67 KB
Ignoring revisions in .git-blame-ignore-revs.
September 14, 2020 10:42
1
/**
2
* @fileoverview Rule to flag use of comma operator
3
* @author Brandon Mills
4
*/
5
6
"use strict";
7
8
//------------------------------------------------------------------------------
9
// Requirements
10
//------------------------------------------------------------------------------
11
12
const astUtils = require("./utils/ast-utils");
13
July 27, 2021 16:54
14
//------------------------------------------------------------------------------
15
// Helpers
16
//------------------------------------------------------------------------------
17
18
const DEFAULT_OPTIONS = {
19
allowInParentheses: true
20
};
21
September 14, 2020 10:42
22
//------------------------------------------------------------------------------
23
// Rule Definition
24
//------------------------------------------------------------------------------
25
January 18, 2023 20:50
26
/** @type {import('../shared/types').Rule} */
September 14, 2020 10:42
27
module.exports = {
28
meta: {
29
type: "suggestion",
30
31
docs: {
January 18, 2023 20:50
32
description: "Disallow comma operators",
September 14, 2020 10:42
33
recommended: false,
July 13, 2023 09:09
34
url: "https://eslint.org/docs/latest/rules/no-sequences"
September 14, 2020 10:42
35
},
36
July 27, 2021 16:54
37
schema: [{
38
properties: {
39
allowInParentheses: {
40
type: "boolean",
41
default: true
42
}
43
},
44
additionalProperties: false
45
}],
September 14, 2020 10:42
46
47
messages: {
48
unexpectedCommaExpression: "Unexpected use of comma operator."
49
}
50
},
51
52
create(context) {
July 27, 2021 16:54
53
const options = Object.assign({}, DEFAULT_OPTIONS, context.options[0]);
July 13, 2023 09:09
54
const sourceCode = context.sourceCode;
September 14, 2020 10:42
55
56
/**
57
* Parts of the grammar that are required to have parens.
58
*/
59
const parenthesized = {
60
DoWhileStatement: "test",
61
IfStatement: "test",
62
SwitchStatement: "discriminant",
63
WhileStatement: "test",
64
WithStatement: "object",
65
ArrowFunctionExpression: "body"
66
67
/*
68
* Omitting CallExpression - commas are parsed as argument separators
69
* Omitting NewExpression - commas are parsed as argument separators
70
* Omitting ForInStatement - parts aren't individually parenthesised
71
* Omitting ForStatement - parts aren't individually parenthesised
72
*/
73
};
74
75
/**
76
* Determines whether a node is required by the grammar to be wrapped in
77
* parens, e.g. the test of an if statement.
78
* @param {ASTNode} node The AST node
79
* @returns {boolean} True if parens around node belong to parent node.
80
*/
81
function requiresExtraParens(node) {
82
return node.parent && parenthesized[node.parent.type] &&
83
node === node.parent[parenthesized[node.parent.type]];
84
}
85
86
/**
87
* Check if a node is wrapped in parens.
88
* @param {ASTNode} node The AST node
89
* @returns {boolean} True if the node has a paren on each side.
90
*/
91
function isParenthesised(node) {
92
return astUtils.isParenthesised(sourceCode, node);
93
}
94
95
/**
96
* Check if a node is wrapped in two levels of parens.
97
* @param {ASTNode} node The AST node
98
* @returns {boolean} True if two parens surround the node on each side.
99
*/
100
function isParenthesisedTwice(node) {
101
const previousToken = sourceCode.getTokenBefore(node, 1),
102
nextToken = sourceCode.getTokenAfter(node, 1);
103
104
return isParenthesised(node) && previousToken && nextToken &&
105
astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
106
astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
107
}
108
109
return {
110
SequenceExpression(node) {
111
112
// Always allow sequences in for statement update
113
if (node.parent.type === "ForStatement" &&
114
(node === node.parent.init || node === node.parent.update)) {
115
return;
116
}
117
118
// Wrapping a sequence in extra parens indicates intent
July 27, 2021 16:54
119
if (options.allowInParentheses) {
120
if (requiresExtraParens(node)) {
121
if (isParenthesisedTwice(node)) {
122
return;
123
}
124
} else {
125
if (isParenthesised(node)) {
126
return;
127
}
September 14, 2020 10:42
128
}
129
}
130
131
const firstCommaToken = sourceCode.getTokenAfter(node.expressions[0], astUtils.isCommaToken);
132
133
context.report({ node, loc: firstCommaToken.loc, messageId: "unexpectedCommaExpression" });
134
}
135
};
136
137
}
138
};