Skip to content

Commit c8de6fe

Browse files
committed
feat(linter/plugins): add parent field to AST nodes (#14345)
Use the new raw transfer deserializer added in #14344 to add `parent` field to all AST node in Oxlint JS plugins.
1 parent 7e4d04f commit c8de6fe

File tree

10 files changed

+872
-197
lines changed

10 files changed

+872
-197
lines changed

.github/generated/ast_changes_watch_list.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ src:
7474
- 'napi/parser/generated/deserialize/ts.js'
7575
- 'napi/parser/generated/deserialize/ts_parent.js'
7676
- 'napi/parser/generated/deserialize/ts_range.js'
77-
- 'napi/parser/generated/deserialize/ts_range_no_parens.js'
7877
- 'napi/parser/generated/deserialize/ts_range_parent.js'
78+
- 'napi/parser/generated/deserialize/ts_range_parent_no_parens.js'
7979
- 'napi/parser/generated/lazy/constructors.js'
8080
- 'napi/parser/generated/lazy/types.js'
8181
- 'napi/parser/generated/lazy/walk.js'

apps/oxlint/scripts/build.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const parserFilePaths = [
3232
'generated/lazy/types.js',
3333
'generated/lazy/walk.js',
3434
*/
35-
'generated/deserialize/ts_range_no_parens.js',
35+
'generated/deserialize/ts_range_parent_no_parens.js',
3636
'generated/visit/keys.js',
3737
'generated/visit/types.js',
3838
'generated/visit/visitor.d.ts',

apps/oxlint/src-js/plugins/source_code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from '../generated/constants.js';
88
// @ts-expect-error we need to generate `.d.ts` file for this module
99
// We use the deserializer which removes `ParenthesizedExpression`s from AST to match ESLint
10-
import { deserializeProgramOnly } from '../../dist/generated/deserialize/ts_range_no_parens.js';
10+
import { deserializeProgramOnly } from '../../dist/generated/deserialize/ts_range_parent_no_parens.js';
1111

1212
import type { Program } from '@oxc-project/types';
1313
import type { Scope, ScopeManager, Variable } from './scope.ts';

apps/oxlint/test/e2e.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ describe('oxlint CLI', () => {
123123
await testFixture('estree');
124124
});
125125

126+
it('should receive AST with all nodes having `parent` property', async () => {
127+
await testFixture('parent');
128+
});
129+
126130
it('should receive data via `context`', async () => {
127131
await testFixture('context_properties');
128132
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"jsPlugins": ["./plugin.ts"],
3+
"categories": {
4+
"correctness": "off"
5+
},
6+
"rules": {
7+
"parents/check": "error"
8+
}
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const obj = { a: [b, c], ...d };
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Exit code
2+
1
3+
4+
# stdout
5+
```
6+
x parents(check): VariableDeclaration -> Program
7+
,-[files/index.js:1:1]
8+
1 | const obj = { a: [b, c], ...d };
9+
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
`----
11+
12+
x parents(check): Program -> null
13+
,-[files/index.js:1:1]
14+
1 | const obj = { a: [b, c], ...d };
15+
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
`----
17+
18+
x parents(check): Identifier -> VariableDeclarator
19+
,-[files/index.js:1:7]
20+
1 | const obj = { a: [b, c], ...d };
21+
: ^^^
22+
`----
23+
24+
x parents(check): VariableDeclarator -> VariableDeclaration
25+
,-[files/index.js:1:7]
26+
1 | const obj = { a: [b, c], ...d };
27+
: ^^^^^^^^^^^^^^^^^^^^^^^^^
28+
`----
29+
30+
x parents(check): ObjectExpression -> VariableDeclarator
31+
,-[files/index.js:1:13]
32+
1 | const obj = { a: [b, c], ...d };
33+
: ^^^^^^^^^^^^^^^^^^^
34+
`----
35+
36+
x parents(check): Identifier -> Property
37+
,-[files/index.js:1:15]
38+
1 | const obj = { a: [b, c], ...d };
39+
: ^
40+
`----
41+
42+
x parents(check): Property -> ObjectExpression
43+
,-[files/index.js:1:15]
44+
1 | const obj = { a: [b, c], ...d };
45+
: ^^^^^^^^^
46+
`----
47+
48+
x parents(check): ArrayExpression -> Property
49+
,-[files/index.js:1:18]
50+
1 | const obj = { a: [b, c], ...d };
51+
: ^^^^^^
52+
`----
53+
54+
x parents(check): Identifier -> ArrayExpression
55+
,-[files/index.js:1:19]
56+
1 | const obj = { a: [b, c], ...d };
57+
: ^
58+
`----
59+
60+
x parents(check): Identifier -> ArrayExpression
61+
,-[files/index.js:1:22]
62+
1 | const obj = { a: [b, c], ...d };
63+
: ^
64+
`----
65+
66+
x parents(check): SpreadElement -> ObjectExpression
67+
,-[files/index.js:1:26]
68+
1 | const obj = { a: [b, c], ...d };
69+
: ^^^^
70+
`----
71+
72+
x parents(check): Identifier -> SpreadElement
73+
,-[files/index.js:1:29]
74+
1 | const obj = { a: [b, c], ...d };
75+
: ^
76+
`----
77+
78+
Found 0 warnings and 12 errors.
79+
Finished in Xms on 1 file using X threads.
80+
```
81+
82+
# stderr
83+
```
84+
WARNING: JS plugins are experimental and not subject to semver.
85+
Breaking changes are possible while JS plugins support is under development.
86+
```
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Plugin } from '../../../dist/index.js';
2+
3+
const plugin: Plugin = {
4+
meta: {
5+
name: 'parents',
6+
},
7+
rules: {
8+
check: {
9+
create(context) {
10+
return {
11+
Program(node) {
12+
context.report({ message: `${node.type} -> ${node.parent}`, node });
13+
},
14+
VariableDeclaration(node) {
15+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
16+
},
17+
VariableDeclarator(node) {
18+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
19+
},
20+
Identifier(node) {
21+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
22+
},
23+
ObjectExpression(node) {
24+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
25+
},
26+
Property(node) {
27+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
28+
},
29+
ArrayExpression(node) {
30+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
31+
},
32+
SpreadElement(node) {
33+
context.report({ message: `${node.type} -> ${node.parent.type}`, node });
34+
},
35+
};
36+
},
37+
},
38+
},
39+
};
40+
41+
export default plugin;

0 commit comments

Comments
 (0)