@prisma-next/psl-parser 0.14.0-dev.4 → 0.14.0-dev.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -10
- package/dist/declarations-CPDuQm7x.mjs +1055 -0
- package/dist/declarations-CPDuQm7x.mjs.map +1 -0
- package/dist/format.d.mts +1 -1
- package/dist/format.mjs +2 -1
- package/dist/format.mjs.map +1 -1
- package/dist/index.d.mts +137 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +474 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{parse-BjZ1LPe6.d.mts → parse-BKN_-hW8.d.mts} +126 -51
- package/dist/parse-BKN_-hW8.d.mts.map +1 -0
- package/dist/parse-Du30Ca0-.mjs +626 -0
- package/dist/parse-Du30Ca0-.mjs.map +1 -0
- package/dist/syntax.d.mts +20 -2
- package/dist/syntax.d.mts.map +1 -1
- package/dist/syntax.mjs +43 -2
- package/dist/syntax.mjs.map +1 -0
- package/package.json +5 -6
- package/src/block-reconstruction.ts +139 -0
- package/src/exports/index.ts +27 -3
- package/src/exports/syntax.ts +25 -5
- package/src/extension-block.ts +107 -0
- package/src/parse.ts +23 -5
- package/src/resolve.ts +123 -0
- package/src/source-file.ts +25 -0
- package/src/symbol-table.ts +446 -0
- package/src/syntax/ast/attributes.ts +5 -6
- package/src/syntax/ast/declarations.ts +51 -26
- package/src/syntax/ast/expressions.ts +12 -13
- package/src/syntax/ast/identifier.ts +2 -3
- package/src/syntax/ast/qualified-name.ts +22 -19
- package/src/syntax/ast/type-annotation.ts +4 -5
- package/src/syntax/ast-helpers.ts +27 -3
- package/src/syntax/navigation.ts +55 -0
- package/src/syntax/red.ts +317 -42
- package/dist/parse-B_3gIEFd.mjs +0 -1421
- package/dist/parse-B_3gIEFd.mjs.map +0 -1
- package/dist/parse-BjZ1LPe6.d.mts.map +0 -1
- package/dist/parser-CaplKvRs.mjs +0 -1145
- package/dist/parser-CaplKvRs.mjs.map +0 -1
- package/dist/parser-Dfi3Wfdq.d.mts +0 -7
- package/dist/parser-Dfi3Wfdq.d.mts.map +0 -1
- package/dist/parser.d.mts +0 -2
- package/dist/parser.mjs +0 -2
- package/src/exports/parser.ts +0 -1
- package/src/parser.ts +0 -1642
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { AstNode } from '../ast-helpers';
|
|
1
|
+
import type { AstNode, BracedBlock } from '../ast-helpers';
|
|
3
2
|
import { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';
|
|
4
|
-
import { SyntaxNode } from '../red';
|
|
3
|
+
import { SyntaxNode, type SyntaxToken } from '../red';
|
|
5
4
|
import { FieldAttributeAst, ModelAttributeAst } from './attributes';
|
|
6
5
|
import type { ExpressionAst } from './expressions';
|
|
7
6
|
import { castExpression } from './expressions';
|
|
@@ -18,6 +17,11 @@ export type NamespaceMemberAst =
|
|
|
18
17
|
| CompositeTypeDeclarationAst
|
|
19
18
|
| GenericBlockDeclarationAst;
|
|
20
19
|
|
|
20
|
+
export type DeclarationAst = NamespaceMemberAst | TypesBlockAst | NamespaceDeclarationAst;
|
|
21
|
+
export type AttributeAst = FieldAttributeAst | ModelAttributeAst;
|
|
22
|
+
export type BlockMemberAst = FieldDeclarationAst | ModelAttributeAst;
|
|
23
|
+
export type GenericBlockMemberAst = KeyValuePairAst | ModelAttributeAst;
|
|
24
|
+
|
|
21
25
|
function castNamespaceMember(node: SyntaxNode): NamespaceMemberAst | undefined {
|
|
22
26
|
return (
|
|
23
27
|
ModelDeclarationAst.cast(node) ??
|
|
@@ -33,7 +37,7 @@ export class DocumentAst implements AstNode {
|
|
|
33
37
|
this.syntax = syntax;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
*declarations(): Iterable<
|
|
40
|
+
*declarations(): Iterable<DeclarationAst> {
|
|
37
41
|
yield* filterChildren(
|
|
38
42
|
this.syntax,
|
|
39
43
|
(node) =>
|
|
@@ -46,14 +50,14 @@ export class DocumentAst implements AstNode {
|
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
export class ModelDeclarationAst implements
|
|
53
|
+
export class ModelDeclarationAst implements BracedBlock {
|
|
50
54
|
readonly syntax: SyntaxNode;
|
|
51
55
|
|
|
52
56
|
constructor(syntax: SyntaxNode) {
|
|
53
57
|
this.syntax = syntax;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
keyword():
|
|
60
|
+
keyword(): SyntaxToken | undefined {
|
|
57
61
|
return findChildToken(this.syntax, 'Ident');
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -61,11 +65,11 @@ export class ModelDeclarationAst implements AstNode {
|
|
|
61
65
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
lbrace():
|
|
68
|
+
lbrace(): SyntaxToken | undefined {
|
|
65
69
|
return findChildToken(this.syntax, 'LBrace');
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
rbrace():
|
|
72
|
+
rbrace(): SyntaxToken | undefined {
|
|
69
73
|
return findChildToken(this.syntax, 'RBrace');
|
|
70
74
|
}
|
|
71
75
|
|
|
@@ -77,19 +81,26 @@ export class ModelDeclarationAst implements AstNode {
|
|
|
77
81
|
yield* filterChildren(this.syntax, ModelAttributeAst.cast);
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
*members(): Iterable<BlockMemberAst> {
|
|
85
|
+
yield* filterChildren(
|
|
86
|
+
this.syntax,
|
|
87
|
+
(node) => FieldDeclarationAst.cast(node) ?? ModelAttributeAst.cast(node),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
80
91
|
static cast(node: SyntaxNode): ModelDeclarationAst | undefined {
|
|
81
92
|
return node.kind === 'ModelDeclaration' ? new ModelDeclarationAst(node) : undefined;
|
|
82
93
|
}
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
export class CompositeTypeDeclarationAst implements
|
|
96
|
+
export class CompositeTypeDeclarationAst implements BracedBlock {
|
|
86
97
|
readonly syntax: SyntaxNode;
|
|
87
98
|
|
|
88
99
|
constructor(syntax: SyntaxNode) {
|
|
89
100
|
this.syntax = syntax;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
|
-
keyword():
|
|
103
|
+
keyword(): SyntaxToken | undefined {
|
|
93
104
|
return findChildToken(this.syntax, 'Ident');
|
|
94
105
|
}
|
|
95
106
|
|
|
@@ -97,11 +108,11 @@ export class CompositeTypeDeclarationAst implements AstNode {
|
|
|
97
108
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
98
109
|
}
|
|
99
110
|
|
|
100
|
-
lbrace():
|
|
111
|
+
lbrace(): SyntaxToken | undefined {
|
|
101
112
|
return findChildToken(this.syntax, 'LBrace');
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
rbrace():
|
|
115
|
+
rbrace(): SyntaxToken | undefined {
|
|
105
116
|
return findChildToken(this.syntax, 'RBrace');
|
|
106
117
|
}
|
|
107
118
|
|
|
@@ -113,6 +124,13 @@ export class CompositeTypeDeclarationAst implements AstNode {
|
|
|
113
124
|
yield* filterChildren(this.syntax, ModelAttributeAst.cast);
|
|
114
125
|
}
|
|
115
126
|
|
|
127
|
+
*members(): Iterable<BlockMemberAst> {
|
|
128
|
+
yield* filterChildren(
|
|
129
|
+
this.syntax,
|
|
130
|
+
(node) => FieldDeclarationAst.cast(node) ?? ModelAttributeAst.cast(node),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
116
134
|
static cast(node: SyntaxNode): CompositeTypeDeclarationAst | undefined {
|
|
117
135
|
return node.kind === 'CompositeTypeDeclaration'
|
|
118
136
|
? new CompositeTypeDeclarationAst(node)
|
|
@@ -120,14 +138,14 @@ export class CompositeTypeDeclarationAst implements AstNode {
|
|
|
120
138
|
}
|
|
121
139
|
}
|
|
122
140
|
|
|
123
|
-
export class NamespaceDeclarationAst implements
|
|
141
|
+
export class NamespaceDeclarationAst implements BracedBlock {
|
|
124
142
|
readonly syntax: SyntaxNode;
|
|
125
143
|
|
|
126
144
|
constructor(syntax: SyntaxNode) {
|
|
127
145
|
this.syntax = syntax;
|
|
128
146
|
}
|
|
129
147
|
|
|
130
|
-
keyword():
|
|
148
|
+
keyword(): SyntaxToken | undefined {
|
|
131
149
|
return findChildToken(this.syntax, 'Ident');
|
|
132
150
|
}
|
|
133
151
|
|
|
@@ -135,11 +153,11 @@ export class NamespaceDeclarationAst implements AstNode {
|
|
|
135
153
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
lbrace():
|
|
156
|
+
lbrace(): SyntaxToken | undefined {
|
|
139
157
|
return findChildToken(this.syntax, 'LBrace');
|
|
140
158
|
}
|
|
141
159
|
|
|
142
|
-
rbrace():
|
|
160
|
+
rbrace(): SyntaxToken | undefined {
|
|
143
161
|
return findChildToken(this.syntax, 'RBrace');
|
|
144
162
|
}
|
|
145
163
|
|
|
@@ -152,22 +170,22 @@ export class NamespaceDeclarationAst implements AstNode {
|
|
|
152
170
|
}
|
|
153
171
|
}
|
|
154
172
|
|
|
155
|
-
export class TypesBlockAst implements
|
|
173
|
+
export class TypesBlockAst implements BracedBlock {
|
|
156
174
|
readonly syntax: SyntaxNode;
|
|
157
175
|
|
|
158
176
|
constructor(syntax: SyntaxNode) {
|
|
159
177
|
this.syntax = syntax;
|
|
160
178
|
}
|
|
161
179
|
|
|
162
|
-
keyword():
|
|
180
|
+
keyword(): SyntaxToken | undefined {
|
|
163
181
|
return findChildToken(this.syntax, 'Ident');
|
|
164
182
|
}
|
|
165
183
|
|
|
166
|
-
lbrace():
|
|
184
|
+
lbrace(): SyntaxToken | undefined {
|
|
167
185
|
return findChildToken(this.syntax, 'LBrace');
|
|
168
186
|
}
|
|
169
187
|
|
|
170
|
-
rbrace():
|
|
188
|
+
rbrace(): SyntaxToken | undefined {
|
|
171
189
|
return findChildToken(this.syntax, 'RBrace');
|
|
172
190
|
}
|
|
173
191
|
|
|
@@ -180,14 +198,14 @@ export class TypesBlockAst implements AstNode {
|
|
|
180
198
|
}
|
|
181
199
|
}
|
|
182
200
|
|
|
183
|
-
export class GenericBlockDeclarationAst implements
|
|
201
|
+
export class GenericBlockDeclarationAst implements BracedBlock {
|
|
184
202
|
readonly syntax: SyntaxNode;
|
|
185
203
|
|
|
186
204
|
constructor(syntax: SyntaxNode) {
|
|
187
205
|
this.syntax = syntax;
|
|
188
206
|
}
|
|
189
207
|
|
|
190
|
-
keyword():
|
|
208
|
+
keyword(): SyntaxToken | undefined {
|
|
191
209
|
return findChildToken(this.syntax, 'Ident');
|
|
192
210
|
}
|
|
193
211
|
|
|
@@ -195,11 +213,11 @@ export class GenericBlockDeclarationAst implements AstNode {
|
|
|
195
213
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
196
214
|
}
|
|
197
215
|
|
|
198
|
-
lbrace():
|
|
216
|
+
lbrace(): SyntaxToken | undefined {
|
|
199
217
|
return findChildToken(this.syntax, 'LBrace');
|
|
200
218
|
}
|
|
201
219
|
|
|
202
|
-
rbrace():
|
|
220
|
+
rbrace(): SyntaxToken | undefined {
|
|
203
221
|
return findChildToken(this.syntax, 'RBrace');
|
|
204
222
|
}
|
|
205
223
|
|
|
@@ -211,6 +229,13 @@ export class GenericBlockDeclarationAst implements AstNode {
|
|
|
211
229
|
yield* filterChildren(this.syntax, ModelAttributeAst.cast);
|
|
212
230
|
}
|
|
213
231
|
|
|
232
|
+
*members(): Iterable<GenericBlockMemberAst> {
|
|
233
|
+
yield* filterChildren(
|
|
234
|
+
this.syntax,
|
|
235
|
+
(node) => KeyValuePairAst.cast(node) ?? ModelAttributeAst.cast(node),
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
214
239
|
static cast(node: SyntaxNode): GenericBlockDeclarationAst | undefined {
|
|
215
240
|
return node.kind === 'GenericBlockDeclaration'
|
|
216
241
|
? new GenericBlockDeclarationAst(node)
|
|
@@ -229,7 +254,7 @@ export class KeyValuePairAst implements AstNode {
|
|
|
229
254
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
230
255
|
}
|
|
231
256
|
|
|
232
|
-
equals():
|
|
257
|
+
equals(): SyntaxToken | undefined {
|
|
233
258
|
return findChildToken(this.syntax, 'Equals');
|
|
234
259
|
}
|
|
235
260
|
|
|
@@ -288,7 +313,7 @@ export class NamedTypeDeclarationAst implements AstNode {
|
|
|
288
313
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
289
314
|
}
|
|
290
315
|
|
|
291
|
-
equals():
|
|
316
|
+
equals(): SyntaxToken | undefined {
|
|
292
317
|
return findChildToken(this.syntax, 'Equals');
|
|
293
318
|
}
|
|
294
319
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Token } from '../../tokenizer';
|
|
2
1
|
import type { AstNode } from '../ast-helpers';
|
|
3
2
|
import { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';
|
|
4
|
-
import { SyntaxNode } from '../red';
|
|
3
|
+
import { SyntaxNode, type SyntaxToken } from '../red';
|
|
5
4
|
import { IdentifierAst } from './identifier';
|
|
6
5
|
import { QualifiedNameAst } from './qualified-name';
|
|
7
6
|
|
|
@@ -32,11 +31,11 @@ export class FunctionCallAst implements AstNode {
|
|
|
32
31
|
return segments;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
lparen():
|
|
34
|
+
lparen(): SyntaxToken | undefined {
|
|
36
35
|
return findChildToken(this.syntax, 'LParen');
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
rparen():
|
|
38
|
+
rparen(): SyntaxToken | undefined {
|
|
40
39
|
return findChildToken(this.syntax, 'RParen');
|
|
41
40
|
}
|
|
42
41
|
|
|
@@ -56,11 +55,11 @@ export class ArrayLiteralAst implements AstNode {
|
|
|
56
55
|
this.syntax = syntax;
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
lbracket():
|
|
58
|
+
lbracket(): SyntaxToken | undefined {
|
|
60
59
|
return findChildToken(this.syntax, 'LBracket');
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
rbracket():
|
|
62
|
+
rbracket(): SyntaxToken | undefined {
|
|
64
63
|
return findChildToken(this.syntax, 'RBracket');
|
|
65
64
|
}
|
|
66
65
|
|
|
@@ -156,7 +155,7 @@ export class StringLiteralExprAst implements AstNode {
|
|
|
156
155
|
this.syntax = syntax;
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
token():
|
|
158
|
+
token(): SyntaxToken | undefined {
|
|
160
159
|
return findChildToken(this.syntax, 'StringLiteral');
|
|
161
160
|
}
|
|
162
161
|
|
|
@@ -178,7 +177,7 @@ export class NumberLiteralExprAst implements AstNode {
|
|
|
178
177
|
this.syntax = syntax;
|
|
179
178
|
}
|
|
180
179
|
|
|
181
|
-
token():
|
|
180
|
+
token(): SyntaxToken | undefined {
|
|
182
181
|
return findChildToken(this.syntax, 'NumberLiteral');
|
|
183
182
|
}
|
|
184
183
|
|
|
@@ -200,7 +199,7 @@ export class BooleanLiteralExprAst implements AstNode {
|
|
|
200
199
|
this.syntax = syntax;
|
|
201
200
|
}
|
|
202
201
|
|
|
203
|
-
token():
|
|
202
|
+
token(): SyntaxToken | undefined {
|
|
204
203
|
return findChildToken(this.syntax, 'Ident');
|
|
205
204
|
}
|
|
206
205
|
|
|
@@ -224,11 +223,11 @@ export class ObjectLiteralExprAst implements AstNode {
|
|
|
224
223
|
this.syntax = syntax;
|
|
225
224
|
}
|
|
226
225
|
|
|
227
|
-
lbrace():
|
|
226
|
+
lbrace(): SyntaxToken | undefined {
|
|
228
227
|
return findChildToken(this.syntax, 'LBrace');
|
|
229
228
|
}
|
|
230
229
|
|
|
231
|
-
rbrace():
|
|
230
|
+
rbrace(): SyntaxToken | undefined {
|
|
232
231
|
return findChildToken(this.syntax, 'RBrace');
|
|
233
232
|
}
|
|
234
233
|
|
|
@@ -279,7 +278,7 @@ export class ObjectFieldAst implements AstNode {
|
|
|
279
278
|
return undefined;
|
|
280
279
|
}
|
|
281
280
|
|
|
282
|
-
colon():
|
|
281
|
+
colon(): SyntaxToken | undefined {
|
|
283
282
|
return findChildToken(this.syntax, 'Colon');
|
|
284
283
|
}
|
|
285
284
|
|
|
@@ -339,7 +338,7 @@ export class AttributeArgAst implements AstNode {
|
|
|
339
338
|
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
340
339
|
}
|
|
341
340
|
|
|
342
|
-
colon():
|
|
341
|
+
colon(): SyntaxToken | undefined {
|
|
343
342
|
return findChildToken(this.syntax, 'Colon');
|
|
344
343
|
}
|
|
345
344
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Token } from '../../tokenizer';
|
|
2
1
|
import type { AstNode } from '../ast-helpers';
|
|
3
2
|
import { findChildToken } from '../ast-helpers';
|
|
4
|
-
import type { SyntaxNode } from '../red';
|
|
3
|
+
import type { SyntaxNode, SyntaxToken } from '../red';
|
|
5
4
|
|
|
6
5
|
export class IdentifierAst implements AstNode {
|
|
7
6
|
readonly syntax: SyntaxNode;
|
|
@@ -10,7 +9,7 @@ export class IdentifierAst implements AstNode {
|
|
|
10
9
|
this.syntax = syntax;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
token():
|
|
12
|
+
token(): SyntaxToken | undefined {
|
|
14
13
|
return findChildToken(this.syntax, 'Ident');
|
|
15
14
|
}
|
|
16
15
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Token } from '../../tokenizer';
|
|
2
1
|
import type { AstNode } from '../ast-helpers';
|
|
3
2
|
import { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';
|
|
4
|
-
import { SyntaxNode } from '../red';
|
|
3
|
+
import { SyntaxNode, type SyntaxToken } from '../red';
|
|
5
4
|
import { IdentifierAst } from './identifier';
|
|
6
5
|
|
|
7
6
|
/** A namespace-qualified name, e.g. `pgvector.Vector` or `supabase:auth.User`. */
|
|
@@ -12,22 +11,20 @@ export class QualifiedNameAst implements AstNode {
|
|
|
12
11
|
this.syntax = syntax;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
#
|
|
16
|
-
let
|
|
14
|
+
#segmentBefore(boundary: number): IdentifierAst | undefined {
|
|
15
|
+
let found: IdentifierAst | undefined;
|
|
17
16
|
for (const segment of filterChildren(this.syntax, IdentifierAst.cast)) {
|
|
18
|
-
|
|
17
|
+
if (segment.syntax.offset >= boundary) break;
|
|
18
|
+
found = segment;
|
|
19
19
|
}
|
|
20
|
-
return
|
|
20
|
+
return found;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
#
|
|
24
|
-
let last: IdentifierAst | undefined;
|
|
25
|
-
let penultimate: IdentifierAst | undefined;
|
|
23
|
+
#segmentAfter(boundary: number): IdentifierAst | undefined {
|
|
26
24
|
for (const segment of filterChildren(this.syntax, IdentifierAst.cast)) {
|
|
27
|
-
|
|
28
|
-
last = segment;
|
|
25
|
+
if (segment.syntax.offset > boundary) return segment;
|
|
29
26
|
}
|
|
30
|
-
return
|
|
27
|
+
return undefined;
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
#separatorCount(kind: 'Dot' | 'Colon'): number {
|
|
@@ -38,26 +35,32 @@ export class QualifiedNameAst implements AstNode {
|
|
|
38
35
|
return count;
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
colon():
|
|
38
|
+
colon(): SyntaxToken | undefined {
|
|
42
39
|
return findChildToken(this.syntax, 'Colon');
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
dot():
|
|
42
|
+
dot(): SyntaxToken | undefined {
|
|
46
43
|
return findChildToken(this.syntax, 'Dot');
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
space(): IdentifierAst | undefined {
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const colon = this.colon();
|
|
48
|
+
if (!colon) return undefined;
|
|
49
|
+
return this.#segmentBefore(colon.offset);
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
namespace(): IdentifierAst | undefined {
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const dot = this.dot();
|
|
54
|
+
if (!dot) return undefined;
|
|
55
|
+
return this.#segmentBefore(dot.offset);
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
identifier(): IdentifierAst | undefined {
|
|
60
|
-
|
|
59
|
+
const dot = this.dot();
|
|
60
|
+
if (dot) return this.#segmentAfter(dot.offset);
|
|
61
|
+
const colon = this.colon();
|
|
62
|
+
if (colon) return this.#segmentAfter(colon.offset);
|
|
63
|
+
return findFirstChild(this.syntax, IdentifierAst.cast);
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Token } from '../../tokenizer';
|
|
2
1
|
import type { AstNode } from '../ast-helpers';
|
|
3
2
|
import { findChildToken, findFirstChild } from '../ast-helpers';
|
|
4
|
-
import type { SyntaxNode } from '../red';
|
|
3
|
+
import type { SyntaxNode, SyntaxToken } from '../red';
|
|
5
4
|
import { AttributeArgListAst } from './attributes';
|
|
6
5
|
import { QualifiedNameAst } from './qualified-name';
|
|
7
6
|
|
|
@@ -26,15 +25,15 @@ export class TypeAnnotationAst implements AstNode {
|
|
|
26
25
|
return this.argList() !== undefined;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
lbracket():
|
|
28
|
+
lbracket(): SyntaxToken | undefined {
|
|
30
29
|
return findChildToken(this.syntax, 'LBracket');
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
rbracket():
|
|
32
|
+
rbracket(): SyntaxToken | undefined {
|
|
34
33
|
return findChildToken(this.syntax, 'RBracket');
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
questionMark():
|
|
36
|
+
questionMark(): SyntaxToken | undefined {
|
|
38
37
|
return findChildToken(this.syntax, 'Question');
|
|
39
38
|
}
|
|
40
39
|
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { SyntaxNode } from './red';
|
|
1
|
+
import type { TokenKind } from '../tokenizer';
|
|
2
|
+
import { SyntaxNode, type SyntaxToken } from './red';
|
|
3
3
|
|
|
4
4
|
export interface AstNode {
|
|
5
5
|
readonly syntax: SyntaxNode;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export interface BracedBlock extends AstNode {
|
|
9
|
+
lbrace(): SyntaxToken | undefined;
|
|
10
|
+
rbrace(): SyntaxToken | undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function findChildToken(node: SyntaxNode, kind: TokenKind): SyntaxToken | undefined {
|
|
9
14
|
for (const child of node.children()) {
|
|
10
15
|
if (!(child instanceof SyntaxNode) && child.kind === kind) {
|
|
11
16
|
return child;
|
|
@@ -35,6 +40,25 @@ export function* filterChildren<T>(
|
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
|
|
43
|
+
type CastTarget<C> = C extends (node: SyntaxNode) => infer R ? Exclude<R, undefined> : never;
|
|
44
|
+
|
|
45
|
+
export function any<Casts extends readonly ((node: SyntaxNode) => unknown)[]>(
|
|
46
|
+
...casts: Casts
|
|
47
|
+
): (node: SyntaxNode) => CastTarget<Casts[number]> | undefined;
|
|
48
|
+
export function any(
|
|
49
|
+
...casts: ReadonlyArray<(node: SyntaxNode) => unknown>
|
|
50
|
+
): (node: SyntaxNode) => unknown {
|
|
51
|
+
return (node) => {
|
|
52
|
+
for (const cast of casts) {
|
|
53
|
+
const result = cast(node);
|
|
54
|
+
if (result !== undefined) {
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
38
62
|
/**
|
|
39
63
|
* Raw source text of a CST node, verbatim (quotes and brackets preserved). For
|
|
40
64
|
* the decoded value of a string literal, decode it instead.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { TokenKind } from '../tokenizer';
|
|
2
|
+
import { type SyntaxElement, SyntaxToken } from './red';
|
|
3
|
+
|
|
4
|
+
/** Direction of a sibling/token walk. */
|
|
5
|
+
export type Direction = 'next' | 'prev';
|
|
6
|
+
|
|
7
|
+
const TRIVIA_KINDS: ReadonlySet<TokenKind> = new Set<TokenKind>([
|
|
8
|
+
'Whitespace',
|
|
9
|
+
'Newline',
|
|
10
|
+
'Comment',
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
/** Whether a token kind is trivia (whitespace, newline, or comment). */
|
|
14
|
+
export function isTriviaKind(kind: TokenKind): boolean {
|
|
15
|
+
return TRIVIA_KINDS.has(kind);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Whether a token is trivia. */
|
|
19
|
+
export function isTrivia(token: SyntaxToken): boolean {
|
|
20
|
+
return isTriviaKind(token.kind);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The first non-trivia token at or beyond `token` in `direction`. Returns
|
|
25
|
+
* `token` itself when it is already significant.
|
|
26
|
+
*/
|
|
27
|
+
export function skipTriviaToken(token: SyntaxToken, direction: Direction): SyntaxToken | undefined {
|
|
28
|
+
let current: SyntaxToken | undefined = token;
|
|
29
|
+
while (current !== undefined && isTrivia(current)) {
|
|
30
|
+
current = direction === 'next' ? current.nextToken : current.prevToken;
|
|
31
|
+
}
|
|
32
|
+
return current;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The nearest sibling of `element` (within the same parent) in `direction` that
|
|
37
|
+
* is not a trivia token. Nodes are always significant.
|
|
38
|
+
*/
|
|
39
|
+
export function nonTriviaSibling(
|
|
40
|
+
element: SyntaxElement,
|
|
41
|
+
direction: Direction,
|
|
42
|
+
): SyntaxElement | undefined {
|
|
43
|
+
let sibling = step(element, direction);
|
|
44
|
+
while (sibling !== undefined) {
|
|
45
|
+
if (!(sibling instanceof SyntaxToken) || !isTrivia(sibling)) {
|
|
46
|
+
return sibling;
|
|
47
|
+
}
|
|
48
|
+
sibling = step(sibling, direction);
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function step(element: SyntaxElement, direction: Direction): SyntaxElement | undefined {
|
|
54
|
+
return direction === 'next' ? element.nextSiblingOrToken : element.prevSiblingOrToken;
|
|
55
|
+
}
|