Skip to content

Commit f125ee3

Browse files
committed
feat(linter): merge visitors when using multiple custom JS rules (#12387)
1 parent 144e284 commit f125ee3

File tree

6 files changed

+123
-2
lines changed

6 files changed

+123
-2
lines changed

napi/oxlint2/src/index.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ class Linter {
125125
visitors.push(rule.create(createContext(ruleId)));
126126
}
127127

128-
// TODO: Combine visitors for multiple rules
129-
const visitor = new Visitor(visitors[0]);
128+
const visitor = new Visitor(
129+
visitors.length === 1 ? visitors[0] : combineVisitors(visitors),
130+
);
130131

131132
// Visit AST
132133
const programPos = buffer.uint32[DATA_POINTER_POS_32],
@@ -143,6 +144,25 @@ class Linter {
143144
}
144145
}
145146

147+
function combineVisitors(visitors) {
148+
const combinedVisitor = {};
149+
for (const visitor of visitors) {
150+
for (const nodeType of Object.keys(visitor)) {
151+
if (!(nodeType in combinedVisitor)) {
152+
combinedVisitor[nodeType] = function(node) {
153+
for (const v of visitors) {
154+
if (typeof v[nodeType] === 'function') {
155+
v[nodeType](node);
156+
}
157+
}
158+
};
159+
}
160+
}
161+
}
162+
163+
return combinedVisitor;
164+
}
165+
146166
async function main() {
147167
const linter = new Linter();
148168

napi/oxlint2/test/__snapshots__/e2e.test.ts.snap

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,38 @@ exports[`oxlint2 CLI > should report the correct severity when using a custom pl
355355
Found 2 warnings and 0 errors.
356356
Finished in Xms on 1 file using X threads."
357357
`;
358+
359+
exports[`oxlint2 CLI > should work with multiple rules 1`] = `
360+
"
361+
! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\\eslint(no-debugger)]8;;\\: \`debugger\` statement is not allowed
362+
,-[index.js:1:1]
363+
1 | debugger;
364+
: ^^^^^^^^^
365+
2 |
366+
\`----
367+
help: Remove the debugger statement
368+
369+
x basic-custom-plugin(no-debugger): Unexpected Debugger Statement
370+
,-[index.js:1:1]
371+
1 | debugger;
372+
: ^^^^^^^^^
373+
2 |
374+
\`----
375+
376+
x basic-custom-plugin(no-debugger-2): Unexpected Debugger Statement
377+
,-[index.js:1:1]
378+
1 | debugger;
379+
: ^^^^^^^^^
380+
2 |
381+
\`----
382+
383+
x basic-custom-plugin(no-ident-references-named-foo): Unexpected Identifier Reference named foo
384+
,-[index.js:3:1]
385+
2 |
386+
3 | foo;
387+
: ^^^
388+
\`----
389+
390+
Found 1 warning and 3 errors.
391+
Finished in Xms on 1 file using X threads."
392+
`;

napi/oxlint2/test/e2e.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,13 @@ describe('oxlint2 CLI', () => {
9292
expect(exitCode).toBe(0);
9393
expect(normalizeOutput(stdout)).toMatchSnapshot();
9494
});
95+
96+
it('should work with multiple rules', async () => {
97+
const { stdout, exitCode } = await runOxlint(
98+
'test/fixtures/basic_custom_plugin_multiple_rules',
99+
);
100+
101+
expect(exitCode).toBe(1);
102+
expect(normalizeOutput(stdout)).toMatchSnapshot();
103+
});
95104
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"plugins": ["./test_plugin"],
3+
"rules": {
4+
"basic-custom-plugin/no-debugger": "error",
5+
"basic-custom-plugin/no-debugger-2": "error",
6+
"basic-custom-plugin/no-ident-references-named-foo": "error"
7+
},
8+
"ignorePatterns": ["test_plugin"]
9+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
debugger;
2+
3+
foo;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
export default {
2+
meta: {
3+
name: "basic-custom-plugin",
4+
},
5+
rules: {
6+
"no-debugger": {
7+
create(context) {
8+
return {
9+
DebuggerStatement(debuggerStatement) {
10+
context.report({
11+
message: "Unexpected Debugger Statement",
12+
node: debuggerStatement,
13+
});
14+
},
15+
};
16+
},
17+
},
18+
"no-debugger-2": {
19+
create(context) {
20+
return {
21+
DebuggerStatement(debuggerStatement) {
22+
context.report({
23+
message: "Unexpected Debugger Statement",
24+
node: debuggerStatement,
25+
});
26+
},
27+
};
28+
},
29+
},
30+
"no-ident-references-named-foo": {
31+
create(context) {
32+
return {
33+
IdentifierReference(identifierReference) {
34+
if (identifierReference.name == "foo") {
35+
context.report({
36+
message: "Unexpected Identifier Reference named foo",
37+
node: identifierReference,
38+
});
39+
}
40+
},
41+
};
42+
},
43+
},
44+
},
45+
};

0 commit comments

Comments
 (0)