Skip to content

Commit eb97068

Browse files
authored
Make GlobalReferenceTracker easier to use (#2768)
1 parent 7aeabab commit eb97068

File tree

5 files changed

+41
-45
lines changed

5 files changed

+41
-45
lines changed

rules/new-for-builtins.js

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const messages = {
1616
[MESSAGE_ID_SUGGESTION_DATE]: 'Switch to `String(new Date())`.',
1717
};
1818

19-
function enforceNewExpression({node, path: [name]}, sourceCode) {
19+
function enforceNewExpression({node, path: [name]}, {sourceCode}) {
2020
if (name === 'Object') {
2121
const {parent} = node;
2222
if (
@@ -63,7 +63,7 @@ function enforceNewExpression({node, path: [name]}, sourceCode) {
6363
};
6464
}
6565

66-
function enforceCallExpression({node, path: [name]}, sourceCode) {
66+
function enforceCallExpression({node, path: [name]}, {sourceCode}) {
6767
const problem = {
6868
node,
6969
messageId: 'disallow',
@@ -79,28 +79,21 @@ function enforceCallExpression({node, path: [name]}, sourceCode) {
7979
return problem;
8080
}
8181

82+
const newExpressionTracker = new GlobalReferenceTracker({
83+
objects: builtins.disallowNew,
84+
type: GlobalReferenceTracker.CONSTRUCT,
85+
handle: enforceCallExpression,
86+
});
87+
const callExpressionTracker = new GlobalReferenceTracker({
88+
objects: builtins.enforceNew,
89+
type: GlobalReferenceTracker.CALL,
90+
handle: enforceNewExpression,
91+
});
92+
8293
/** @param {import('eslint').Rule.RuleContext} context */
8394
const create = context => {
84-
const {sourceCode} = context;
85-
const newExpressionTracker = new GlobalReferenceTracker({
86-
objects: builtins.disallowNew,
87-
type: GlobalReferenceTracker.CONSTRUCT,
88-
handle: reference => enforceCallExpression(reference, sourceCode),
89-
});
90-
const callExpressionTracker = new GlobalReferenceTracker({
91-
objects: builtins.enforceNew,
92-
type: GlobalReferenceTracker.CALL,
93-
handle: reference => enforceNewExpression(reference, sourceCode),
94-
});
95-
96-
return {
97-
* 'Program:exit'(program) {
98-
const scope = sourceCode.getScope(program);
99-
100-
yield * newExpressionTracker.track(scope);
101-
yield * callExpressionTracker.track(scope);
102-
},
103-
};
95+
newExpressionTracker.listen({context});
96+
callExpressionTracker.listen({context});
10497
};
10598

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

rules/no-document-cookie.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const tracker = new GlobalReferenceTracker({
1313

1414
/** @type {import('eslint').Rule.RuleModule} */
1515
const config = {
16-
create: context => tracker.createListeners(context),
16+
create: context => tracker.listen({context}),
1717
meta: {
1818
type: 'problem',
1919
docs: {

rules/prefer-number-properties.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const isNegative = node => {
2626
return parent.type === 'UnaryExpression' && parent.operator === '-' && parent.argument === node;
2727
};
2828

29-
function checkProperty({node, path: [name]}, sourceCode) {
29+
function checkProperty({node, path: [name]}, {sourceCode}) {
3030
const {parent} = node;
3131

3232
let property = name;
@@ -81,7 +81,6 @@ const create = context => {
8181
checkNaN: true,
8282
...context.options[0],
8383
};
84-
const {sourceCode} = context;
8584

8685
const objects = Object.keys(globalObjects).filter(name => {
8786
if (!checkInfinity && name === 'Infinity') {
@@ -95,13 +94,12 @@ const create = context => {
9594
return true;
9695
});
9796

98-
const tracker = new GlobalReferenceTracker({
97+
new GlobalReferenceTracker({
9998
objects,
100-
handle: reference => checkProperty(reference, sourceCode),
99+
context,
100+
handle: checkProperty,
101101
filter: ({node}) => !isLeftHandSide(node),
102-
});
103-
104-
return tracker.createListeners(context);
102+
}).listen();
105103
};
106104

107105
const schema = [

rules/prefer-prototype-methods.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function create(context) {
125125
callExpressions.push(callExpression);
126126
});
127127

128-
context.on('Program:exit', function * (program) {
128+
context.onExit('Program', function * (program) {
129129
const globalReferences = new WeakMap();
130130

131131
const tracker = new ReferenceTracker(sourceCode.getScope(program));

rules/utils/global-reference-tracker.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,55 @@ const createTraceMap = (object, type) => {
1313

1414
export class GlobalReferenceTracker {
1515
#traceMap = {};
16+
#context;
1617
#filter;
1718
#handle;
1819

1920
constructor({
2021
object,
2122
objects = [object],
23+
type = ReferenceTracker.READ,
24+
25+
context,
2226
filter,
2327
handle,
24-
type = ReferenceTracker.READ,
2528
}) {
2629
for (const object of objects) {
2730
Object.assign(this.#traceMap, createTraceMap(object, type));
2831
}
2932

33+
this.#context = context;
3034
this.#filter = filter;
3135
this.#handle = handle;
3236
}
3337

34-
* track(globalScope) {
38+
* #track(globalScope, options) {
39+
const context = options?.context ?? this.#context;
40+
const filter = options?.filter ?? this.#filter;
41+
const handle = options?.handle ?? this.#handle;
3542
const tracker = new ReferenceTracker(globalScope);
3643

3744
for (const reference of tracker.iterateGlobalReferences(this.#traceMap)) {
38-
if (this.#filter && !this.#filter(reference)) {
45+
if (filter && !filter(reference)) {
3946
continue;
4047
}
4148

42-
const problems = this.#handle(reference);
43-
44-
if (!problems) {
45-
continue;
46-
}
49+
const problems = handle(reference, context);
4750

48-
if (problems[Symbol.iterator]) {
51+
if (problems?.[Symbol.iterator]) {
4952
yield * problems;
50-
} else {
53+
} else if (problems) {
5154
yield problems;
5255
}
5356
}
5457
}
5558

56-
createListeners(context) {
57-
return {
58-
'Program:exit': program => this.track(context.sourceCode.getScope(program)),
59-
};
59+
listen(options) {
60+
const context = options?.context ?? this.#context;
61+
context.onExit(
62+
'Program',
63+
program => this.#track(context.sourceCode.getScope(program), options),
64+
);
6065
}
6166
}
6267

0 commit comments

Comments
 (0)