Skip to content

Commit fb613f5

Browse files
authored
Add AST utils (#1769)
1 parent 20a1f52 commit fb613f5

38 files changed

+149
-157
lines changed

rules/ast/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
'use strict';
2+
3+
const {
4+
isLiteral,
5+
isStringLiteral,
6+
isNumberLiteral,
7+
isBigIntLiteral,
8+
isNullLiteral,
9+
isRegexLiteral,
10+
} = require('./literal.js');
11+
212
module.exports = {
13+
isLiteral,
14+
isStringLiteral,
15+
isNumberLiteral,
16+
isBigIntLiteral,
17+
isNullLiteral,
18+
isRegexLiteral,
19+
320
isArrowFunctionBody: require('./is-arrow-function-body.js'),
421
isEmptyNode: require('./is-empty-node.js'),
22+
isStaticRequire: require('./is-static-require.js'),
23+
isUndefined: require('./is-undefined.js'),
524
};
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const {isStringLiteral} = require('./literal.js');
4+
35
const isStaticRequire = node => Boolean(
46
node
57
&& node.type === 'CallExpression'
@@ -8,8 +10,7 @@ const isStaticRequire = node => Boolean(
810
&& node.callee.name === 'require'
911
&& !node.optional
1012
&& node.arguments.length === 1
11-
&& node.arguments[0].type === 'Literal'
12-
&& typeof node.arguments[0].value === 'string',
13+
&& isStringLiteral(node.arguments[0]),
1314
);
1415

1516
module.exports = isStaticRequire;

rules/ast/is-undefined.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
function isUndefined(node) {
4+
return node.type === 'Identifier' && node.name === 'undefined';
5+
}
6+
7+
module.exports = isUndefined;

rules/ast/literal.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
function isLiteral(node, value) {
4+
if (node?.type !== 'Literal') {
5+
return false;
6+
}
7+
8+
if (value === null) {
9+
return node.raw === 'null';
10+
}
11+
12+
return node.value === value;
13+
}
14+
15+
const isStringLiteral = node => node?.type === 'Literal' && typeof node.value === 'string';
16+
const isNumberLiteral = node => node.type === 'Literal' && typeof node.value === 'number';
17+
const isRegexLiteral = node => node.type === 'Literal' && Boolean(node.regex);
18+
// eslint-disable-next-line unicorn/no-null
19+
const isNullLiteral = node => isLiteral(node, null);
20+
const isBigIntLiteral = node => node.type === 'Literal' && Boolean(node.bigint);
21+
22+
module.exports = {
23+
isLiteral,
24+
isStringLiteral,
25+
isNumberLiteral,
26+
isBigIntLiteral,
27+
isNullLiteral,
28+
isRegexLiteral,
29+
};

rules/better-regex.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@ const cleanRegexp = require('clean-regexp');
33
const {optimize} = require('regexp-tree');
44
const quoteString = require('./utils/quote-string.js');
55
const {newExpressionSelector} = require('./selectors/index.js');
6+
const {isStringLiteral} = require('./ast/index.js');
67

78
const MESSAGE_ID = 'better-regex';
89
const messages = {
910
[MESSAGE_ID]: '{{original}} can be optimized to {{optimized}}.',
1011
};
1112

12-
const newRegExp = [
13-
newExpressionSelector({name: 'RegExp', minimumArguments: 1}),
14-
'[arguments.0.type="Literal"]',
15-
].join('');
13+
const newRegExp = newExpressionSelector({name: 'RegExp', minimumArguments: 1});
1614

1715
/** @param {import('eslint').Rule.RuleContext} context */
1816
const create = context => {
@@ -66,16 +64,12 @@ const create = context => {
6664
[newRegExp](node) {
6765
const [patternNode, flagsNode] = node.arguments;
6866

69-
if (typeof patternNode.value !== 'string') {
67+
if (!isStringLiteral(patternNode)) {
7068
return;
7169
}
7270

7371
const oldPattern = patternNode.value;
74-
const flags = (
75-
flagsNode
76-
&& flagsNode.type === 'Literal'
77-
&& typeof flagsNode.value === 'string'
78-
)
72+
const flags = isStringLiteral(flagsNode)
7973
? flagsNode.value
8074
: '';
8175

rules/consistent-function-scoping.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ const iifeFunctionTypes = new Set([
109109
]);
110110
const isIife = node => node
111111
&& iifeFunctionTypes.has(node.type)
112-
&& node.parent
113112
&& node.parent.type === 'CallExpression'
114113
&& node.parent.callee === node;
115114

rules/explicit-length-check.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
'use strict';
22
const {isParenthesized, getStaticValue} = require('eslint-utils');
33
const {checkVueTemplate} = require('./utils/rule.js');
4-
const isLiteralValue = require('./utils/is-literal-value.js');
54
const isLogicalExpression = require('./utils/is-logical-expression.js');
65
const {isBooleanNode, getBooleanAncestor} = require('./utils/boolean.js');
76
const {memberExpressionSelector} = require('./selectors/index.js');
87
const {fixSpaceAroundKeyword} = require('./fix/index.js');
8+
const {isLiteral} = require('./ast/index.js');
99

1010
const TYPE_NON_ZERO = 'non-zero';
1111
const TYPE_ZERO = 'zero';
@@ -19,11 +19,11 @@ const messages = {
1919
const isCompareRight = (node, operator, value) =>
2020
node.type === 'BinaryExpression'
2121
&& node.operator === operator
22-
&& isLiteralValue(node.right, value);
22+
&& isLiteral(node.right, value);
2323
const isCompareLeft = (node, operator, value) =>
2424
node.type === 'BinaryExpression'
2525
&& node.operator === operator
26-
&& isLiteralValue(node.left, value);
26+
&& isLiteral(node.left, value);
2727
const nonZeroStyles = new Map([
2828
[
2929
'greater-than',

rules/no-await-expression-member.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const {
33
removeParentheses,
44
removeMemberExpressionProperty,
55
} = require('./fix/index.js');
6+
const {isLiteral} = require('./ast/index.js');
67

78
const MESSAGE_ID = 'no-await-expression-member';
89
const messages = {
@@ -25,8 +26,7 @@ const create = context => {
2526
if (
2627
memberExpression.computed
2728
&& !memberExpression.optional
28-
&& property.type === 'Literal'
29-
&& (property.value === 0 || property.value === 1)
29+
&& (isLiteral(property, 0) || isLiteral(property, 1))
3030
&& memberExpression.parent.type === 'VariableDeclarator'
3131
&& memberExpression.parent.init === memberExpression
3232
&& memberExpression.parent.id.type === 'Identifier'

rules/no-console-spaces.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
const {methodCallSelector} = require('./selectors/index.js');
33
const toLocation = require('./utils/to-location.js');
4+
const {isStringLiteral} = require('./ast/index.js');
45

56
const MESSAGE_ID = 'no-console-spaces';
67
const messages = {
@@ -50,11 +51,7 @@ const create = context => {
5051
const {arguments: messages} = node;
5152
const {length} = messages;
5253
for (const [index, node] of messages.entries()) {
53-
const {type, value} = node;
54-
if (
55-
!(type === 'Literal' && typeof value === 'string')
56-
&& type !== 'TemplateLiteral'
57-
) {
54+
if (!isStringLiteral(node) && node.type !== 'TemplateLiteral') {
5855
continue;
5956
}
6057

rules/no-for-loop.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
'use strict';
22
const {isClosingParenToken, getStaticValue} = require('eslint-utils');
3-
const isLiteralValue = require('./utils/is-literal-value.js');
43
const avoidCapture = require('./utils/avoid-capture.js');
54
const getScopes = require('./utils/get-scopes.js');
65
const singular = require('./utils/singular.js');
76
const toLocation = require('./utils/to-location.js');
87
const getReferences = require('./utils/get-references.js');
8+
const {isLiteral} = require('./ast/index.js');
99

1010
const MESSAGE_ID = 'no-for-loop';
1111
const messages = {
1212
[MESSAGE_ID]: 'Use a `for-of` loop instead of this `for` loop.',
1313
};
1414

1515
const defaultElementName = 'element';
16-
const isLiteralZero = node => isLiteralValue(node, 0);
17-
const isLiteralOne = node => isLiteralValue(node, 1);
16+
const isLiteralZero = node => isLiteral(node, 0);
17+
const isLiteralOne = node => isLiteral(node, 1);
1818

1919
const isIdentifierWithName = (node, name) => node && node.type === 'Identifier' && node.name === name;
2020

0 commit comments

Comments
 (0)