Skip to content

Commit ab61540

Browse files
authored
Use simple selectors (#2134)
1 parent 1f7488a commit ab61540

32 files changed

+661
-576
lines changed

rules/ast/function-types.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
const functionTypes = ['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'];
4+
5+
module.exports = functionTypes;

rules/ast/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@ module.exports = {
3333
isReferenceIdentifier: require('./is-reference-identifier.js'),
3434
isStaticRequire: require('./is-static-require.js'),
3535
isUndefined: require('./is-undefined.js'),
36+
37+
functionTypes: require('./function-types.js'),
3638
};

rules/ast/is-function.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
'use strict';
2+
const functionTypes = require('./function-types.js');
23

34
function isFunction(node) {
4-
return node.type === 'FunctionDeclaration'
5-
|| node.type === 'FunctionExpression'
6-
|| node.type === 'ArrowFunctionExpression';
5+
return functionTypes.includes(node.type);
76
}
87

98
module.exports = isFunction;

rules/better-regex.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
const cleanRegexp = require('clean-regexp');
33
const {optimize} = require('regexp-tree');
44
const escapeString = require('./utils/escape-string.js');
5-
const {isStringLiteral, isNewExpression} = require('./ast/index.js');
5+
const {isStringLiteral, isNewExpression, isRegexLiteral} = require('./ast/index.js');
66

77
const MESSAGE_ID = 'better-regex';
88
const MESSAGE_ID_PARSE_ERROR = 'better-regex/parse-error';
@@ -22,7 +22,11 @@ const create = context => {
2222
}
2323

2424
return {
25-
'Literal[regex]'(node) {
25+
Literal(node) {
26+
if (!isRegexLiteral(node)) {
27+
return;
28+
}
29+
2630
const {raw: original, regex} = node;
2731

2832
// Regular Expressions with `u` flag are not well handled by `regexp-tree`

rules/consistent-function-scoping.js

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
'use strict';
22
const {getFunctionHeadLocation, getFunctionNameWithKind} = require('@eslint-community/eslint-utils');
3-
const getReferences = require('./utils/get-references.js');
4-
const {isNodeMatches} = require('./utils/is-node-matches.js');
3+
const {
4+
getReferences,
5+
isNodeMatches,
6+
} = require('./utils/index.js');
7+
const {
8+
functionTypes,
9+
} = require('./ast/index.js');
510

611
const MESSAGE_ID = 'consistent-function-scoping';
712
const messages = {
@@ -154,41 +159,41 @@ const create = context => {
154159

155160
const functions = [];
156161

157-
return {
158-
':function'() {
159-
functions.push(false);
160-
},
161-
JSXElement() {
162-
// Turn off this rule if we see a JSX element because scope
163-
// references does not include JSXElement nodes.
164-
if (functions.length > 0) {
165-
functions[functions.length - 1] = true;
166-
}
167-
},
168-
':function:exit'(node) {
169-
const currentFunctionHasJsx = functions.pop();
170-
if (currentFunctionHasJsx) {
171-
return;
172-
}
173-
174-
if (node.type === 'ArrowFunctionExpression' && !checkArrowFunctions) {
175-
return;
176-
}
177-
178-
if (checkNode(node, scopeManager)) {
179-
return;
180-
}
181-
182-
return {
183-
node,
184-
loc: getFunctionHeadLocation(node, sourceCode),
185-
messageId: MESSAGE_ID,
186-
data: {
187-
functionNameWithKind: getFunctionNameWithKind(node, sourceCode),
188-
},
189-
};
190-
},
191-
};
162+
context.on(functionTypes, () => {
163+
functions.push(false);
164+
});
165+
166+
context.on('JSXElement', () => {
167+
// Turn off this rule if we see a JSX element because scope
168+
// references does not include JSXElement nodes.
169+
if (functions.length > 0) {
170+
functions[functions.length - 1] = true;
171+
}
172+
});
173+
174+
context.onExit(functionTypes, node => {
175+
const currentFunctionHasJsx = functions.pop();
176+
if (currentFunctionHasJsx) {
177+
return;
178+
}
179+
180+
if (node.type === 'ArrowFunctionExpression' && !checkArrowFunctions) {
181+
return;
182+
}
183+
184+
if (checkNode(node, scopeManager)) {
185+
return;
186+
}
187+
188+
return {
189+
node,
190+
loc: getFunctionHeadLocation(node, sourceCode),
191+
messageId: MESSAGE_ID,
192+
data: {
193+
functionNameWithKind: getFunctionNameWithKind(node, sourceCode),
194+
},
195+
};
196+
});
192197
};
193198

194199
const schema = [

rules/custom-error-definition.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,23 @@ const customErrorExport = (context, node) => {
183183
};
184184

185185
/** @param {import('eslint').Rule.RuleContext} context */
186-
const create = context => ({
187-
ClassDeclaration: node => customErrorDefinition(context, node),
188-
'AssignmentExpression[right.type="ClassExpression"]': node => customErrorDefinition(context, node.right),
189-
'AssignmentExpression[left.type="MemberExpression"][left.object.type="Identifier"][left.object.name="exports"]': node => customErrorExport(context, node),
190-
});
186+
const create = context => {
187+
context.on('ClassDeclaration', node => customErrorDefinition(context, node));
188+
context.on('AssignmentExpression', node => {
189+
if (node.right.type === 'ClassExpression') {
190+
return customErrorDefinition(context, node.right);
191+
}
192+
});
193+
context.on('AssignmentExpression', node => {
194+
if (
195+
node.left.type === 'MemberExpression'
196+
&& node.left.object.type === 'Identifier'
197+
&& node.left.object.name === 'exports'
198+
) {
199+
return customErrorExport(context, node);
200+
}
201+
});
202+
};
191203

192204
/** @type {import('eslint').Rule.RuleModule} */
193205
module.exports = {

rules/error-message.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ const builtinErrors = [
2626
];
2727

2828
/** @param {import('eslint').Rule.RuleContext} context */
29-
const create = context => ({
30-
'CallExpression,NewExpression'(expression) {
29+
const create = context => {
30+
context.on(['CallExpression', 'NewExpression'], expression => {
3131
if (!isCallOrNewExpression(expression, {
3232
names: builtinErrors,
3333
optional: false,
@@ -88,8 +88,8 @@ const create = context => ({
8888
messageId: MESSAGE_ID_EMPTY_MESSAGE,
8989
};
9090
}
91-
},
92-
});
91+
});
92+
};
9393

9494
/** @type {import('eslint').Rule.RuleModule} */
9595
module.exports = {

rules/escape-case.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,32 @@ const getProblem = ({node, original, regex = escapeWithLowercase, fix}) => {
2222
};
2323

2424
/** @param {import('eslint').Rule.RuleContext} context */
25-
const create = () => ({
26-
Literal(node) {
25+
const create = context => {
26+
context.on('Literal', node => {
2727
if (isStringLiteral(node)) {
2828
return getProblem({
2929
node,
3030
original: node.raw,
3131
});
3232
}
33+
});
3334

35+
context.on('Literal', node => {
3436
if (isRegexLiteral(node)) {
3537
return getProblem({
3638
node,
3739
original: node.raw,
3840
regex: escapePatternWithLowercase,
3941
});
4042
}
41-
},
42-
TemplateElement(node) {
43-
return getProblem({
44-
node,
45-
original: node.value.raw,
46-
fix: (fixer, fixed) => replaceTemplateElement(fixer, node, fixed),
47-
});
48-
},
49-
});
43+
});
44+
45+
context.on('TemplateElement', node => getProblem({
46+
node,
47+
original: node.value.raw,
48+
fix: (fixer, fixed) => replaceTemplateElement(fixer, node, fixed),
49+
}));
50+
};
5051

5152
/** @type {import('eslint').Rule.RuleModule} */
5253
module.exports = {

rules/no-array-for-each.js

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const isFunctionSelfUsedInside = require('./utils/is-function-self-used-inside.j
1616
const {isNodeMatches} = require('./utils/is-node-matches.js');
1717
const assertToken = require('./utils/assert-token.js');
1818
const {fixSpaceAroundKeyword, removeParentheses} = require('./fix/index.js');
19-
const {isArrowFunctionBody, isMethodCall, isReferenceIdentifier} = require('./ast/index.js');
19+
const {isArrowFunctionBody, isMethodCall, isReferenceIdentifier, functionTypes} = require('./ast/index.js');
2020

2121
const MESSAGE_ID_ERROR = 'no-array-for-each/error';
2222
const MESSAGE_ID_SUGGESTION = 'no-array-for-each/suggestion';
@@ -381,74 +381,81 @@ const create = context => {
381381
const functionInfo = new Map();
382382
const {sourceCode} = context;
383383

384-
return {
385-
':function'(node) {
386-
functionStack.push(node);
387-
functionInfo.set(node, {
388-
returnStatements: [],
389-
scope: sourceCode.getScope(node),
390-
});
391-
},
392-
':function:exit'() {
393-
functionStack.pop();
394-
},
395-
Identifier(node) {
396-
if (isReferenceIdentifier(node)) {
397-
allIdentifiers.push(node);
398-
}
399-
},
400-
':function ReturnStatement'(node) {
401-
const currentFunction = functionStack[functionStack.length - 1];
402-
const {returnStatements} = functionInfo.get(currentFunction);
403-
returnStatements.push(node);
404-
},
405-
CallExpression(node) {
406-
if (
407-
!isMethodCall(node, {
408-
method: 'forEach',
409-
})
410-
|| isNodeMatches(node.callee.object, ignoredObjects)
411-
) {
412-
return;
413-
}
384+
context.on(functionTypes, node => {
385+
functionStack.push(node);
386+
functionInfo.set(node, {
387+
returnStatements: [],
388+
scope: sourceCode.getScope(node),
389+
});
390+
});
414391

415-
callExpressions.push({
416-
node,
417-
scope: sourceCode.getScope(node),
418-
});
419-
},
420-
* 'Program:exit'() {
421-
for (const {node, scope} of callExpressions) {
422-
const iterable = node.callee;
423-
424-
const problem = {
425-
node: iterable.property,
426-
messageId: MESSAGE_ID_ERROR,
427-
};
428-
429-
if (!isFixable(node, {scope, allIdentifiers, functionInfo, sourceCode})) {
430-
yield problem;
431-
continue;
432-
}
433-
434-
const shouldUseSuggestion = iterable.optional && hasSideEffect(iterable, sourceCode);
435-
const fix = getFixFunction(node, functionInfo, context);
436-
437-
if (shouldUseSuggestion) {
438-
problem.suggest = [
439-
{
440-
messageId: MESSAGE_ID_SUGGESTION,
441-
fix,
442-
},
443-
];
444-
} else {
445-
problem.fix = fix;
446-
}
392+
context.onExit(functionTypes, () => {
393+
functionStack.pop();
394+
});
395+
396+
context.on('Identifier', node => {
397+
if (isReferenceIdentifier(node)) {
398+
allIdentifiers.push(node);
399+
}
400+
});
401+
402+
context.on('ReturnStatement', node => {
403+
const currentFunction = functionStack[functionStack.length - 1];
404+
if (!currentFunction) {
405+
return;
406+
}
447407

408+
const {returnStatements} = functionInfo.get(currentFunction);
409+
returnStatements.push(node);
410+
});
411+
412+
context.on('CallExpression', node => {
413+
if (
414+
!isMethodCall(node, {
415+
method: 'forEach',
416+
})
417+
|| isNodeMatches(node.callee.object, ignoredObjects)
418+
) {
419+
return;
420+
}
421+
422+
callExpressions.push({
423+
node,
424+
scope: sourceCode.getScope(node),
425+
});
426+
});
427+
428+
context.onExit('Program', function * () {
429+
for (const {node, scope} of callExpressions) {
430+
const iterable = node.callee;
431+
432+
const problem = {
433+
node: iterable.property,
434+
messageId: MESSAGE_ID_ERROR,
435+
};
436+
437+
if (!isFixable(node, {scope, allIdentifiers, functionInfo, sourceCode})) {
448438
yield problem;
439+
continue;
449440
}
450-
},
451-
};
441+
442+
const shouldUseSuggestion = iterable.optional && hasSideEffect(iterable, sourceCode);
443+
const fix = getFixFunction(node, functionInfo, context);
444+
445+
if (shouldUseSuggestion) {
446+
problem.suggest = [
447+
{
448+
messageId: MESSAGE_ID_SUGGESTION,
449+
fix,
450+
},
451+
];
452+
} else {
453+
problem.fix = fix;
454+
}
455+
456+
yield problem;
457+
}
458+
});
452459
};
453460

454461
/** @type {import('eslint').Rule.RuleModule} */

0 commit comments

Comments
 (0)