@saasmakers/eslint 0.2.6 → 0.2.8
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/dist/chunks/formatters.cjs +248 -0
- package/dist/chunks/formatters.mjs +246 -0
- package/dist/chunks/import.cjs +53 -0
- package/dist/chunks/import.mjs +51 -0
- package/dist/chunks/index.cjs +120 -0
- package/dist/chunks/index.mjs +101 -0
- package/dist/chunks/index2.cjs +880 -0
- package/dist/chunks/index2.mjs +868 -0
- package/dist/chunks/index3.cjs +982 -0
- package/dist/chunks/index3.mjs +979 -0
- package/dist/chunks/index4.cjs +12099 -0
- package/dist/chunks/index4.mjs +12077 -0
- package/dist/chunks/jsdoc.cjs +38398 -0
- package/dist/chunks/jsdoc.mjs +38391 -0
- package/dist/chunks/regexp.cjs +18518 -0
- package/dist/chunks/regexp.mjs +18511 -0
- package/dist/chunks/stylistic.cjs +23935 -0
- package/dist/chunks/stylistic.mjs +23932 -0
- package/dist/chunks/typescript.cjs +56168 -0
- package/dist/chunks/typescript.mjs +56154 -0
- package/dist/chunks/unicorn.cjs +82775 -0
- package/dist/chunks/unicorn.mjs +82764 -0
- package/dist/chunks/vue.cjs +96233 -0
- package/dist/chunks/vue.mjs +96220 -0
- package/dist/eslint.config.cjs +19 -10875
- package/dist/eslint.config.d.cts +3898 -16
- package/dist/eslint.config.d.mts +3898 -16
- package/dist/eslint.config.d.ts +3898 -16
- package/dist/eslint.config.mjs +18 -10853
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +1 -1
- package/dist/shared/eslint.05nu4VbT.mjs +9 -0
- package/dist/shared/eslint.07qTxm9w.mjs +3352 -0
- package/dist/shared/eslint.6MAvpL4q.cjs +2141 -0
- package/dist/shared/{eslint.CohBuu1-.mjs → eslint.B3ywQ3NK.mjs} +157 -331
- package/dist/shared/eslint.BGpVg2tt.cjs +13 -0
- package/dist/shared/eslint.BL4sYiVQ.cjs +820 -0
- package/dist/shared/eslint.BOOP2x9L.cjs +67 -0
- package/dist/shared/eslint.Bf7aat-e.mjs +10 -0
- package/dist/shared/eslint.Bl69eiyD.cjs +7073 -0
- package/dist/shared/eslint.BtkqW7nC.mjs +818 -0
- package/dist/shared/eslint.C12_M0Cw.cjs +9 -0
- package/dist/shared/eslint.CMfxPSSy.cjs +14 -0
- package/dist/shared/eslint.COweQ1RR.mjs +5 -0
- package/dist/shared/eslint.CUi9znUC.mjs +13 -0
- package/dist/shared/eslint.Cg6Ty7p7.mjs +2699 -0
- package/dist/shared/eslint.Ct3Vg5Bb.cjs +37182 -0
- package/dist/shared/eslint.CxAZpd0w.cjs +3365 -0
- package/dist/shared/eslint.CyJA7jO6.cjs +3813 -0
- package/dist/shared/eslint.DDD2xc4l.cjs +25 -0
- package/dist/shared/eslint.DHV9wVWi.mjs +37141 -0
- package/dist/shared/eslint.DI7QBrVD.mjs +6 -0
- package/dist/shared/eslint.DUamuDzp.cjs +7 -0
- package/dist/shared/eslint.DV_fpPxQ.mjs +3805 -0
- package/dist/shared/{eslint.DhFjwkxh.cjs → eslint.Dhg0jKDi.cjs} +167 -330
- package/dist/shared/eslint.Difk5awg.mjs +2139 -0
- package/dist/shared/eslint.Dlgr3LGM.mjs +7070 -0
- package/dist/shared/eslint.DoYGbUIG.cjs +2724 -0
- package/dist/shared/eslint.Dprsk9zl.mjs +65 -0
- package/dist/shared/eslint.MfgVmFE7.cjs +3054 -0
- package/dist/shared/eslint.W7RM7aEw.mjs +3052 -0
- package/package.json +2 -1
|
@@ -0,0 +1,3365 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/errors.ts
|
|
4
|
+
function tokenToString(token) {
|
|
5
|
+
if (token.text !== void 0 && token.text !== "") {
|
|
6
|
+
return `'${token.type}' with value '${token.text}'`;
|
|
7
|
+
} else {
|
|
8
|
+
return `'${token.type}'`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
var NoParsletFoundError = class _NoParsletFoundError extends Error {
|
|
12
|
+
token;
|
|
13
|
+
constructor(token) {
|
|
14
|
+
super(`No parslet found for token: ${tokenToString(token)}`);
|
|
15
|
+
this.token = token;
|
|
16
|
+
Object.setPrototypeOf(this, _NoParsletFoundError.prototype);
|
|
17
|
+
}
|
|
18
|
+
getToken() {
|
|
19
|
+
return this.token;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var EarlyEndOfParseError = class _EarlyEndOfParseError extends Error {
|
|
23
|
+
token;
|
|
24
|
+
constructor(token) {
|
|
25
|
+
super(`The parsing ended early. The next token was: ${tokenToString(token)}`);
|
|
26
|
+
this.token = token;
|
|
27
|
+
Object.setPrototypeOf(this, _EarlyEndOfParseError.prototype);
|
|
28
|
+
}
|
|
29
|
+
getToken() {
|
|
30
|
+
return this.token;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var UnexpectedTypeError = class _UnexpectedTypeError extends Error {
|
|
34
|
+
constructor(result, message) {
|
|
35
|
+
let error = `Unexpected type: '${result.type}'.`;
|
|
36
|
+
if (message !== void 0) {
|
|
37
|
+
error += ` Message: ${message}`;
|
|
38
|
+
}
|
|
39
|
+
super(error);
|
|
40
|
+
Object.setPrototypeOf(this, _UnexpectedTypeError.prototype);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/lexer/Token.ts
|
|
45
|
+
var baseNameTokens = [
|
|
46
|
+
"module",
|
|
47
|
+
"keyof",
|
|
48
|
+
"event",
|
|
49
|
+
"external",
|
|
50
|
+
"readonly",
|
|
51
|
+
"is",
|
|
52
|
+
"typeof",
|
|
53
|
+
"in",
|
|
54
|
+
"null",
|
|
55
|
+
"undefined",
|
|
56
|
+
"function",
|
|
57
|
+
"asserts",
|
|
58
|
+
"infer",
|
|
59
|
+
"extends",
|
|
60
|
+
"import"
|
|
61
|
+
];
|
|
62
|
+
var reservedWordsAsRootTSTypes = [
|
|
63
|
+
"false",
|
|
64
|
+
"null",
|
|
65
|
+
"true",
|
|
66
|
+
"void"
|
|
67
|
+
];
|
|
68
|
+
var reservedWords = {
|
|
69
|
+
always: [
|
|
70
|
+
"break",
|
|
71
|
+
"case",
|
|
72
|
+
"catch",
|
|
73
|
+
"class",
|
|
74
|
+
"const",
|
|
75
|
+
"continue",
|
|
76
|
+
"debugger",
|
|
77
|
+
"default",
|
|
78
|
+
"delete",
|
|
79
|
+
"do",
|
|
80
|
+
"else",
|
|
81
|
+
"export",
|
|
82
|
+
"extends",
|
|
83
|
+
"false",
|
|
84
|
+
"finally",
|
|
85
|
+
"for",
|
|
86
|
+
"function",
|
|
87
|
+
"if",
|
|
88
|
+
"import",
|
|
89
|
+
"in",
|
|
90
|
+
"instanceof",
|
|
91
|
+
"new",
|
|
92
|
+
"null",
|
|
93
|
+
"return",
|
|
94
|
+
"super",
|
|
95
|
+
"switch",
|
|
96
|
+
"this",
|
|
97
|
+
"throw",
|
|
98
|
+
"true",
|
|
99
|
+
"try",
|
|
100
|
+
"typeof",
|
|
101
|
+
"var",
|
|
102
|
+
"void",
|
|
103
|
+
"while",
|
|
104
|
+
"with"
|
|
105
|
+
],
|
|
106
|
+
strictMode: [
|
|
107
|
+
"let",
|
|
108
|
+
"static",
|
|
109
|
+
"yield"
|
|
110
|
+
],
|
|
111
|
+
moduleOrAsyncFunctionBodies: [
|
|
112
|
+
"await"
|
|
113
|
+
]
|
|
114
|
+
};
|
|
115
|
+
var futureReservedWords = {
|
|
116
|
+
always: ["enum"],
|
|
117
|
+
strictMode: [
|
|
118
|
+
"implements",
|
|
119
|
+
"interface",
|
|
120
|
+
"package",
|
|
121
|
+
"private",
|
|
122
|
+
"protected",
|
|
123
|
+
"public"
|
|
124
|
+
]
|
|
125
|
+
};
|
|
126
|
+
var strictModeNonIdentifiers = [
|
|
127
|
+
"arguments",
|
|
128
|
+
"eval"
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
// src/assertTypes.ts
|
|
132
|
+
function assertResultIsNotReservedWord(parser, result) {
|
|
133
|
+
let text;
|
|
134
|
+
if (result.type === "JsdocTypeName") {
|
|
135
|
+
text = result.value;
|
|
136
|
+
} else if (result.type === "JsdocTypeParenthesis") {
|
|
137
|
+
let res = result;
|
|
138
|
+
while (res.type === "JsdocTypeParenthesis") {
|
|
139
|
+
res = res.element;
|
|
140
|
+
}
|
|
141
|
+
if (res.type === "JsdocTypeName") {
|
|
142
|
+
text = res.value;
|
|
143
|
+
} else {
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
if (reservedWords.always.includes(text) && !reservedWordsAsRootTSTypes.includes(text) && (text !== "this" || parser.classContext !== true)) {
|
|
150
|
+
throw new Error(`Unexpected reserved keyword "${text}"`);
|
|
151
|
+
}
|
|
152
|
+
if (futureReservedWords.always.includes(text)) {
|
|
153
|
+
throw new Error(`Unexpected future reserved keyword "${text}"`);
|
|
154
|
+
}
|
|
155
|
+
if (parser.module !== void 0 && parser.module || parser.strictMode !== void 0 && parser.strictMode) {
|
|
156
|
+
if (reservedWords.strictMode.includes(text)) {
|
|
157
|
+
throw new Error(`Unexpected reserved keyword "${text}" for strict mode`);
|
|
158
|
+
}
|
|
159
|
+
if (futureReservedWords.strictMode.includes(text)) {
|
|
160
|
+
throw new Error(`Unexpected future reserved keyword "${text}" for strict mode`);
|
|
161
|
+
}
|
|
162
|
+
if (strictModeNonIdentifiers.includes(text)) {
|
|
163
|
+
throw new Error(`The item "${text}" is not an identifier in strict mode`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (parser.module !== void 0 && parser.module || parser.asyncFunctionBody !== void 0 && parser.asyncFunctionBody) {
|
|
167
|
+
if (reservedWords.moduleOrAsyncFunctionBodies.includes(text)) {
|
|
168
|
+
throw new Error(`Unexpected reserved keyword "${text}" for modules or async function bodies`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
function assertRootResult(result) {
|
|
174
|
+
if (result === void 0) {
|
|
175
|
+
throw new Error("Unexpected undefined");
|
|
176
|
+
}
|
|
177
|
+
if (result.type === "JsdocTypeKeyValue" || result.type === "JsdocTypeParameterList" || result.type === "JsdocTypeProperty" || result.type === "JsdocTypeReadonlyProperty" || result.type === "JsdocTypeObjectField" || result.type === "JsdocTypeJsdocObjectField" || result.type === "JsdocTypeIndexSignature" || result.type === "JsdocTypeMappedType" || result.type === "JsdocTypeTypeParameter" || result.type === "JsdocTypeCallSignature" || result.type === "JsdocTypeConstructorSignature" || result.type === "JsdocTypeMethodSignature" || result.type === "JsdocTypeIndexedAccessIndex" || result.type === "JsdocTypeComputedProperty" || result.type === "JsdocTypeComputedMethod") {
|
|
178
|
+
throw new UnexpectedTypeError(result);
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
function assertPlainKeyValueOrRootResult(result) {
|
|
183
|
+
if (result.type === "JsdocTypeKeyValue") {
|
|
184
|
+
return assertPlainKeyValueResult(result);
|
|
185
|
+
}
|
|
186
|
+
return assertRootResult(result);
|
|
187
|
+
}
|
|
188
|
+
function assertPlainKeyValueOrNameResult(result) {
|
|
189
|
+
if (result.type === "JsdocTypeName") {
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
return assertPlainKeyValueResult(result);
|
|
193
|
+
}
|
|
194
|
+
function assertPlainKeyValueResult(result) {
|
|
195
|
+
if (result.type !== "JsdocTypeKeyValue") {
|
|
196
|
+
throw new UnexpectedTypeError(result);
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
function assertNumberOrVariadicNameResult(result) {
|
|
201
|
+
if (result.type === "JsdocTypeVariadic") {
|
|
202
|
+
if (result.element?.type === "JsdocTypeName") {
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
throw new UnexpectedTypeError(result);
|
|
206
|
+
}
|
|
207
|
+
if (result.type !== "JsdocTypeNumber" && result.type !== "JsdocTypeName") {
|
|
208
|
+
throw new UnexpectedTypeError(result);
|
|
209
|
+
}
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
function assertArrayOrTupleResult(result) {
|
|
213
|
+
if (result.type === "JsdocTypeTuple") {
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
if (result.type === "JsdocTypeGeneric" && result.meta.brackets === "square") {
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
throw new UnexpectedTypeError(result);
|
|
220
|
+
}
|
|
221
|
+
function isSquaredProperty(result) {
|
|
222
|
+
return result.type === "JsdocTypeIndexSignature" || result.type === "JsdocTypeMappedType";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/Parser.ts
|
|
226
|
+
var Parser = class {
|
|
227
|
+
grammar;
|
|
228
|
+
_lexer;
|
|
229
|
+
baseParser;
|
|
230
|
+
externalParsers;
|
|
231
|
+
module;
|
|
232
|
+
strictMode;
|
|
233
|
+
asyncFunctionBody;
|
|
234
|
+
classContext;
|
|
235
|
+
rangeStart;
|
|
236
|
+
range;
|
|
237
|
+
locStart;
|
|
238
|
+
loc;
|
|
239
|
+
constructor(grammar, lexer, baseParser, {
|
|
240
|
+
module,
|
|
241
|
+
strictMode,
|
|
242
|
+
asyncFunctionBody,
|
|
243
|
+
classContext,
|
|
244
|
+
range = false,
|
|
245
|
+
rangeStart = 0,
|
|
246
|
+
loc = false,
|
|
247
|
+
locStart = {
|
|
248
|
+
line: 1,
|
|
249
|
+
column: 0
|
|
250
|
+
},
|
|
251
|
+
externalParsers
|
|
252
|
+
} = {}) {
|
|
253
|
+
this.grammar = grammar;
|
|
254
|
+
this._lexer = lexer;
|
|
255
|
+
this.baseParser = baseParser;
|
|
256
|
+
this.externalParsers = externalParsers;
|
|
257
|
+
this.module = module;
|
|
258
|
+
this.strictMode = strictMode;
|
|
259
|
+
this.asyncFunctionBody = asyncFunctionBody;
|
|
260
|
+
this.classContext = classContext;
|
|
261
|
+
this.rangeStart = rangeStart;
|
|
262
|
+
this.range = range;
|
|
263
|
+
this.locStart = locStart;
|
|
264
|
+
this.loc = loc;
|
|
265
|
+
}
|
|
266
|
+
get lexer() {
|
|
267
|
+
return this._lexer;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Parses a given string and throws an error if the parse ended before the end of the string.
|
|
271
|
+
*/
|
|
272
|
+
parse() {
|
|
273
|
+
const result = this.parseType(0 /* ALL */);
|
|
274
|
+
if (this.lexer.current.type !== "EOF") {
|
|
275
|
+
throw new EarlyEndOfParseError(this.lexer.current);
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Parses with the current lexer and asserts that the result is a {@link RootResult}.
|
|
281
|
+
*/
|
|
282
|
+
parseType(precedence) {
|
|
283
|
+
return assertRootResult(this.parseIntermediateType(precedence));
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* The main parsing function. First it tries to parse the current state in the prefix step, and then it continues
|
|
287
|
+
* to parse the state in the infix step.
|
|
288
|
+
*/
|
|
289
|
+
parseIntermediateType(precedence) {
|
|
290
|
+
const result = this.tryParslets(null, precedence);
|
|
291
|
+
if (result === null) {
|
|
292
|
+
throw new NoParsletFoundError(this.lexer.current);
|
|
293
|
+
}
|
|
294
|
+
return this.parseInfixIntermediateType(result, precedence);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* In the infix parsing step the parser continues to parse the current state with all parslets until none returns
|
|
298
|
+
* a result.
|
|
299
|
+
*/
|
|
300
|
+
parseInfixIntermediateType(left, precedence) {
|
|
301
|
+
let result = this.tryParslets(left, precedence);
|
|
302
|
+
while (result !== null) {
|
|
303
|
+
left = result;
|
|
304
|
+
result = this.tryParslets(left, precedence);
|
|
305
|
+
}
|
|
306
|
+
return left;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Tries to parse the current state with all parslets in the grammar and returns the first non null result.
|
|
310
|
+
*/
|
|
311
|
+
tryParslets(left, precedence) {
|
|
312
|
+
for (const parslet of this.grammar) {
|
|
313
|
+
const rangeStart = this.rangeStart;
|
|
314
|
+
const locStartLine = this.locStart.line;
|
|
315
|
+
const locStartColumn = this.locStart.column;
|
|
316
|
+
const result = parslet(this, precedence, left);
|
|
317
|
+
if (result !== null) {
|
|
318
|
+
if (this.range) {
|
|
319
|
+
result.range = [
|
|
320
|
+
rangeStart,
|
|
321
|
+
this.rangeStart
|
|
322
|
+
];
|
|
323
|
+
}
|
|
324
|
+
if (this.loc) {
|
|
325
|
+
result.loc = {
|
|
326
|
+
end: {
|
|
327
|
+
line: this.locStart.line,
|
|
328
|
+
column: this.locStart.column
|
|
329
|
+
},
|
|
330
|
+
start: {
|
|
331
|
+
line: locStartLine,
|
|
332
|
+
column: locStartColumn
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* If the given type equals the current type of the {@link Lexer} advance the lexer. Return true if the lexer was
|
|
343
|
+
* advanced.
|
|
344
|
+
*/
|
|
345
|
+
consume(types) {
|
|
346
|
+
if (!Array.isArray(types)) {
|
|
347
|
+
types = [types];
|
|
348
|
+
}
|
|
349
|
+
if (types.includes(this.lexer.current.type)) {
|
|
350
|
+
if (this.range) {
|
|
351
|
+
this.rangeStart += this.lexer.current?.reduced ?? 0;
|
|
352
|
+
}
|
|
353
|
+
if (this.loc) {
|
|
354
|
+
this.locStart.line += this.lexer.current?.line ?? 0;
|
|
355
|
+
this.locStart.column = (this.lexer.current?.line ?? 0) > 0 ? this.lexer.current?.column ?? 0 : this.locStart.column + (this.lexer.current?.column ?? 0);
|
|
356
|
+
}
|
|
357
|
+
this._lexer = this.lexer.advance();
|
|
358
|
+
return true;
|
|
359
|
+
} else {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
acceptLexerState(parser) {
|
|
364
|
+
this._lexer = parser.lexer;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// src/parslets/isQuestionMarkUnknownType.ts
|
|
369
|
+
function isQuestionMarkUnknownType(next) {
|
|
370
|
+
return next === "}" || next === "EOF" || next === "|" || next === "," || next === ")" || next === ">";
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/parslets/NullableParslets.ts
|
|
374
|
+
var nullableParslet = (parser, precedence, left) => {
|
|
375
|
+
const type = parser.lexer.current.type;
|
|
376
|
+
const next = parser.lexer.next.type;
|
|
377
|
+
const accept = left === null && type === "?" && !isQuestionMarkUnknownType(next) || left !== null && type === "?" && 12 /* NULLABLE */ > precedence;
|
|
378
|
+
if (!accept) {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
parser.consume("?");
|
|
382
|
+
if (left === null) {
|
|
383
|
+
return {
|
|
384
|
+
type: "JsdocTypeNullable",
|
|
385
|
+
element: parser.parseType(12 /* NULLABLE */),
|
|
386
|
+
meta: {
|
|
387
|
+
position: "prefix"
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
} else {
|
|
391
|
+
return {
|
|
392
|
+
type: "JsdocTypeNullable",
|
|
393
|
+
element: assertRootResult(left),
|
|
394
|
+
meta: {
|
|
395
|
+
position: "suffix"
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// src/parslets/Parslet.ts
|
|
402
|
+
function composeParslet(options) {
|
|
403
|
+
const parslet = (parser, curPrecedence, left) => {
|
|
404
|
+
const type = parser.lexer.current.type;
|
|
405
|
+
const next = parser.lexer.next.type;
|
|
406
|
+
if (left === null) {
|
|
407
|
+
if ("parsePrefix" in options) {
|
|
408
|
+
if (options.accept(type, next)) {
|
|
409
|
+
return options.parsePrefix(parser);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
if ("parseInfix" in options) {
|
|
414
|
+
if (options.precedence > curPrecedence && options.accept(type, next)) {
|
|
415
|
+
return options.parseInfix(parser, left);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
};
|
|
421
|
+
Object.defineProperty(parslet, "name", {
|
|
422
|
+
value: options.name
|
|
423
|
+
});
|
|
424
|
+
return parslet;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// src/parslets/OptionalParslet.ts
|
|
428
|
+
var optionalParslet = composeParslet({
|
|
429
|
+
name: "optionalParslet",
|
|
430
|
+
accept: (type) => type === "=",
|
|
431
|
+
precedence: 11 /* OPTIONAL */,
|
|
432
|
+
parsePrefix: (parser) => {
|
|
433
|
+
parser.consume("=");
|
|
434
|
+
return {
|
|
435
|
+
type: "JsdocTypeOptional",
|
|
436
|
+
element: parser.parseType(11 /* OPTIONAL */),
|
|
437
|
+
meta: {
|
|
438
|
+
position: "prefix"
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
},
|
|
442
|
+
parseInfix: (parser, left) => {
|
|
443
|
+
parser.consume("=");
|
|
444
|
+
return {
|
|
445
|
+
type: "JsdocTypeOptional",
|
|
446
|
+
element: assertRootResult(left),
|
|
447
|
+
meta: {
|
|
448
|
+
position: "suffix"
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// src/parslets/NumberParslet.ts
|
|
455
|
+
var numberParslet = composeParslet({
|
|
456
|
+
name: "numberParslet",
|
|
457
|
+
accept: (type) => type === "Number",
|
|
458
|
+
parsePrefix: (parser) => {
|
|
459
|
+
const value = parseFloat(parser.lexer.current.text);
|
|
460
|
+
parser.consume("Number");
|
|
461
|
+
return {
|
|
462
|
+
type: "JsdocTypeNumber",
|
|
463
|
+
value
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// src/parslets/ParenthesisParslet.ts
|
|
469
|
+
var parenthesisParslet = composeParslet({
|
|
470
|
+
name: "parenthesisParslet",
|
|
471
|
+
accept: (type) => type === "(",
|
|
472
|
+
parsePrefix: (parser) => {
|
|
473
|
+
parser.consume("(");
|
|
474
|
+
if (parser.consume(")")) {
|
|
475
|
+
return {
|
|
476
|
+
type: "JsdocTypeParameterList",
|
|
477
|
+
elements: []
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
const result = parser.parseIntermediateType(0 /* ALL */);
|
|
481
|
+
if (!parser.consume(")")) {
|
|
482
|
+
throw new Error("Unterminated parenthesis");
|
|
483
|
+
}
|
|
484
|
+
if (result.type === "JsdocTypeParameterList") {
|
|
485
|
+
return result;
|
|
486
|
+
} else if (result.type === "JsdocTypeKeyValue") {
|
|
487
|
+
return {
|
|
488
|
+
type: "JsdocTypeParameterList",
|
|
489
|
+
elements: [result]
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
type: "JsdocTypeParenthesis",
|
|
494
|
+
element: assertRootResult(result)
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// src/parslets/SpecialTypesParslet.ts
|
|
500
|
+
var specialTypesParslet = composeParslet({
|
|
501
|
+
name: "specialTypesParslet",
|
|
502
|
+
accept: (type, next) => type === "?" && isQuestionMarkUnknownType(next) || type === "null" || type === "undefined" || type === "*",
|
|
503
|
+
parsePrefix: (parser) => {
|
|
504
|
+
if (parser.consume("null")) {
|
|
505
|
+
return {
|
|
506
|
+
type: "JsdocTypeNull"
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
if (parser.consume("undefined")) {
|
|
510
|
+
return {
|
|
511
|
+
type: "JsdocTypeUndefined"
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
if (parser.consume("*")) {
|
|
515
|
+
return {
|
|
516
|
+
type: "JsdocTypeAny"
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (parser.consume("?")) {
|
|
520
|
+
return {
|
|
521
|
+
type: "JsdocTypeUnknown"
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
throw new Error(`Unacceptable token: ${parser.lexer.current.text}`);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// src/parslets/NotNullableParslet.ts
|
|
529
|
+
var notNullableParslet = composeParslet({
|
|
530
|
+
name: "notNullableParslet",
|
|
531
|
+
accept: (type) => type === "!",
|
|
532
|
+
precedence: 12 /* NULLABLE */,
|
|
533
|
+
parsePrefix: (parser) => {
|
|
534
|
+
parser.consume("!");
|
|
535
|
+
return {
|
|
536
|
+
type: "JsdocTypeNotNullable",
|
|
537
|
+
element: parser.parseType(12 /* NULLABLE */),
|
|
538
|
+
meta: {
|
|
539
|
+
position: "prefix"
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
},
|
|
543
|
+
parseInfix: (parser, left) => {
|
|
544
|
+
parser.consume("!");
|
|
545
|
+
return {
|
|
546
|
+
type: "JsdocTypeNotNullable",
|
|
547
|
+
element: assertRootResult(left),
|
|
548
|
+
meta: {
|
|
549
|
+
position: "suffix"
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
// src/parslets/ParameterListParslet.ts
|
|
556
|
+
function createParameterListParslet({ allowTrailingComma }) {
|
|
557
|
+
return composeParslet({
|
|
558
|
+
name: "parameterListParslet",
|
|
559
|
+
accept: (type) => type === ",",
|
|
560
|
+
precedence: 1 /* PARAMETER_LIST */,
|
|
561
|
+
parseInfix: (parser, left) => {
|
|
562
|
+
const elements = [
|
|
563
|
+
assertPlainKeyValueOrRootResult(left)
|
|
564
|
+
];
|
|
565
|
+
parser.consume(",");
|
|
566
|
+
do {
|
|
567
|
+
try {
|
|
568
|
+
const next = parser.parseIntermediateType(1 /* PARAMETER_LIST */);
|
|
569
|
+
elements.push(assertPlainKeyValueOrRootResult(next));
|
|
570
|
+
} catch (e) {
|
|
571
|
+
if (e instanceof NoParsletFoundError) {
|
|
572
|
+
break;
|
|
573
|
+
} else {
|
|
574
|
+
throw e;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
} while (parser.consume(","));
|
|
578
|
+
if (elements.length > 0 && elements.slice(0, -1).some((e) => e.type === "JsdocTypeVariadic")) {
|
|
579
|
+
throw new Error("Only the last parameter may be a rest parameter");
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
type: "JsdocTypeParameterList",
|
|
583
|
+
elements
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// src/parslets/GenericParslet.ts
|
|
590
|
+
var genericParslet = composeParslet({
|
|
591
|
+
name: "genericParslet",
|
|
592
|
+
accept: (type, next) => type === "<" || type === "." && next === "<",
|
|
593
|
+
precedence: 17 /* GENERIC */,
|
|
594
|
+
parseInfix: (parser, left) => {
|
|
595
|
+
const dot = parser.consume(".");
|
|
596
|
+
parser.consume("<");
|
|
597
|
+
const elements = [];
|
|
598
|
+
do {
|
|
599
|
+
if (parser.consume("infer")) {
|
|
600
|
+
const name = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
601
|
+
if (name.type !== "JsdocTypeName") {
|
|
602
|
+
throw new UnexpectedTypeError(name, "A typescript infer always has to have a name.");
|
|
603
|
+
}
|
|
604
|
+
elements.push({
|
|
605
|
+
type: "JsdocTypeInfer",
|
|
606
|
+
element: name
|
|
607
|
+
});
|
|
608
|
+
} else {
|
|
609
|
+
elements.push(parser.parseType(1 /* PARAMETER_LIST */));
|
|
610
|
+
}
|
|
611
|
+
} while (parser.consume(","));
|
|
612
|
+
if (!parser.consume(">")) {
|
|
613
|
+
throw new Error("Unterminated generic parameter list");
|
|
614
|
+
}
|
|
615
|
+
return {
|
|
616
|
+
type: "JsdocTypeGeneric",
|
|
617
|
+
left: assertRootResult(left),
|
|
618
|
+
elements,
|
|
619
|
+
meta: {
|
|
620
|
+
brackets: "angle",
|
|
621
|
+
dot
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
// src/parslets/UnionParslets.ts
|
|
628
|
+
var unionParslet = composeParslet({
|
|
629
|
+
name: "unionParslet",
|
|
630
|
+
accept: (type) => type === "|",
|
|
631
|
+
precedence: 5 /* UNION */,
|
|
632
|
+
parseInfix: (parser, left) => {
|
|
633
|
+
parser.consume("|");
|
|
634
|
+
const elements = [];
|
|
635
|
+
do {
|
|
636
|
+
elements.push(parser.parseType(5 /* UNION */));
|
|
637
|
+
} while (parser.consume("|"));
|
|
638
|
+
return {
|
|
639
|
+
type: "JsdocTypeUnion",
|
|
640
|
+
elements: [
|
|
641
|
+
assertResultIsNotReservedWord(parser, assertRootResult(left)),
|
|
642
|
+
...elements.map((element) => assertResultIsNotReservedWord(parser, element))
|
|
643
|
+
]
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
// src/grammars/baseGrammar.ts
|
|
649
|
+
var baseGrammar = [
|
|
650
|
+
nullableParslet,
|
|
651
|
+
optionalParslet,
|
|
652
|
+
numberParslet,
|
|
653
|
+
parenthesisParslet,
|
|
654
|
+
specialTypesParslet,
|
|
655
|
+
notNullableParslet,
|
|
656
|
+
createParameterListParslet({
|
|
657
|
+
allowTrailingComma: true
|
|
658
|
+
}),
|
|
659
|
+
genericParslet,
|
|
660
|
+
unionParslet,
|
|
661
|
+
optionalParslet
|
|
662
|
+
];
|
|
663
|
+
|
|
664
|
+
// src/parslets/NamePathParslet.ts
|
|
665
|
+
function createNamePathParslet({ allowSquareBracketsOnAnyType, allowJsdocNamePaths, pathGrammar: pathGrammar2 }) {
|
|
666
|
+
return function namePathParslet(parser, precedence, left) {
|
|
667
|
+
if (left === null || precedence >= 18 /* NAME_PATH */) {
|
|
668
|
+
return null;
|
|
669
|
+
}
|
|
670
|
+
const type = parser.lexer.current.type;
|
|
671
|
+
const next = parser.lexer.next.type;
|
|
672
|
+
const accept = type === "." && next !== "<" || type === "[" && (allowSquareBracketsOnAnyType || left.type === "JsdocTypeName") || allowJsdocNamePaths && (type === "~" || type === "#");
|
|
673
|
+
if (!accept) {
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
let pathType;
|
|
677
|
+
let brackets = false;
|
|
678
|
+
if (parser.consume(".")) {
|
|
679
|
+
pathType = "property";
|
|
680
|
+
} else if (parser.consume("[")) {
|
|
681
|
+
pathType = "property-brackets";
|
|
682
|
+
brackets = true;
|
|
683
|
+
} else if (parser.consume("~")) {
|
|
684
|
+
pathType = "inner";
|
|
685
|
+
} else {
|
|
686
|
+
parser.consume("#");
|
|
687
|
+
pathType = "instance";
|
|
688
|
+
}
|
|
689
|
+
const pathParser = brackets && allowSquareBracketsOnAnyType ? parser : pathGrammar2 !== null ? new Parser(pathGrammar2, parser.lexer, parser) : parser;
|
|
690
|
+
const parsed = pathParser.parseType(18 /* NAME_PATH */);
|
|
691
|
+
parser.acceptLexerState(pathParser);
|
|
692
|
+
let right;
|
|
693
|
+
switch (parsed.type) {
|
|
694
|
+
case "JsdocTypeName":
|
|
695
|
+
right = {
|
|
696
|
+
type: "JsdocTypeProperty",
|
|
697
|
+
value: parsed.value,
|
|
698
|
+
meta: {
|
|
699
|
+
quote: void 0
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
break;
|
|
703
|
+
case "JsdocTypeNumber":
|
|
704
|
+
right = {
|
|
705
|
+
type: "JsdocTypeProperty",
|
|
706
|
+
value: parsed.value.toString(10),
|
|
707
|
+
meta: {
|
|
708
|
+
quote: void 0
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
break;
|
|
712
|
+
case "JsdocTypeStringValue":
|
|
713
|
+
right = {
|
|
714
|
+
type: "JsdocTypeProperty",
|
|
715
|
+
value: parsed.value,
|
|
716
|
+
meta: {
|
|
717
|
+
quote: parsed.meta.quote
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
break;
|
|
721
|
+
case "JsdocTypeSpecialNamePath":
|
|
722
|
+
if (parsed.specialType === "event") {
|
|
723
|
+
right = parsed;
|
|
724
|
+
} else {
|
|
725
|
+
throw new UnexpectedTypeError(parsed, "Type 'JsdocTypeSpecialNamePath' is only allowed with specialType 'event'");
|
|
726
|
+
}
|
|
727
|
+
break;
|
|
728
|
+
default:
|
|
729
|
+
if (!brackets || !allowSquareBracketsOnAnyType) {
|
|
730
|
+
throw new UnexpectedTypeError(parsed, "Expecting 'JsdocTypeName', 'JsdocTypeNumber', 'JsdocStringValue' or 'JsdocTypeSpecialNamePath'");
|
|
731
|
+
}
|
|
732
|
+
right = {
|
|
733
|
+
type: "JsdocTypeIndexedAccessIndex",
|
|
734
|
+
right: parsed
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
if (brackets && !parser.consume("]")) {
|
|
738
|
+
const token = parser.lexer.current;
|
|
739
|
+
throw new Error(`Unterminated square brackets. Next token is '${token.type}' with text '${token.text}'`);
|
|
740
|
+
}
|
|
741
|
+
return {
|
|
742
|
+
type: "JsdocTypeNamePath",
|
|
743
|
+
left: assertRootResult(left),
|
|
744
|
+
right,
|
|
745
|
+
pathType
|
|
746
|
+
};
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// src/parslets/NameParslet.ts
|
|
751
|
+
function createNameParslet({ allowedAdditionalTokens }) {
|
|
752
|
+
return composeParslet({
|
|
753
|
+
name: "nameParslet",
|
|
754
|
+
accept: (type) => type === "Identifier" || type === "this" || type === "new" || allowedAdditionalTokens.includes(type),
|
|
755
|
+
parsePrefix: (parser) => {
|
|
756
|
+
const { type, text } = parser.lexer.current;
|
|
757
|
+
parser.consume(type);
|
|
758
|
+
return {
|
|
759
|
+
type: "JsdocTypeName",
|
|
760
|
+
value: text
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/parslets/StringValueParslet.ts
|
|
767
|
+
var stringValueParslet = composeParslet({
|
|
768
|
+
name: "stringValueParslet",
|
|
769
|
+
accept: (type) => type === "StringValue",
|
|
770
|
+
parsePrefix: (parser) => {
|
|
771
|
+
const text = parser.lexer.current.text;
|
|
772
|
+
parser.consume("StringValue");
|
|
773
|
+
return {
|
|
774
|
+
type: "JsdocTypeStringValue",
|
|
775
|
+
value: text.slice(1, -1),
|
|
776
|
+
meta: {
|
|
777
|
+
quote: text.startsWith("'") ? "single" : "double"
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
// src/parslets/SpecialNamePathParslet.ts
|
|
784
|
+
function createSpecialNamePathParslet({ pathGrammar: pathGrammar2, allowedTypes }) {
|
|
785
|
+
return composeParslet({
|
|
786
|
+
name: "specialNamePathParslet",
|
|
787
|
+
accept: (type) => allowedTypes.includes(type),
|
|
788
|
+
parsePrefix: (parser) => {
|
|
789
|
+
const type = parser.lexer.current.type;
|
|
790
|
+
parser.consume(type);
|
|
791
|
+
if (!parser.consume(":")) {
|
|
792
|
+
return {
|
|
793
|
+
type: "JsdocTypeName",
|
|
794
|
+
value: type
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
let result;
|
|
798
|
+
let token = parser.lexer.current;
|
|
799
|
+
if (parser.consume("StringValue")) {
|
|
800
|
+
result = {
|
|
801
|
+
type: "JsdocTypeSpecialNamePath",
|
|
802
|
+
value: token.text.slice(1, -1),
|
|
803
|
+
specialType: type,
|
|
804
|
+
meta: {
|
|
805
|
+
quote: token.text.startsWith("'") ? "single" : "double"
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
} else {
|
|
809
|
+
let value = "";
|
|
810
|
+
const allowed = ["Identifier", "@", "/"];
|
|
811
|
+
while (allowed.some((type2) => parser.consume(type2))) {
|
|
812
|
+
value += token.text;
|
|
813
|
+
token = parser.lexer.current;
|
|
814
|
+
}
|
|
815
|
+
result = {
|
|
816
|
+
type: "JsdocTypeSpecialNamePath",
|
|
817
|
+
value,
|
|
818
|
+
specialType: type,
|
|
819
|
+
meta: {
|
|
820
|
+
quote: void 0
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
const moduleParser = new Parser(pathGrammar2, parser.lexer, parser);
|
|
825
|
+
const moduleResult = moduleParser.parseInfixIntermediateType(result, 0 /* ALL */);
|
|
826
|
+
parser.acceptLexerState(moduleParser);
|
|
827
|
+
return assertRootResult(moduleResult);
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// src/grammars/pathGrammar.ts
|
|
833
|
+
var basePathGrammar = [
|
|
834
|
+
createNameParslet({
|
|
835
|
+
allowedAdditionalTokens: ["external", "module"]
|
|
836
|
+
}),
|
|
837
|
+
stringValueParslet,
|
|
838
|
+
numberParslet,
|
|
839
|
+
createNamePathParslet({
|
|
840
|
+
allowSquareBracketsOnAnyType: false,
|
|
841
|
+
allowJsdocNamePaths: true,
|
|
842
|
+
pathGrammar: null
|
|
843
|
+
})
|
|
844
|
+
];
|
|
845
|
+
var pathGrammar = [
|
|
846
|
+
...basePathGrammar,
|
|
847
|
+
createSpecialNamePathParslet({
|
|
848
|
+
allowedTypes: ["event"],
|
|
849
|
+
pathGrammar: basePathGrammar
|
|
850
|
+
}),
|
|
851
|
+
createNameParslet({
|
|
852
|
+
allowedAdditionalTokens: baseNameTokens
|
|
853
|
+
})
|
|
854
|
+
];
|
|
855
|
+
|
|
856
|
+
// src/parslets/FunctionParslet.ts
|
|
857
|
+
function getParameters(value) {
|
|
858
|
+
let parameters;
|
|
859
|
+
if (value.type === "JsdocTypeParameterList") {
|
|
860
|
+
parameters = value.elements;
|
|
861
|
+
} else if (value.type === "JsdocTypeParenthesis") {
|
|
862
|
+
parameters = [value.element];
|
|
863
|
+
} else {
|
|
864
|
+
throw new UnexpectedTypeError(value);
|
|
865
|
+
}
|
|
866
|
+
return parameters.map((p) => assertPlainKeyValueOrRootResult(p));
|
|
867
|
+
}
|
|
868
|
+
function getUnnamedParameters(value) {
|
|
869
|
+
const parameters = getParameters(value);
|
|
870
|
+
if (parameters.some((p) => p.type === "JsdocTypeKeyValue")) {
|
|
871
|
+
throw new Error("No parameter should be named");
|
|
872
|
+
}
|
|
873
|
+
return parameters;
|
|
874
|
+
}
|
|
875
|
+
function createFunctionParslet({ allowNamedParameters, allowNoReturnType, allowWithoutParenthesis, allowNewAsFunctionKeyword }) {
|
|
876
|
+
return composeParslet({
|
|
877
|
+
name: "functionParslet",
|
|
878
|
+
accept: (type, next) => type === "function" || allowNewAsFunctionKeyword && type === "new" && next === "(",
|
|
879
|
+
parsePrefix: (parser) => {
|
|
880
|
+
const newKeyword = parser.consume("new");
|
|
881
|
+
parser.consume("function");
|
|
882
|
+
const hasParenthesis = parser.lexer.current.type === "(";
|
|
883
|
+
if (!hasParenthesis) {
|
|
884
|
+
if (!allowWithoutParenthesis) {
|
|
885
|
+
throw new Error("function is missing parameter list");
|
|
886
|
+
}
|
|
887
|
+
return {
|
|
888
|
+
type: "JsdocTypeName",
|
|
889
|
+
value: "function"
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
let result = {
|
|
893
|
+
type: "JsdocTypeFunction",
|
|
894
|
+
parameters: [],
|
|
895
|
+
arrow: false,
|
|
896
|
+
constructor: newKeyword,
|
|
897
|
+
parenthesis: hasParenthesis
|
|
898
|
+
};
|
|
899
|
+
const value = parser.parseIntermediateType(14 /* FUNCTION */);
|
|
900
|
+
if (allowNamedParameters === void 0) {
|
|
901
|
+
result.parameters = getUnnamedParameters(value);
|
|
902
|
+
} else if (newKeyword && value.type === "JsdocTypeFunction" && value.arrow) {
|
|
903
|
+
result = value;
|
|
904
|
+
result.constructor = true;
|
|
905
|
+
return result;
|
|
906
|
+
} else {
|
|
907
|
+
result.parameters = getParameters(value);
|
|
908
|
+
for (const p of result.parameters) {
|
|
909
|
+
if (p.type === "JsdocTypeKeyValue" && !allowNamedParameters.includes(p.key)) {
|
|
910
|
+
throw new Error(`only allowed named parameters are ${allowNamedParameters.join(", ")} but got ${p.type}`);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
if (parser.consume(":")) {
|
|
915
|
+
result.returnType = parser.parseType(7 /* PREFIX */);
|
|
916
|
+
}
|
|
917
|
+
return result;
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// src/parslets/VariadicParslet.ts
|
|
923
|
+
function createVariadicParslet({ allowPostfix, allowEnclosingBrackets }) {
|
|
924
|
+
return composeParslet({
|
|
925
|
+
name: "variadicParslet",
|
|
926
|
+
accept: (type) => type === "...",
|
|
927
|
+
precedence: 7 /* PREFIX */,
|
|
928
|
+
parsePrefix: (parser) => {
|
|
929
|
+
parser.consume("...");
|
|
930
|
+
const brackets = allowEnclosingBrackets && parser.consume("[");
|
|
931
|
+
try {
|
|
932
|
+
const element = parser.parseType(7 /* PREFIX */);
|
|
933
|
+
if (brackets && !parser.consume("]")) {
|
|
934
|
+
throw new Error("Unterminated variadic type. Missing ']'");
|
|
935
|
+
}
|
|
936
|
+
return {
|
|
937
|
+
type: "JsdocTypeVariadic",
|
|
938
|
+
element: assertRootResult(element),
|
|
939
|
+
meta: {
|
|
940
|
+
position: "prefix",
|
|
941
|
+
squareBrackets: brackets
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
} catch (e) {
|
|
945
|
+
if (e instanceof NoParsletFoundError) {
|
|
946
|
+
if (brackets) {
|
|
947
|
+
throw new Error("Empty square brackets for variadic are not allowed.", {
|
|
948
|
+
cause: e
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
return {
|
|
952
|
+
type: "JsdocTypeVariadic",
|
|
953
|
+
meta: {
|
|
954
|
+
position: void 0,
|
|
955
|
+
squareBrackets: false
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
} else {
|
|
959
|
+
throw e;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
parseInfix: allowPostfix ? (parser, left) => {
|
|
964
|
+
parser.consume("...");
|
|
965
|
+
return {
|
|
966
|
+
type: "JsdocTypeVariadic",
|
|
967
|
+
element: assertRootResult(left),
|
|
968
|
+
meta: {
|
|
969
|
+
position: "suffix",
|
|
970
|
+
squareBrackets: false
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
} : void 0
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/parslets/SymbolParslet.ts
|
|
978
|
+
var symbolParslet = composeParslet({
|
|
979
|
+
name: "symbolParslet",
|
|
980
|
+
accept: (type) => type === "(",
|
|
981
|
+
precedence: 10 /* SYMBOL */,
|
|
982
|
+
parseInfix: (parser, left) => {
|
|
983
|
+
if (left.type !== "JsdocTypeName") {
|
|
984
|
+
throw new Error("Symbol expects a name on the left side. (Reacting on '(')");
|
|
985
|
+
}
|
|
986
|
+
parser.consume("(");
|
|
987
|
+
const result = {
|
|
988
|
+
type: "JsdocTypeSymbol",
|
|
989
|
+
value: left.value
|
|
990
|
+
};
|
|
991
|
+
if (!parser.consume(")")) {
|
|
992
|
+
const next = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
993
|
+
result.element = assertNumberOrVariadicNameResult(next);
|
|
994
|
+
if (!parser.consume(")")) {
|
|
995
|
+
throw new Error("Symbol does not end after value");
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return result;
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
|
|
1002
|
+
// src/parslets/ArrayBracketsParslet.ts
|
|
1003
|
+
var arrayBracketsParslet = composeParslet({
|
|
1004
|
+
name: "arrayBracketsParslet",
|
|
1005
|
+
precedence: 16 /* ARRAY_BRACKETS */,
|
|
1006
|
+
accept: (type, next) => type === "[" && next === "]",
|
|
1007
|
+
parseInfix: (parser, left) => {
|
|
1008
|
+
parser.consume("[");
|
|
1009
|
+
parser.consume("]");
|
|
1010
|
+
return {
|
|
1011
|
+
type: "JsdocTypeGeneric",
|
|
1012
|
+
left: {
|
|
1013
|
+
type: "JsdocTypeName",
|
|
1014
|
+
value: "Array"
|
|
1015
|
+
},
|
|
1016
|
+
elements: [
|
|
1017
|
+
assertRootResult(left)
|
|
1018
|
+
],
|
|
1019
|
+
meta: {
|
|
1020
|
+
brackets: "square",
|
|
1021
|
+
dot: false
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
// src/parslets/ObjectParslet.ts
|
|
1028
|
+
function createObjectParslet({ signatureGrammar, objectFieldGrammar: objectFieldGrammar3, allowKeyTypes }) {
|
|
1029
|
+
return composeParslet({
|
|
1030
|
+
name: "objectParslet",
|
|
1031
|
+
accept: (type) => type === "{",
|
|
1032
|
+
parsePrefix: (parser) => {
|
|
1033
|
+
parser.consume("{");
|
|
1034
|
+
const result = {
|
|
1035
|
+
type: "JsdocTypeObject",
|
|
1036
|
+
meta: {
|
|
1037
|
+
separator: "comma"
|
|
1038
|
+
},
|
|
1039
|
+
elements: []
|
|
1040
|
+
};
|
|
1041
|
+
if (!parser.consume("}")) {
|
|
1042
|
+
let separator;
|
|
1043
|
+
const fieldParser = new Parser(
|
|
1044
|
+
objectFieldGrammar3,
|
|
1045
|
+
parser.lexer,
|
|
1046
|
+
parser,
|
|
1047
|
+
parser.externalParsers?.computedPropertyParser !== void 0 ? {
|
|
1048
|
+
externalParsers: {
|
|
1049
|
+
computedPropertyParser: parser.externalParsers.computedPropertyParser
|
|
1050
|
+
}
|
|
1051
|
+
} : void 0
|
|
1052
|
+
);
|
|
1053
|
+
while (true) {
|
|
1054
|
+
fieldParser.acceptLexerState(parser);
|
|
1055
|
+
let field = fieldParser.parseIntermediateType(2 /* OBJECT */);
|
|
1056
|
+
parser.acceptLexerState(fieldParser);
|
|
1057
|
+
if (field === void 0 && allowKeyTypes) {
|
|
1058
|
+
field = parser.parseIntermediateType(2 /* OBJECT */);
|
|
1059
|
+
}
|
|
1060
|
+
let optional = false;
|
|
1061
|
+
if (field.type === "JsdocTypeNullable") {
|
|
1062
|
+
optional = true;
|
|
1063
|
+
field = field.element;
|
|
1064
|
+
}
|
|
1065
|
+
if (field.type === "JsdocTypeNumber" || field.type === "JsdocTypeName" || field.type === "JsdocTypeStringValue") {
|
|
1066
|
+
let quote2;
|
|
1067
|
+
if (field.type === "JsdocTypeStringValue") {
|
|
1068
|
+
quote2 = field.meta.quote;
|
|
1069
|
+
}
|
|
1070
|
+
result.elements.push({
|
|
1071
|
+
type: "JsdocTypeObjectField",
|
|
1072
|
+
key: field.value.toString(),
|
|
1073
|
+
right: void 0,
|
|
1074
|
+
optional,
|
|
1075
|
+
readonly: false,
|
|
1076
|
+
meta: {
|
|
1077
|
+
quote: quote2
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
} else if (signatureGrammar !== void 0 && (field.type === "JsdocTypeCallSignature" || field.type === "JsdocTypeConstructorSignature" || field.type === "JsdocTypeMethodSignature")) {
|
|
1081
|
+
const signatureParser = new Parser(
|
|
1082
|
+
[
|
|
1083
|
+
...signatureGrammar,
|
|
1084
|
+
...parser.grammar.flatMap((grammar) => {
|
|
1085
|
+
if (grammar.name === "keyValueParslet") {
|
|
1086
|
+
return [];
|
|
1087
|
+
}
|
|
1088
|
+
return [grammar];
|
|
1089
|
+
})
|
|
1090
|
+
],
|
|
1091
|
+
parser.lexer,
|
|
1092
|
+
parser
|
|
1093
|
+
);
|
|
1094
|
+
signatureParser.acceptLexerState(parser);
|
|
1095
|
+
const params = signatureParser.parseIntermediateType(2 /* OBJECT */);
|
|
1096
|
+
parser.acceptLexerState(signatureParser);
|
|
1097
|
+
field.parameters = getParameters(params);
|
|
1098
|
+
const returnType = parser.parseType(2 /* OBJECT */);
|
|
1099
|
+
field.returnType = returnType;
|
|
1100
|
+
result.elements.push(field);
|
|
1101
|
+
} else if (field.type === "JsdocTypeObjectField" || field.type === "JsdocTypeJsdocObjectField") {
|
|
1102
|
+
result.elements.push(field);
|
|
1103
|
+
} else if (field.type === "JsdocTypeReadonlyProperty" && field.element.type === "JsdocTypeObjectField") {
|
|
1104
|
+
if (typeof field.element.key === "object" && field.element.key.type === "JsdocTypeComputedMethod") {
|
|
1105
|
+
throw new Error("Computed method may not be readonly");
|
|
1106
|
+
}
|
|
1107
|
+
field.element.readonly = true;
|
|
1108
|
+
result.elements.push(field.element);
|
|
1109
|
+
} else {
|
|
1110
|
+
throw new UnexpectedTypeError(field);
|
|
1111
|
+
}
|
|
1112
|
+
if (parser.lexer.current.startOfLine) {
|
|
1113
|
+
separator ??= "linebreak";
|
|
1114
|
+
parser.consume(",") || parser.consume(";");
|
|
1115
|
+
} else if (parser.consume(",")) {
|
|
1116
|
+
if (parser.lexer.current.startOfLine) {
|
|
1117
|
+
separator = "comma-and-linebreak";
|
|
1118
|
+
} else {
|
|
1119
|
+
separator = "comma";
|
|
1120
|
+
}
|
|
1121
|
+
} else if (parser.consume(";")) {
|
|
1122
|
+
if (parser.lexer.current.startOfLine) {
|
|
1123
|
+
separator = "semicolon-and-linebreak";
|
|
1124
|
+
} else {
|
|
1125
|
+
separator = "semicolon";
|
|
1126
|
+
}
|
|
1127
|
+
} else {
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
const type = parser.lexer.current.type;
|
|
1131
|
+
if (type === "}") {
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
result.meta.separator = separator ?? "comma";
|
|
1136
|
+
if ((separator ?? "").endsWith("linebreak")) {
|
|
1137
|
+
result.meta.propertyIndent = " ";
|
|
1138
|
+
}
|
|
1139
|
+
if (!parser.consume("}")) {
|
|
1140
|
+
throw new Error("Unterminated record type. Missing '}'");
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
return result;
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// src/parslets/ObjectFieldParslet.ts
|
|
1149
|
+
function createObjectFieldParslet({ allowSquaredProperties, allowKeyTypes, allowReadonly, allowOptional }) {
|
|
1150
|
+
return composeParslet({
|
|
1151
|
+
name: "objectFieldParslet",
|
|
1152
|
+
precedence: 3 /* KEY_VALUE */,
|
|
1153
|
+
accept: (type) => type === ":",
|
|
1154
|
+
parseInfix: (parser, left) => {
|
|
1155
|
+
let optional = false;
|
|
1156
|
+
let readonlyProperty = false;
|
|
1157
|
+
if (allowOptional && left.type === "JsdocTypeNullable") {
|
|
1158
|
+
optional = true;
|
|
1159
|
+
left = left.element;
|
|
1160
|
+
}
|
|
1161
|
+
if (allowReadonly && left.type === "JsdocTypeReadonlyProperty") {
|
|
1162
|
+
readonlyProperty = true;
|
|
1163
|
+
left = left.element;
|
|
1164
|
+
}
|
|
1165
|
+
const parentParser = parser.baseParser ?? parser;
|
|
1166
|
+
parentParser.acceptLexerState(parser);
|
|
1167
|
+
if (left.type === "JsdocTypeNumber" || left.type === "JsdocTypeName" || left.type === "JsdocTypeStringValue" || isSquaredProperty(left)) {
|
|
1168
|
+
if (isSquaredProperty(left) && !allowSquaredProperties) {
|
|
1169
|
+
throw new UnexpectedTypeError(left);
|
|
1170
|
+
}
|
|
1171
|
+
parentParser.consume(":");
|
|
1172
|
+
let quote2;
|
|
1173
|
+
if (left.type === "JsdocTypeStringValue") {
|
|
1174
|
+
quote2 = left.meta.quote;
|
|
1175
|
+
}
|
|
1176
|
+
const right = parentParser.parseType(3 /* KEY_VALUE */);
|
|
1177
|
+
parser.acceptLexerState(parentParser);
|
|
1178
|
+
return {
|
|
1179
|
+
type: "JsdocTypeObjectField",
|
|
1180
|
+
/* c8 ignore next -- Guard; not needed anymore? */
|
|
1181
|
+
key: isSquaredProperty(left) ? left : left.value.toString(),
|
|
1182
|
+
right,
|
|
1183
|
+
optional,
|
|
1184
|
+
readonly: readonlyProperty,
|
|
1185
|
+
meta: {
|
|
1186
|
+
quote: quote2
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
} else {
|
|
1190
|
+
if (!allowKeyTypes) {
|
|
1191
|
+
throw new UnexpectedTypeError(left);
|
|
1192
|
+
}
|
|
1193
|
+
parentParser.consume(":");
|
|
1194
|
+
const right = parentParser.parseType(3 /* KEY_VALUE */);
|
|
1195
|
+
parser.acceptLexerState(parentParser);
|
|
1196
|
+
return {
|
|
1197
|
+
type: "JsdocTypeJsdocObjectField",
|
|
1198
|
+
left: assertRootResult(left),
|
|
1199
|
+
right
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// src/parslets/KeyValueParslet.ts
|
|
1207
|
+
function createKeyValueParslet({ allowOptional, allowVariadic, acceptParameterList }) {
|
|
1208
|
+
return composeParslet({
|
|
1209
|
+
name: "keyValueParslet",
|
|
1210
|
+
precedence: 3 /* KEY_VALUE */,
|
|
1211
|
+
accept: (type) => type === ":",
|
|
1212
|
+
parseInfix: (parser, left) => {
|
|
1213
|
+
let optional = false;
|
|
1214
|
+
let variadic = false;
|
|
1215
|
+
if (allowOptional && left.type === "JsdocTypeNullable") {
|
|
1216
|
+
optional = true;
|
|
1217
|
+
left = left.element;
|
|
1218
|
+
}
|
|
1219
|
+
if (allowVariadic && left.type === "JsdocTypeVariadic" && left.element !== void 0) {
|
|
1220
|
+
variadic = true;
|
|
1221
|
+
left = left.element;
|
|
1222
|
+
}
|
|
1223
|
+
if (left.type !== "JsdocTypeName") {
|
|
1224
|
+
if (acceptParameterList !== void 0 && left.type === "JsdocTypeParameterList") {
|
|
1225
|
+
parser.consume(":");
|
|
1226
|
+
return left;
|
|
1227
|
+
}
|
|
1228
|
+
throw new UnexpectedTypeError(left);
|
|
1229
|
+
}
|
|
1230
|
+
parser.consume(":");
|
|
1231
|
+
const right = parser.parseType(3 /* KEY_VALUE */);
|
|
1232
|
+
return {
|
|
1233
|
+
type: "JsdocTypeKeyValue",
|
|
1234
|
+
key: left.value,
|
|
1235
|
+
right,
|
|
1236
|
+
optional,
|
|
1237
|
+
variadic
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// src/grammars/jsdocGrammar.ts
|
|
1244
|
+
var jsdocBaseGrammar = [
|
|
1245
|
+
...baseGrammar,
|
|
1246
|
+
createFunctionParslet({
|
|
1247
|
+
allowWithoutParenthesis: true,
|
|
1248
|
+
allowNamedParameters: ["this", "new"],
|
|
1249
|
+
allowNoReturnType: true,
|
|
1250
|
+
allowNewAsFunctionKeyword: false
|
|
1251
|
+
}),
|
|
1252
|
+
stringValueParslet,
|
|
1253
|
+
createSpecialNamePathParslet({
|
|
1254
|
+
allowedTypes: ["module", "external", "event"],
|
|
1255
|
+
pathGrammar
|
|
1256
|
+
}),
|
|
1257
|
+
createVariadicParslet({
|
|
1258
|
+
allowEnclosingBrackets: true,
|
|
1259
|
+
allowPostfix: true
|
|
1260
|
+
}),
|
|
1261
|
+
createNameParslet({
|
|
1262
|
+
allowedAdditionalTokens: ["keyof"]
|
|
1263
|
+
}),
|
|
1264
|
+
symbolParslet,
|
|
1265
|
+
arrayBracketsParslet,
|
|
1266
|
+
createNamePathParslet({
|
|
1267
|
+
allowSquareBracketsOnAnyType: false,
|
|
1268
|
+
allowJsdocNamePaths: true,
|
|
1269
|
+
pathGrammar
|
|
1270
|
+
})
|
|
1271
|
+
];
|
|
1272
|
+
var jsdocGrammar = [
|
|
1273
|
+
...jsdocBaseGrammar,
|
|
1274
|
+
createObjectParslet({
|
|
1275
|
+
// jsdoc syntax allows full types as keys, so we need to pull in the full grammar here
|
|
1276
|
+
// we leave out the object type deliberately
|
|
1277
|
+
objectFieldGrammar: [
|
|
1278
|
+
createNameParslet({
|
|
1279
|
+
allowedAdditionalTokens: ["typeof", "module", "in"]
|
|
1280
|
+
}),
|
|
1281
|
+
createObjectFieldParslet({
|
|
1282
|
+
allowSquaredProperties: false,
|
|
1283
|
+
allowKeyTypes: true,
|
|
1284
|
+
allowOptional: false,
|
|
1285
|
+
allowReadonly: false
|
|
1286
|
+
}),
|
|
1287
|
+
...jsdocBaseGrammar
|
|
1288
|
+
],
|
|
1289
|
+
allowKeyTypes: true
|
|
1290
|
+
}),
|
|
1291
|
+
createKeyValueParslet({
|
|
1292
|
+
allowOptional: true,
|
|
1293
|
+
allowVariadic: true
|
|
1294
|
+
})
|
|
1295
|
+
];
|
|
1296
|
+
var jsdocNameGrammar = [
|
|
1297
|
+
genericParslet,
|
|
1298
|
+
arrayBracketsParslet,
|
|
1299
|
+
createNameParslet({
|
|
1300
|
+
allowedAdditionalTokens: baseNameTokens
|
|
1301
|
+
})
|
|
1302
|
+
];
|
|
1303
|
+
var jsdocNamePathGrammar = [
|
|
1304
|
+
genericParslet,
|
|
1305
|
+
arrayBracketsParslet,
|
|
1306
|
+
createNameParslet({
|
|
1307
|
+
allowedAdditionalTokens: baseNameTokens
|
|
1308
|
+
}),
|
|
1309
|
+
createNamePathParslet({
|
|
1310
|
+
allowSquareBracketsOnAnyType: false,
|
|
1311
|
+
allowJsdocNamePaths: true,
|
|
1312
|
+
pathGrammar
|
|
1313
|
+
})
|
|
1314
|
+
];
|
|
1315
|
+
var jsdocNamePathSpecialGrammar = [
|
|
1316
|
+
createSpecialNamePathParslet({
|
|
1317
|
+
allowedTypes: ["module", "external", "event"],
|
|
1318
|
+
pathGrammar
|
|
1319
|
+
}),
|
|
1320
|
+
...jsdocNamePathGrammar
|
|
1321
|
+
];
|
|
1322
|
+
|
|
1323
|
+
// src/parslets/TypeOfParslet.ts
|
|
1324
|
+
var typeOfParslet = composeParslet({
|
|
1325
|
+
name: "typeOfParslet",
|
|
1326
|
+
accept: (type) => type === "typeof",
|
|
1327
|
+
parsePrefix: (parser) => {
|
|
1328
|
+
parser.consume("typeof");
|
|
1329
|
+
return {
|
|
1330
|
+
type: "JsdocTypeTypeof",
|
|
1331
|
+
element: parser.parseType(13 /* KEY_OF_TYPE_OF */)
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
|
|
1336
|
+
// src/grammars/closureGrammar.ts
|
|
1337
|
+
var objectFieldGrammar = [
|
|
1338
|
+
createNameParslet({
|
|
1339
|
+
allowedAdditionalTokens: [
|
|
1340
|
+
"typeof",
|
|
1341
|
+
"module",
|
|
1342
|
+
"keyof",
|
|
1343
|
+
"event",
|
|
1344
|
+
"external",
|
|
1345
|
+
"in"
|
|
1346
|
+
]
|
|
1347
|
+
}),
|
|
1348
|
+
nullableParslet,
|
|
1349
|
+
optionalParslet,
|
|
1350
|
+
stringValueParslet,
|
|
1351
|
+
numberParslet,
|
|
1352
|
+
createObjectFieldParslet({
|
|
1353
|
+
allowSquaredProperties: false,
|
|
1354
|
+
allowKeyTypes: false,
|
|
1355
|
+
allowOptional: false,
|
|
1356
|
+
allowReadonly: false
|
|
1357
|
+
})
|
|
1358
|
+
];
|
|
1359
|
+
var closureGrammar = [
|
|
1360
|
+
...baseGrammar,
|
|
1361
|
+
createObjectParslet({
|
|
1362
|
+
allowKeyTypes: false,
|
|
1363
|
+
objectFieldGrammar
|
|
1364
|
+
}),
|
|
1365
|
+
createNameParslet({
|
|
1366
|
+
allowedAdditionalTokens: ["event", "external", "in"]
|
|
1367
|
+
}),
|
|
1368
|
+
typeOfParslet,
|
|
1369
|
+
createFunctionParslet({
|
|
1370
|
+
allowWithoutParenthesis: false,
|
|
1371
|
+
allowNamedParameters: ["this", "new"],
|
|
1372
|
+
allowNoReturnType: true,
|
|
1373
|
+
allowNewAsFunctionKeyword: false
|
|
1374
|
+
}),
|
|
1375
|
+
createVariadicParslet({
|
|
1376
|
+
allowEnclosingBrackets: false,
|
|
1377
|
+
allowPostfix: false
|
|
1378
|
+
}),
|
|
1379
|
+
// additional name parslet is needed for some special cases
|
|
1380
|
+
createNameParslet({
|
|
1381
|
+
allowedAdditionalTokens: ["keyof"]
|
|
1382
|
+
}),
|
|
1383
|
+
createSpecialNamePathParslet({
|
|
1384
|
+
allowedTypes: ["module"],
|
|
1385
|
+
pathGrammar
|
|
1386
|
+
}),
|
|
1387
|
+
createNamePathParslet({
|
|
1388
|
+
allowSquareBracketsOnAnyType: false,
|
|
1389
|
+
allowJsdocNamePaths: true,
|
|
1390
|
+
pathGrammar
|
|
1391
|
+
}),
|
|
1392
|
+
createKeyValueParslet({
|
|
1393
|
+
allowOptional: false,
|
|
1394
|
+
allowVariadic: false
|
|
1395
|
+
}),
|
|
1396
|
+
symbolParslet
|
|
1397
|
+
];
|
|
1398
|
+
var closureNameGrammar = [
|
|
1399
|
+
genericParslet,
|
|
1400
|
+
arrayBracketsParslet,
|
|
1401
|
+
createNameParslet({
|
|
1402
|
+
allowedAdditionalTokens: baseNameTokens
|
|
1403
|
+
})
|
|
1404
|
+
];
|
|
1405
|
+
var closureNamePathGrammar = [
|
|
1406
|
+
genericParslet,
|
|
1407
|
+
arrayBracketsParslet,
|
|
1408
|
+
createNameParslet({
|
|
1409
|
+
allowedAdditionalTokens: baseNameTokens
|
|
1410
|
+
}),
|
|
1411
|
+
createNamePathParslet({
|
|
1412
|
+
allowSquareBracketsOnAnyType: false,
|
|
1413
|
+
allowJsdocNamePaths: true,
|
|
1414
|
+
pathGrammar
|
|
1415
|
+
})
|
|
1416
|
+
];
|
|
1417
|
+
var closureNamePathSpecialGrammar = [
|
|
1418
|
+
createSpecialNamePathParslet({
|
|
1419
|
+
allowedTypes: ["module"],
|
|
1420
|
+
pathGrammar
|
|
1421
|
+
}),
|
|
1422
|
+
...closureNamePathGrammar
|
|
1423
|
+
];
|
|
1424
|
+
|
|
1425
|
+
// src/parslets/assertsParslet.ts
|
|
1426
|
+
var assertsParslet = composeParslet({
|
|
1427
|
+
name: "assertsParslet",
|
|
1428
|
+
accept: (type) => type === "asserts",
|
|
1429
|
+
parsePrefix: (parser) => {
|
|
1430
|
+
parser.consume("asserts");
|
|
1431
|
+
const left = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
1432
|
+
if (left.type !== "JsdocTypeName") {
|
|
1433
|
+
throw new UnexpectedTypeError(left, "A typescript asserts always has to have a name.");
|
|
1434
|
+
}
|
|
1435
|
+
if (!parser.consume("is")) {
|
|
1436
|
+
return {
|
|
1437
|
+
type: "JsdocTypeAssertsPlain",
|
|
1438
|
+
element: left
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
return {
|
|
1442
|
+
type: "JsdocTypeAsserts",
|
|
1443
|
+
left,
|
|
1444
|
+
right: assertRootResult(parser.parseIntermediateType(8 /* INFIX */))
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1449
|
+
// src/parslets/FunctionPropertyParslet.ts
|
|
1450
|
+
var functionPropertyParslet = composeParslet({
|
|
1451
|
+
name: "functionPropertyParslet",
|
|
1452
|
+
accept: (type, next) => type === "new" && (next === "(" || next === "<") || type === "Identifier" && (next === "(" || next === "<") || type === "StringValue" && (next === "(" || next === "<") || type === "(" || type === "<",
|
|
1453
|
+
parsePrefix: (parser) => {
|
|
1454
|
+
let result;
|
|
1455
|
+
const returnType = {
|
|
1456
|
+
type: "JsdocTypeName",
|
|
1457
|
+
value: "void"
|
|
1458
|
+
};
|
|
1459
|
+
const newKeyword = parser.consume("new");
|
|
1460
|
+
if (newKeyword) {
|
|
1461
|
+
result = {
|
|
1462
|
+
type: "JsdocTypeConstructorSignature",
|
|
1463
|
+
parameters: [],
|
|
1464
|
+
returnType
|
|
1465
|
+
};
|
|
1466
|
+
} else {
|
|
1467
|
+
const text = parser.lexer.current.text;
|
|
1468
|
+
const identifier = parser.consume("Identifier");
|
|
1469
|
+
if (identifier) {
|
|
1470
|
+
result = {
|
|
1471
|
+
type: "JsdocTypeMethodSignature",
|
|
1472
|
+
name: text,
|
|
1473
|
+
meta: {
|
|
1474
|
+
quote: void 0
|
|
1475
|
+
},
|
|
1476
|
+
parameters: [],
|
|
1477
|
+
returnType
|
|
1478
|
+
};
|
|
1479
|
+
} else {
|
|
1480
|
+
const text2 = parser.lexer.current.text;
|
|
1481
|
+
const stringValue = parser.consume("StringValue");
|
|
1482
|
+
if (stringValue) {
|
|
1483
|
+
result = {
|
|
1484
|
+
type: "JsdocTypeMethodSignature",
|
|
1485
|
+
name: text2.slice(1, -1),
|
|
1486
|
+
meta: {
|
|
1487
|
+
quote: text2.startsWith('"') ? "double" : "single"
|
|
1488
|
+
},
|
|
1489
|
+
parameters: [],
|
|
1490
|
+
returnType
|
|
1491
|
+
};
|
|
1492
|
+
} else {
|
|
1493
|
+
result = {
|
|
1494
|
+
type: "JsdocTypeCallSignature",
|
|
1495
|
+
parameters: [],
|
|
1496
|
+
returnType
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
const typeParameters = [];
|
|
1502
|
+
if (parser.consume("<")) {
|
|
1503
|
+
do {
|
|
1504
|
+
let defaultValue = void 0;
|
|
1505
|
+
let name = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
1506
|
+
if (name.type === "JsdocTypeOptional") {
|
|
1507
|
+
name = name.element;
|
|
1508
|
+
defaultValue = parser.parseType(10 /* SYMBOL */);
|
|
1509
|
+
}
|
|
1510
|
+
if (name.type !== "JsdocTypeName") {
|
|
1511
|
+
throw new UnexpectedTypeError(name);
|
|
1512
|
+
}
|
|
1513
|
+
let constraint = void 0;
|
|
1514
|
+
if (parser.consume("extends")) {
|
|
1515
|
+
constraint = parser.parseType(10 /* SYMBOL */);
|
|
1516
|
+
if (constraint.type === "JsdocTypeOptional") {
|
|
1517
|
+
constraint = constraint.element;
|
|
1518
|
+
defaultValue = parser.parseType(10 /* SYMBOL */);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
const typeParameter = {
|
|
1522
|
+
type: "JsdocTypeTypeParameter",
|
|
1523
|
+
name
|
|
1524
|
+
};
|
|
1525
|
+
if (constraint !== void 0) {
|
|
1526
|
+
typeParameter.constraint = constraint;
|
|
1527
|
+
}
|
|
1528
|
+
if (defaultValue !== void 0) {
|
|
1529
|
+
typeParameter.defaultValue = defaultValue;
|
|
1530
|
+
}
|
|
1531
|
+
typeParameters.push(typeParameter);
|
|
1532
|
+
if (parser.consume(">")) {
|
|
1533
|
+
break;
|
|
1534
|
+
}
|
|
1535
|
+
} while (parser.consume(","));
|
|
1536
|
+
result.typeParameters = typeParameters;
|
|
1537
|
+
}
|
|
1538
|
+
const hasParenthesis = parser.lexer.current.type === "(";
|
|
1539
|
+
if (!hasParenthesis) {
|
|
1540
|
+
throw new Error("function property is missing parameter list");
|
|
1541
|
+
}
|
|
1542
|
+
return result;
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
|
|
1546
|
+
// src/parslets/TupleParslet.ts
|
|
1547
|
+
function createTupleParslet({ allowQuestionMark }) {
|
|
1548
|
+
return composeParslet({
|
|
1549
|
+
name: "tupleParslet",
|
|
1550
|
+
accept: (type) => type === "[",
|
|
1551
|
+
parsePrefix: (parser) => {
|
|
1552
|
+
parser.consume("[");
|
|
1553
|
+
const result = {
|
|
1554
|
+
type: "JsdocTypeTuple",
|
|
1555
|
+
elements: []
|
|
1556
|
+
};
|
|
1557
|
+
if (parser.consume("]")) {
|
|
1558
|
+
return result;
|
|
1559
|
+
}
|
|
1560
|
+
const typeList = parser.parseIntermediateType(0 /* ALL */);
|
|
1561
|
+
if (typeList.type === "JsdocTypeParameterList") {
|
|
1562
|
+
if (typeList.elements[0].type === "JsdocTypeKeyValue") {
|
|
1563
|
+
result.elements = typeList.elements.map(assertPlainKeyValueResult);
|
|
1564
|
+
} else {
|
|
1565
|
+
result.elements = typeList.elements.map(assertRootResult);
|
|
1566
|
+
}
|
|
1567
|
+
} else {
|
|
1568
|
+
if (typeList.type === "JsdocTypeKeyValue") {
|
|
1569
|
+
result.elements = [assertPlainKeyValueResult(typeList)];
|
|
1570
|
+
} else {
|
|
1571
|
+
result.elements = [assertRootResult(typeList)];
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (!parser.consume("]")) {
|
|
1575
|
+
throw new Error("Unterminated '['");
|
|
1576
|
+
}
|
|
1577
|
+
if (result.elements.some((e) => e.type === "JsdocTypeUnknown")) {
|
|
1578
|
+
throw new Error("Question mark in tuple not allowed");
|
|
1579
|
+
}
|
|
1580
|
+
return result;
|
|
1581
|
+
}
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// src/parslets/KeyOfParslet.ts
|
|
1586
|
+
var keyOfParslet = composeParslet({
|
|
1587
|
+
name: "keyOfParslet",
|
|
1588
|
+
accept: (type) => type === "keyof",
|
|
1589
|
+
parsePrefix: (parser) => {
|
|
1590
|
+
parser.consume("keyof");
|
|
1591
|
+
return {
|
|
1592
|
+
type: "JsdocTypeKeyof",
|
|
1593
|
+
element: assertRootResult(parser.parseType(13 /* KEY_OF_TYPE_OF */))
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
|
|
1598
|
+
// src/parslets/ImportParslet.ts
|
|
1599
|
+
var importParslet = composeParslet({
|
|
1600
|
+
name: "importParslet",
|
|
1601
|
+
accept: (type) => type === "import",
|
|
1602
|
+
parsePrefix: (parser) => {
|
|
1603
|
+
parser.consume("import");
|
|
1604
|
+
if (!parser.consume("(")) {
|
|
1605
|
+
throw new Error("Missing parenthesis after import keyword");
|
|
1606
|
+
}
|
|
1607
|
+
const path = parser.parseType(7 /* PREFIX */);
|
|
1608
|
+
if (path.type !== "JsdocTypeStringValue") {
|
|
1609
|
+
throw new Error("Only string values are allowed as paths for imports");
|
|
1610
|
+
}
|
|
1611
|
+
if (!parser.consume(")")) {
|
|
1612
|
+
throw new Error("Missing closing parenthesis after import keyword");
|
|
1613
|
+
}
|
|
1614
|
+
return {
|
|
1615
|
+
type: "JsdocTypeImport",
|
|
1616
|
+
element: path
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1621
|
+
// src/parslets/ReadonlyPropertyParslet.ts
|
|
1622
|
+
var readonlyPropertyParslet = composeParslet({
|
|
1623
|
+
name: "readonlyPropertyParslet",
|
|
1624
|
+
accept: (type, next) => type === "readonly" && next !== ":",
|
|
1625
|
+
parsePrefix: (parser) => {
|
|
1626
|
+
parser.consume("readonly");
|
|
1627
|
+
return {
|
|
1628
|
+
type: "JsdocTypeReadonlyProperty",
|
|
1629
|
+
element: parser.parseIntermediateType(3 /* KEY_VALUE */)
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
|
|
1634
|
+
// src/parslets/ArrowFunctionParslet.ts
|
|
1635
|
+
var arrowFunctionParslet = composeParslet({
|
|
1636
|
+
name: "arrowFunctionParslet",
|
|
1637
|
+
precedence: 15 /* ARROW */,
|
|
1638
|
+
accept: (type) => type === "=>",
|
|
1639
|
+
parseInfix: (parser, left) => {
|
|
1640
|
+
parser.consume("=>");
|
|
1641
|
+
return {
|
|
1642
|
+
type: "JsdocTypeFunction",
|
|
1643
|
+
parameters: getParameters(left).map(assertPlainKeyValueOrNameResult),
|
|
1644
|
+
arrow: true,
|
|
1645
|
+
constructor: false,
|
|
1646
|
+
parenthesis: true,
|
|
1647
|
+
returnType: parser.parseType(2 /* OBJECT */)
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
});
|
|
1651
|
+
|
|
1652
|
+
// src/parslets/GenericArrowFunctionParslet.ts
|
|
1653
|
+
var genericArrowFunctionParslet = composeParslet({
|
|
1654
|
+
name: "genericArrowFunctionParslet",
|
|
1655
|
+
accept: (type) => type === "<",
|
|
1656
|
+
parsePrefix: (parser) => {
|
|
1657
|
+
const typeParameters = [];
|
|
1658
|
+
parser.consume("<");
|
|
1659
|
+
do {
|
|
1660
|
+
let defaultValue = void 0;
|
|
1661
|
+
let name = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
1662
|
+
if (name.type === "JsdocTypeOptional") {
|
|
1663
|
+
name = name.element;
|
|
1664
|
+
defaultValue = parser.parseType(10 /* SYMBOL */);
|
|
1665
|
+
}
|
|
1666
|
+
if (name.type !== "JsdocTypeName") {
|
|
1667
|
+
throw new UnexpectedTypeError(name);
|
|
1668
|
+
}
|
|
1669
|
+
let constraint = void 0;
|
|
1670
|
+
if (parser.consume("extends")) {
|
|
1671
|
+
constraint = parser.parseType(10 /* SYMBOL */);
|
|
1672
|
+
if (constraint.type === "JsdocTypeOptional") {
|
|
1673
|
+
constraint = constraint.element;
|
|
1674
|
+
defaultValue = parser.parseType(10 /* SYMBOL */);
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
const typeParameter = {
|
|
1678
|
+
type: "JsdocTypeTypeParameter",
|
|
1679
|
+
name
|
|
1680
|
+
};
|
|
1681
|
+
if (constraint !== void 0) {
|
|
1682
|
+
typeParameter.constraint = constraint;
|
|
1683
|
+
}
|
|
1684
|
+
if (defaultValue !== void 0) {
|
|
1685
|
+
typeParameter.defaultValue = defaultValue;
|
|
1686
|
+
}
|
|
1687
|
+
typeParameters.push(typeParameter);
|
|
1688
|
+
if (parser.consume(">")) {
|
|
1689
|
+
break;
|
|
1690
|
+
}
|
|
1691
|
+
} while (parser.consume(","));
|
|
1692
|
+
const functionBase = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
1693
|
+
functionBase.typeParameters = typeParameters;
|
|
1694
|
+
return functionBase;
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
|
|
1698
|
+
// src/parslets/IntersectionParslet.ts
|
|
1699
|
+
var intersectionParslet = composeParslet({
|
|
1700
|
+
name: "intersectionParslet",
|
|
1701
|
+
accept: (type) => type === "&",
|
|
1702
|
+
precedence: 6 /* INTERSECTION */,
|
|
1703
|
+
parseInfix: (parser, left) => {
|
|
1704
|
+
parser.consume("&");
|
|
1705
|
+
const elements = [];
|
|
1706
|
+
do {
|
|
1707
|
+
elements.push(parser.parseType(6 /* INTERSECTION */));
|
|
1708
|
+
} while (parser.consume("&"));
|
|
1709
|
+
return {
|
|
1710
|
+
type: "JsdocTypeIntersection",
|
|
1711
|
+
elements: [
|
|
1712
|
+
assertResultIsNotReservedWord(parser, assertRootResult(left)),
|
|
1713
|
+
...elements.map((element) => assertResultIsNotReservedWord(parser, element))
|
|
1714
|
+
]
|
|
1715
|
+
};
|
|
1716
|
+
}
|
|
1717
|
+
});
|
|
1718
|
+
|
|
1719
|
+
// src/parslets/predicateParslet.ts
|
|
1720
|
+
var predicateParslet = composeParslet({
|
|
1721
|
+
name: "predicateParslet",
|
|
1722
|
+
precedence: 8 /* INFIX */,
|
|
1723
|
+
accept: (type) => type === "is",
|
|
1724
|
+
parseInfix: (parser, left) => {
|
|
1725
|
+
if (left.type !== "JsdocTypeName") {
|
|
1726
|
+
throw new UnexpectedTypeError(left, "A typescript predicate always has to have a name on the left side.");
|
|
1727
|
+
}
|
|
1728
|
+
parser.consume("is");
|
|
1729
|
+
return {
|
|
1730
|
+
type: "JsdocTypePredicate",
|
|
1731
|
+
left,
|
|
1732
|
+
right: assertRootResult(parser.parseIntermediateType(8 /* INFIX */))
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
|
|
1737
|
+
// src/lexer/Lexer.ts
|
|
1738
|
+
var breakingWhitespaceRegex = /^\s*\n\s*/v;
|
|
1739
|
+
var Lexer = class _Lexer {
|
|
1740
|
+
text = "";
|
|
1741
|
+
lexerRules;
|
|
1742
|
+
current;
|
|
1743
|
+
next;
|
|
1744
|
+
previous;
|
|
1745
|
+
static create(lexerRules, text) {
|
|
1746
|
+
const current = this.read(lexerRules, text);
|
|
1747
|
+
text = current.text;
|
|
1748
|
+
const next = this.read(lexerRules, text);
|
|
1749
|
+
text = next.text;
|
|
1750
|
+
return new _Lexer(lexerRules, text, void 0, current.token, next.token);
|
|
1751
|
+
}
|
|
1752
|
+
constructor(lexerRules, text, previous, current, next) {
|
|
1753
|
+
this.lexerRules = lexerRules;
|
|
1754
|
+
this.text = text;
|
|
1755
|
+
this.previous = previous;
|
|
1756
|
+
this.current = current;
|
|
1757
|
+
this.next = next;
|
|
1758
|
+
}
|
|
1759
|
+
static read(lexerRules, text, startOfLine = false) {
|
|
1760
|
+
startOfLine ||= breakingWhitespaceRegex.test(text);
|
|
1761
|
+
const start = text.length;
|
|
1762
|
+
const initialWhitespace = /^\s+/v.exec(text)?.[0] ?? "";
|
|
1763
|
+
text = text.trimStart();
|
|
1764
|
+
const trimmed = start - text.length;
|
|
1765
|
+
for (const rule of lexerRules) {
|
|
1766
|
+
const partial = rule(text);
|
|
1767
|
+
if (partial !== null) {
|
|
1768
|
+
const initialLines = initialWhitespace.split("\n");
|
|
1769
|
+
const currentLines = partial.text.split("\n");
|
|
1770
|
+
const token = {
|
|
1771
|
+
...partial,
|
|
1772
|
+
startOfLine,
|
|
1773
|
+
reduced: trimmed + partial.text.length,
|
|
1774
|
+
line: initialLines.length + currentLines.length - 2,
|
|
1775
|
+
column: currentLines.length === 1 ? (initialLines.at(-1)?.length ?? 0) + (currentLines.at(-1)?.length ?? 0) : currentLines.at(-1)?.length ?? 0
|
|
1776
|
+
};
|
|
1777
|
+
text = text.slice(token.text.length);
|
|
1778
|
+
return { text, token };
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
throw new Error(`Unexpected Token ${text}`);
|
|
1782
|
+
}
|
|
1783
|
+
remaining() {
|
|
1784
|
+
return this.next.text + this.text;
|
|
1785
|
+
}
|
|
1786
|
+
advance() {
|
|
1787
|
+
const next = _Lexer.read(this.lexerRules, this.text);
|
|
1788
|
+
return new _Lexer(
|
|
1789
|
+
this.lexerRules,
|
|
1790
|
+
next.text,
|
|
1791
|
+
this.current,
|
|
1792
|
+
this.next,
|
|
1793
|
+
next.token
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
|
|
1798
|
+
// src/parslets/ObjectSquaredPropertyParslet.ts
|
|
1799
|
+
var objectSquaredPropertyParslet = composeParslet({
|
|
1800
|
+
name: "objectSquarePropertyParslet",
|
|
1801
|
+
accept: (type) => type === "[",
|
|
1802
|
+
parsePrefix: (parser) => {
|
|
1803
|
+
if (parser.baseParser === void 0) {
|
|
1804
|
+
throw new Error("Only allowed inside object grammar");
|
|
1805
|
+
}
|
|
1806
|
+
parser.consume("[");
|
|
1807
|
+
let innerBracketType;
|
|
1808
|
+
if (parser.externalParsers?.computedPropertyParser === void 0) {
|
|
1809
|
+
try {
|
|
1810
|
+
innerBracketType = parser.parseIntermediateType(2 /* OBJECT */);
|
|
1811
|
+
} catch (err) {
|
|
1812
|
+
throw new Error("Error parsing value inside square bracketed property.", {
|
|
1813
|
+
cause: err
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
let result;
|
|
1818
|
+
if (
|
|
1819
|
+
// Looks like an object field because of `key: value`, but is
|
|
1820
|
+
// shaping to be an index signature
|
|
1821
|
+
innerBracketType?.type === "JsdocTypeObjectField" && typeof innerBracketType.key === "string" && !innerBracketType.optional && !innerBracketType.readonly && innerBracketType.right !== void 0
|
|
1822
|
+
) {
|
|
1823
|
+
const key = innerBracketType.key;
|
|
1824
|
+
if (!parser.consume("]")) {
|
|
1825
|
+
throw new Error("Unterminated square brackets");
|
|
1826
|
+
}
|
|
1827
|
+
if (!parser.consume(":")) {
|
|
1828
|
+
throw new Error("Incomplete index signature");
|
|
1829
|
+
}
|
|
1830
|
+
const parentParser = parser.baseParser;
|
|
1831
|
+
parentParser.acceptLexerState(parser);
|
|
1832
|
+
innerBracketType.key = {
|
|
1833
|
+
type: "JsdocTypeIndexSignature",
|
|
1834
|
+
key,
|
|
1835
|
+
right: innerBracketType.right
|
|
1836
|
+
};
|
|
1837
|
+
innerBracketType.optional = false;
|
|
1838
|
+
innerBracketType.meta.quote = void 0;
|
|
1839
|
+
result = innerBracketType;
|
|
1840
|
+
const right = parentParser.parseType(4 /* INDEX_BRACKETS */);
|
|
1841
|
+
result.right = right;
|
|
1842
|
+
parser.acceptLexerState(parentParser);
|
|
1843
|
+
} else if (
|
|
1844
|
+
// Looks like a name, but is shaping to be a mapped type clause
|
|
1845
|
+
innerBracketType?.type === "JsdocTypeName" && parser.consume("in")
|
|
1846
|
+
) {
|
|
1847
|
+
const parentParser = parser.baseParser;
|
|
1848
|
+
parentParser.acceptLexerState(parser);
|
|
1849
|
+
const mappedTypeRight = parentParser.parseType(4 /* INDEX_BRACKETS */);
|
|
1850
|
+
if (!parentParser.consume("]")) {
|
|
1851
|
+
throw new Error("Unterminated square brackets");
|
|
1852
|
+
}
|
|
1853
|
+
const optional = parentParser.consume("?");
|
|
1854
|
+
if (!parentParser.consume(":")) {
|
|
1855
|
+
throw new Error("Incomplete mapped type clause: missing colon");
|
|
1856
|
+
}
|
|
1857
|
+
const right = parentParser.parseType(4 /* INDEX_BRACKETS */);
|
|
1858
|
+
result = {
|
|
1859
|
+
type: "JsdocTypeObjectField",
|
|
1860
|
+
optional,
|
|
1861
|
+
readonly: false,
|
|
1862
|
+
meta: {
|
|
1863
|
+
quote: void 0
|
|
1864
|
+
},
|
|
1865
|
+
key: {
|
|
1866
|
+
type: "JsdocTypeMappedType",
|
|
1867
|
+
key: innerBracketType.value,
|
|
1868
|
+
right: mappedTypeRight
|
|
1869
|
+
},
|
|
1870
|
+
right
|
|
1871
|
+
};
|
|
1872
|
+
parser.acceptLexerState(parentParser);
|
|
1873
|
+
} else {
|
|
1874
|
+
if (parser.externalParsers?.computedPropertyParser !== void 0) {
|
|
1875
|
+
let remaining = parser.lexer.current.text + parser.lexer.remaining();
|
|
1876
|
+
let checkingText = remaining;
|
|
1877
|
+
while (checkingText !== "") {
|
|
1878
|
+
try {
|
|
1879
|
+
innerBracketType = parser.externalParsers.computedPropertyParser(
|
|
1880
|
+
checkingText
|
|
1881
|
+
);
|
|
1882
|
+
break;
|
|
1883
|
+
} catch (err) {
|
|
1884
|
+
}
|
|
1885
|
+
checkingText = checkingText.slice(0, -1);
|
|
1886
|
+
}
|
|
1887
|
+
remaining = remaining.slice(checkingText.length);
|
|
1888
|
+
const remainingTextParser = new Parser(
|
|
1889
|
+
parser.grammar,
|
|
1890
|
+
Lexer.create(parser.lexer.lexerRules, remaining),
|
|
1891
|
+
parser.baseParser,
|
|
1892
|
+
{
|
|
1893
|
+
externalParsers: {
|
|
1894
|
+
computedPropertyParser: parser.externalParsers.computedPropertyParser
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
);
|
|
1898
|
+
parser.acceptLexerState(remainingTextParser);
|
|
1899
|
+
}
|
|
1900
|
+
if (!parser.consume("]")) {
|
|
1901
|
+
throw new Error("Unterminated square brackets");
|
|
1902
|
+
}
|
|
1903
|
+
let optional = parser.consume("?");
|
|
1904
|
+
const typeParameters = [];
|
|
1905
|
+
if (parser.consume("<")) {
|
|
1906
|
+
do {
|
|
1907
|
+
let defaultValue = void 0;
|
|
1908
|
+
let name = parser.parseIntermediateType(10 /* SYMBOL */);
|
|
1909
|
+
if (name.type === "JsdocTypeOptional") {
|
|
1910
|
+
name = name.element;
|
|
1911
|
+
defaultValue = parser.parseType(10 /* SYMBOL */);
|
|
1912
|
+
}
|
|
1913
|
+
if (name.type !== "JsdocTypeName") {
|
|
1914
|
+
throw new UnexpectedTypeError(name);
|
|
1915
|
+
}
|
|
1916
|
+
let constraint = void 0;
|
|
1917
|
+
if (parser.consume("extends")) {
|
|
1918
|
+
constraint = parser.parseType(10 /* SYMBOL */);
|
|
1919
|
+
if (constraint.type === "JsdocTypeOptional") {
|
|
1920
|
+
constraint = constraint.element;
|
|
1921
|
+
defaultValue = parser.parseType(10 /* SYMBOL */);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
const typeParameter = {
|
|
1925
|
+
type: "JsdocTypeTypeParameter",
|
|
1926
|
+
name
|
|
1927
|
+
};
|
|
1928
|
+
if (constraint !== void 0) {
|
|
1929
|
+
typeParameter.constraint = constraint;
|
|
1930
|
+
}
|
|
1931
|
+
if (defaultValue !== void 0) {
|
|
1932
|
+
typeParameter.defaultValue = defaultValue;
|
|
1933
|
+
}
|
|
1934
|
+
typeParameters.push(typeParameter);
|
|
1935
|
+
if (parser.consume(">")) {
|
|
1936
|
+
break;
|
|
1937
|
+
}
|
|
1938
|
+
} while (parser.consume(","));
|
|
1939
|
+
}
|
|
1940
|
+
let type;
|
|
1941
|
+
let key;
|
|
1942
|
+
const checkMiddle = () => {
|
|
1943
|
+
if (!optional) {
|
|
1944
|
+
optional = parser.consume("?");
|
|
1945
|
+
}
|
|
1946
|
+
};
|
|
1947
|
+
let right;
|
|
1948
|
+
const text = parser.lexer.current.type;
|
|
1949
|
+
if (text === "(") {
|
|
1950
|
+
const signatureParser = new Parser(
|
|
1951
|
+
[
|
|
1952
|
+
createKeyValueParslet({
|
|
1953
|
+
allowVariadic: true,
|
|
1954
|
+
allowOptional: true,
|
|
1955
|
+
acceptParameterList: true
|
|
1956
|
+
}),
|
|
1957
|
+
...parser.baseParser.grammar.flatMap((grammar) => {
|
|
1958
|
+
if (grammar.name === "keyValueParslet") {
|
|
1959
|
+
return [];
|
|
1960
|
+
}
|
|
1961
|
+
return [grammar];
|
|
1962
|
+
})
|
|
1963
|
+
],
|
|
1964
|
+
parser.lexer,
|
|
1965
|
+
parser
|
|
1966
|
+
);
|
|
1967
|
+
signatureParser.acceptLexerState(parser);
|
|
1968
|
+
const params = signatureParser.parseIntermediateType(2 /* OBJECT */);
|
|
1969
|
+
parser.acceptLexerState(signatureParser);
|
|
1970
|
+
const parameters = getParameters(params);
|
|
1971
|
+
type = "JsdocTypeComputedMethod";
|
|
1972
|
+
checkMiddle();
|
|
1973
|
+
parser.consume(":");
|
|
1974
|
+
const nextValue = parser.parseType(4 /* INDEX_BRACKETS */);
|
|
1975
|
+
key = {
|
|
1976
|
+
type,
|
|
1977
|
+
optional,
|
|
1978
|
+
value: innerBracketType,
|
|
1979
|
+
parameters,
|
|
1980
|
+
returnType: nextValue
|
|
1981
|
+
};
|
|
1982
|
+
if (typeParameters.length > 0) {
|
|
1983
|
+
key.typeParameters = typeParameters;
|
|
1984
|
+
}
|
|
1985
|
+
} else {
|
|
1986
|
+
type = "JsdocTypeComputedProperty";
|
|
1987
|
+
checkMiddle();
|
|
1988
|
+
if (!parser.consume(":")) {
|
|
1989
|
+
throw new Error("Incomplete computed property: missing colon");
|
|
1990
|
+
}
|
|
1991
|
+
right = parser.parseType(4 /* INDEX_BRACKETS */);
|
|
1992
|
+
key = {
|
|
1993
|
+
type,
|
|
1994
|
+
value: innerBracketType
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
result = {
|
|
1998
|
+
type: "JsdocTypeObjectField",
|
|
1999
|
+
optional: type === "JsdocTypeComputedMethod" ? false : optional,
|
|
2000
|
+
readonly: false,
|
|
2001
|
+
meta: {
|
|
2002
|
+
quote: void 0
|
|
2003
|
+
},
|
|
2004
|
+
key,
|
|
2005
|
+
right
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
return result;
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
|
|
2012
|
+
// src/parslets/ReadonlyArrayParslet.ts
|
|
2013
|
+
var readonlyArrayParslet = composeParslet({
|
|
2014
|
+
name: "readonlyArrayParslet",
|
|
2015
|
+
accept: (type) => type === "readonly",
|
|
2016
|
+
parsePrefix: (parser) => {
|
|
2017
|
+
parser.consume("readonly");
|
|
2018
|
+
return {
|
|
2019
|
+
type: "JsdocTypeReadonlyArray",
|
|
2020
|
+
element: assertArrayOrTupleResult(parser.parseIntermediateType(0 /* ALL */))
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
});
|
|
2024
|
+
|
|
2025
|
+
// src/parslets/ConditionalParslet.ts
|
|
2026
|
+
var conditionalParslet = composeParslet({
|
|
2027
|
+
name: "conditionalParslet",
|
|
2028
|
+
precedence: 8 /* INFIX */,
|
|
2029
|
+
accept: (type) => type === "extends",
|
|
2030
|
+
parseInfix: (parser, left) => {
|
|
2031
|
+
parser.consume("extends");
|
|
2032
|
+
const extendsType = assertRootResult(parser.parseType(13 /* KEY_OF_TYPE_OF */));
|
|
2033
|
+
parser.consume("?");
|
|
2034
|
+
const trueType = parser.parseType(8 /* INFIX */);
|
|
2035
|
+
parser.consume(":");
|
|
2036
|
+
return {
|
|
2037
|
+
type: "JsdocTypeConditional",
|
|
2038
|
+
checksType: assertRootResult(left),
|
|
2039
|
+
extendsType,
|
|
2040
|
+
trueType,
|
|
2041
|
+
falseType: parser.parseType(8 /* INFIX */)
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
});
|
|
2045
|
+
|
|
2046
|
+
// src/lexer/LexerRules.ts
|
|
2047
|
+
function makePunctuationRule(type) {
|
|
2048
|
+
return (text) => {
|
|
2049
|
+
if (text.startsWith(type)) {
|
|
2050
|
+
return { type, text: type };
|
|
2051
|
+
} else {
|
|
2052
|
+
return null;
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
function getQuoted(text) {
|
|
2057
|
+
let position = 0;
|
|
2058
|
+
let char = void 0;
|
|
2059
|
+
const mark = text[0];
|
|
2060
|
+
let escaped = false;
|
|
2061
|
+
if (mark !== "'" && mark !== '"') {
|
|
2062
|
+
return null;
|
|
2063
|
+
}
|
|
2064
|
+
while (position < text.length) {
|
|
2065
|
+
position++;
|
|
2066
|
+
char = text[position];
|
|
2067
|
+
if (!escaped && char === mark) {
|
|
2068
|
+
position++;
|
|
2069
|
+
break;
|
|
2070
|
+
}
|
|
2071
|
+
escaped = !escaped && char === "\\";
|
|
2072
|
+
}
|
|
2073
|
+
if (char !== mark) {
|
|
2074
|
+
throw new Error("Unterminated String");
|
|
2075
|
+
}
|
|
2076
|
+
return text.slice(0, position);
|
|
2077
|
+
}
|
|
2078
|
+
function getTemplateLiteral(text) {
|
|
2079
|
+
let position = 0;
|
|
2080
|
+
let char = void 0;
|
|
2081
|
+
const mark = text[0];
|
|
2082
|
+
let escaped = false;
|
|
2083
|
+
if (mark !== "`") {
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2086
|
+
while (position < text.length) {
|
|
2087
|
+
position++;
|
|
2088
|
+
char = text[position];
|
|
2089
|
+
if (!escaped && char === mark) {
|
|
2090
|
+
position++;
|
|
2091
|
+
break;
|
|
2092
|
+
}
|
|
2093
|
+
escaped = !escaped && char === "\\";
|
|
2094
|
+
}
|
|
2095
|
+
if (char !== mark) {
|
|
2096
|
+
throw new Error("Unterminated template literal");
|
|
2097
|
+
}
|
|
2098
|
+
return text.slice(0, position);
|
|
2099
|
+
}
|
|
2100
|
+
function getTemplateLiteralLiteral(text) {
|
|
2101
|
+
let position = 0;
|
|
2102
|
+
const start = text[0];
|
|
2103
|
+
let escaped = false;
|
|
2104
|
+
if (start === "`" || start === "$" && text[1] === "{") {
|
|
2105
|
+
return null;
|
|
2106
|
+
}
|
|
2107
|
+
while (position < text.length) {
|
|
2108
|
+
position++;
|
|
2109
|
+
const char = text[position];
|
|
2110
|
+
if (!escaped && (char === "`" || char === "$" && text[position + 1] === "{")) {
|
|
2111
|
+
break;
|
|
2112
|
+
}
|
|
2113
|
+
escaped = !escaped && char === "\\";
|
|
2114
|
+
}
|
|
2115
|
+
return text.slice(0, position);
|
|
2116
|
+
}
|
|
2117
|
+
var identifierStartRegex = /[$_\p{ID_Start}]|\\u\p{Hex_Digit}{4}|\\u\{0*(?:\p{Hex_Digit}{1,5}|10\p{Hex_Digit}{4})\}/v;
|
|
2118
|
+
var identifierContinueRegex = /[$\p{ID_Continue}\u200C\u200D]|\\u\p{Hex_Digit}{4}|\\u\{0*(?:\p{Hex_Digit}{1,5}|10\p{Hex_Digit}{4})\}/v;
|
|
2119
|
+
var identifierContinueRegexLoose = /[$\-\p{ID_Continue}\u200C\u200D]|\\u\p{Hex_Digit}{4}|\\u\{0*(?:\p{Hex_Digit}{1,5}|10\p{Hex_Digit}{4})\}/v;
|
|
2120
|
+
function makeGetIdentifier(identifierContinueRegex2) {
|
|
2121
|
+
return function(text) {
|
|
2122
|
+
let char = text[0];
|
|
2123
|
+
if (!identifierStartRegex.test(char)) {
|
|
2124
|
+
return null;
|
|
2125
|
+
}
|
|
2126
|
+
let position = 1;
|
|
2127
|
+
do {
|
|
2128
|
+
char = text[position];
|
|
2129
|
+
if (!identifierContinueRegex2.test(char)) {
|
|
2130
|
+
break;
|
|
2131
|
+
}
|
|
2132
|
+
position++;
|
|
2133
|
+
} while (position < text.length);
|
|
2134
|
+
return text.slice(0, position);
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
var numberRegex = /^(?:-?(?:(?:\d*\.\d+|\d+)(?:[Ee][+\-]?\d+)?))/v;
|
|
2138
|
+
var looseNumberRegex = /^(?:NaN|-?(?:(?:\d*\.\d+|\d+)(?:[Ee][+\-]?\d+)?|Infinity))/v;
|
|
2139
|
+
function getGetNumber(numberRegex2) {
|
|
2140
|
+
return function getNumber(text) {
|
|
2141
|
+
return numberRegex2.exec(text)?.[0] ?? null;
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2144
|
+
var looseIdentifierRule = (text) => {
|
|
2145
|
+
const value = makeGetIdentifier(identifierContinueRegexLoose)(text);
|
|
2146
|
+
if (value === null) {
|
|
2147
|
+
return null;
|
|
2148
|
+
}
|
|
2149
|
+
return {
|
|
2150
|
+
type: "Identifier",
|
|
2151
|
+
text: value
|
|
2152
|
+
};
|
|
2153
|
+
};
|
|
2154
|
+
var identifierRule = (text) => {
|
|
2155
|
+
const value = makeGetIdentifier(identifierContinueRegex)(text);
|
|
2156
|
+
if (value === null) {
|
|
2157
|
+
return null;
|
|
2158
|
+
}
|
|
2159
|
+
return {
|
|
2160
|
+
type: "Identifier",
|
|
2161
|
+
text: value
|
|
2162
|
+
};
|
|
2163
|
+
};
|
|
2164
|
+
function makeKeyWordRule(type) {
|
|
2165
|
+
return (text) => {
|
|
2166
|
+
if (!text.startsWith(type)) {
|
|
2167
|
+
return null;
|
|
2168
|
+
}
|
|
2169
|
+
const prepends = text[type.length];
|
|
2170
|
+
if (prepends !== void 0 && identifierContinueRegex.test(prepends)) {
|
|
2171
|
+
return null;
|
|
2172
|
+
}
|
|
2173
|
+
return {
|
|
2174
|
+
type,
|
|
2175
|
+
text: type
|
|
2176
|
+
};
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
var stringValueRule = (text) => {
|
|
2180
|
+
const value = getQuoted(text);
|
|
2181
|
+
if (value === null) {
|
|
2182
|
+
return null;
|
|
2183
|
+
}
|
|
2184
|
+
return {
|
|
2185
|
+
type: "StringValue",
|
|
2186
|
+
text: value
|
|
2187
|
+
};
|
|
2188
|
+
};
|
|
2189
|
+
var templateLiteralRule = (text) => {
|
|
2190
|
+
const value = getTemplateLiteral(text);
|
|
2191
|
+
if (value === null) {
|
|
2192
|
+
return null;
|
|
2193
|
+
}
|
|
2194
|
+
return {
|
|
2195
|
+
type: "TemplateLiteral",
|
|
2196
|
+
text: value
|
|
2197
|
+
};
|
|
2198
|
+
};
|
|
2199
|
+
var eofRule = (text) => {
|
|
2200
|
+
if (text.length > 0) {
|
|
2201
|
+
return null;
|
|
2202
|
+
}
|
|
2203
|
+
return {
|
|
2204
|
+
type: "EOF",
|
|
2205
|
+
text: ""
|
|
2206
|
+
};
|
|
2207
|
+
};
|
|
2208
|
+
var numberRule = (text) => {
|
|
2209
|
+
const value = getGetNumber(numberRegex)(text);
|
|
2210
|
+
if (value === null) {
|
|
2211
|
+
return null;
|
|
2212
|
+
}
|
|
2213
|
+
return {
|
|
2214
|
+
type: "Number",
|
|
2215
|
+
text: value
|
|
2216
|
+
};
|
|
2217
|
+
};
|
|
2218
|
+
var looseNumberRule = (text) => {
|
|
2219
|
+
const value = getGetNumber(looseNumberRegex)(text);
|
|
2220
|
+
if (value === null) {
|
|
2221
|
+
return null;
|
|
2222
|
+
}
|
|
2223
|
+
return {
|
|
2224
|
+
type: "Number",
|
|
2225
|
+
text: value
|
|
2226
|
+
};
|
|
2227
|
+
};
|
|
2228
|
+
var rules = [
|
|
2229
|
+
eofRule,
|
|
2230
|
+
makePunctuationRule("=>"),
|
|
2231
|
+
makePunctuationRule("("),
|
|
2232
|
+
makePunctuationRule(")"),
|
|
2233
|
+
makePunctuationRule("{"),
|
|
2234
|
+
makePunctuationRule("}"),
|
|
2235
|
+
makePunctuationRule("["),
|
|
2236
|
+
makePunctuationRule("]"),
|
|
2237
|
+
makePunctuationRule("|"),
|
|
2238
|
+
makePunctuationRule("&"),
|
|
2239
|
+
makePunctuationRule("<"),
|
|
2240
|
+
makePunctuationRule(">"),
|
|
2241
|
+
makePunctuationRule(","),
|
|
2242
|
+
makePunctuationRule(";"),
|
|
2243
|
+
makePunctuationRule("*"),
|
|
2244
|
+
makePunctuationRule("?"),
|
|
2245
|
+
makePunctuationRule("!"),
|
|
2246
|
+
makePunctuationRule("="),
|
|
2247
|
+
makePunctuationRule(":"),
|
|
2248
|
+
makePunctuationRule("..."),
|
|
2249
|
+
makePunctuationRule("."),
|
|
2250
|
+
makePunctuationRule("#"),
|
|
2251
|
+
makePunctuationRule("~"),
|
|
2252
|
+
makePunctuationRule("/"),
|
|
2253
|
+
makePunctuationRule("@"),
|
|
2254
|
+
makeKeyWordRule("undefined"),
|
|
2255
|
+
makeKeyWordRule("null"),
|
|
2256
|
+
makeKeyWordRule("function"),
|
|
2257
|
+
makeKeyWordRule("this"),
|
|
2258
|
+
makeKeyWordRule("new"),
|
|
2259
|
+
makeKeyWordRule("module"),
|
|
2260
|
+
makeKeyWordRule("event"),
|
|
2261
|
+
makeKeyWordRule("extends"),
|
|
2262
|
+
makeKeyWordRule("external"),
|
|
2263
|
+
makeKeyWordRule("infer"),
|
|
2264
|
+
makeKeyWordRule("typeof"),
|
|
2265
|
+
makeKeyWordRule("keyof"),
|
|
2266
|
+
makeKeyWordRule("readonly"),
|
|
2267
|
+
makeKeyWordRule("import"),
|
|
2268
|
+
makeKeyWordRule("is"),
|
|
2269
|
+
makeKeyWordRule("in"),
|
|
2270
|
+
makeKeyWordRule("asserts"),
|
|
2271
|
+
numberRule,
|
|
2272
|
+
identifierRule,
|
|
2273
|
+
stringValueRule,
|
|
2274
|
+
templateLiteralRule
|
|
2275
|
+
];
|
|
2276
|
+
var looseRules = rules.toSpliced(
|
|
2277
|
+
-4,
|
|
2278
|
+
2,
|
|
2279
|
+
looseNumberRule,
|
|
2280
|
+
looseIdentifierRule
|
|
2281
|
+
);
|
|
2282
|
+
|
|
2283
|
+
// src/parslets/TemplateLiteralParslet.ts
|
|
2284
|
+
var templateLiteralParslet = composeParslet({
|
|
2285
|
+
name: "templateLiteralParslet",
|
|
2286
|
+
accept: (type) => type === "TemplateLiteral",
|
|
2287
|
+
parsePrefix: (parser) => {
|
|
2288
|
+
const text = parser.lexer.current.text;
|
|
2289
|
+
parser.consume("TemplateLiteral");
|
|
2290
|
+
const literals = [];
|
|
2291
|
+
const interpolations = [];
|
|
2292
|
+
let currentText = text.slice(1, -1);
|
|
2293
|
+
const advanceLiteral = () => {
|
|
2294
|
+
const literal = getTemplateLiteralLiteral(currentText) ?? "";
|
|
2295
|
+
literals.push(literal.replace(/\\`/gv, "`"));
|
|
2296
|
+
currentText = currentText.slice(literal.length);
|
|
2297
|
+
};
|
|
2298
|
+
advanceLiteral();
|
|
2299
|
+
while (true) {
|
|
2300
|
+
if (currentText.startsWith("${")) {
|
|
2301
|
+
currentText = currentText.slice(2);
|
|
2302
|
+
let templateParser;
|
|
2303
|
+
let interpolationType;
|
|
2304
|
+
let snipped = currentText;
|
|
2305
|
+
let remnant = "";
|
|
2306
|
+
while (true) {
|
|
2307
|
+
try {
|
|
2308
|
+
templateParser = new Parser(
|
|
2309
|
+
parser.grammar,
|
|
2310
|
+
Lexer.create(parser.lexer.lexerRules, snipped)
|
|
2311
|
+
);
|
|
2312
|
+
interpolationType = templateParser.parseType(0 /* ALL */);
|
|
2313
|
+
break;
|
|
2314
|
+
} catch (err) {
|
|
2315
|
+
remnant = snipped.slice(-1) + remnant;
|
|
2316
|
+
snipped = snipped.slice(0, -1);
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
interpolations.push(interpolationType);
|
|
2320
|
+
if (templateParser.lexer.current.text !== "}") {
|
|
2321
|
+
throw new Error("unterminated interpolation");
|
|
2322
|
+
}
|
|
2323
|
+
currentText = templateParser.lexer.remaining() + remnant;
|
|
2324
|
+
} else {
|
|
2325
|
+
break;
|
|
2326
|
+
}
|
|
2327
|
+
advanceLiteral();
|
|
2328
|
+
}
|
|
2329
|
+
return {
|
|
2330
|
+
type: "JsdocTypeTemplateLiteral",
|
|
2331
|
+
literals,
|
|
2332
|
+
interpolations
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2336
|
+
|
|
2337
|
+
// src/grammars/typescriptGrammar.ts
|
|
2338
|
+
var objectFieldGrammar2 = [
|
|
2339
|
+
functionPropertyParslet,
|
|
2340
|
+
readonlyPropertyParslet,
|
|
2341
|
+
createNameParslet({
|
|
2342
|
+
allowedAdditionalTokens: baseNameTokens
|
|
2343
|
+
}),
|
|
2344
|
+
nullableParslet,
|
|
2345
|
+
optionalParslet,
|
|
2346
|
+
stringValueParslet,
|
|
2347
|
+
numberParslet,
|
|
2348
|
+
createObjectFieldParslet({
|
|
2349
|
+
allowSquaredProperties: true,
|
|
2350
|
+
allowKeyTypes: false,
|
|
2351
|
+
allowOptional: true,
|
|
2352
|
+
allowReadonly: true
|
|
2353
|
+
}),
|
|
2354
|
+
objectSquaredPropertyParslet
|
|
2355
|
+
];
|
|
2356
|
+
var typescriptGrammar = [
|
|
2357
|
+
...baseGrammar,
|
|
2358
|
+
createObjectParslet({
|
|
2359
|
+
allowKeyTypes: false,
|
|
2360
|
+
objectFieldGrammar: objectFieldGrammar2,
|
|
2361
|
+
signatureGrammar: [
|
|
2362
|
+
createKeyValueParslet({
|
|
2363
|
+
allowVariadic: true,
|
|
2364
|
+
allowOptional: true,
|
|
2365
|
+
acceptParameterList: true
|
|
2366
|
+
})
|
|
2367
|
+
]
|
|
2368
|
+
}),
|
|
2369
|
+
readonlyArrayParslet,
|
|
2370
|
+
typeOfParslet,
|
|
2371
|
+
keyOfParslet,
|
|
2372
|
+
importParslet,
|
|
2373
|
+
stringValueParslet,
|
|
2374
|
+
createFunctionParslet({
|
|
2375
|
+
allowWithoutParenthesis: true,
|
|
2376
|
+
allowNoReturnType: true,
|
|
2377
|
+
allowNamedParameters: ["this", "new", "args"],
|
|
2378
|
+
allowNewAsFunctionKeyword: true
|
|
2379
|
+
}),
|
|
2380
|
+
createTupleParslet({
|
|
2381
|
+
allowQuestionMark: false
|
|
2382
|
+
}),
|
|
2383
|
+
createVariadicParslet({
|
|
2384
|
+
allowEnclosingBrackets: false,
|
|
2385
|
+
allowPostfix: false
|
|
2386
|
+
}),
|
|
2387
|
+
assertsParslet,
|
|
2388
|
+
conditionalParslet,
|
|
2389
|
+
createNameParslet({
|
|
2390
|
+
allowedAdditionalTokens: ["event", "external", "in"]
|
|
2391
|
+
}),
|
|
2392
|
+
createSpecialNamePathParslet({
|
|
2393
|
+
allowedTypes: ["module"],
|
|
2394
|
+
pathGrammar
|
|
2395
|
+
}),
|
|
2396
|
+
arrayBracketsParslet,
|
|
2397
|
+
arrowFunctionParslet,
|
|
2398
|
+
genericArrowFunctionParslet,
|
|
2399
|
+
createNamePathParslet({
|
|
2400
|
+
allowSquareBracketsOnAnyType: true,
|
|
2401
|
+
allowJsdocNamePaths: false,
|
|
2402
|
+
pathGrammar
|
|
2403
|
+
}),
|
|
2404
|
+
intersectionParslet,
|
|
2405
|
+
predicateParslet,
|
|
2406
|
+
templateLiteralParslet,
|
|
2407
|
+
createKeyValueParslet({
|
|
2408
|
+
allowVariadic: true,
|
|
2409
|
+
allowOptional: true
|
|
2410
|
+
})
|
|
2411
|
+
];
|
|
2412
|
+
var typescriptNameGrammar = [
|
|
2413
|
+
genericParslet,
|
|
2414
|
+
arrayBracketsParslet,
|
|
2415
|
+
createNameParslet({
|
|
2416
|
+
allowedAdditionalTokens: baseNameTokens
|
|
2417
|
+
})
|
|
2418
|
+
];
|
|
2419
|
+
var typescriptNamePathGrammar = [
|
|
2420
|
+
genericParslet,
|
|
2421
|
+
arrayBracketsParslet,
|
|
2422
|
+
createNameParslet({
|
|
2423
|
+
allowedAdditionalTokens: baseNameTokens
|
|
2424
|
+
}),
|
|
2425
|
+
createNamePathParslet({
|
|
2426
|
+
allowSquareBracketsOnAnyType: true,
|
|
2427
|
+
// Here we actually want JSDoc name paths (even though TS
|
|
2428
|
+
// in JSDoc namepath positions interpret them differently
|
|
2429
|
+
// than JSDoc)
|
|
2430
|
+
allowJsdocNamePaths: true,
|
|
2431
|
+
pathGrammar
|
|
2432
|
+
})
|
|
2433
|
+
];
|
|
2434
|
+
var typescriptNamePathSpecialGrammar = [
|
|
2435
|
+
createSpecialNamePathParslet({
|
|
2436
|
+
allowedTypes: ["module"],
|
|
2437
|
+
pathGrammar
|
|
2438
|
+
}),
|
|
2439
|
+
...typescriptNamePathGrammar
|
|
2440
|
+
];
|
|
2441
|
+
|
|
2442
|
+
// src/parse.ts
|
|
2443
|
+
function parse$1(expression, mode, {
|
|
2444
|
+
range = false,
|
|
2445
|
+
rangeStart,
|
|
2446
|
+
loc = false,
|
|
2447
|
+
locStart = {
|
|
2448
|
+
column: 0,
|
|
2449
|
+
line: 1
|
|
2450
|
+
},
|
|
2451
|
+
module = true,
|
|
2452
|
+
strictMode = true,
|
|
2453
|
+
asyncFunctionBody = true,
|
|
2454
|
+
classContext = false,
|
|
2455
|
+
computedPropertyParser
|
|
2456
|
+
} = {}) {
|
|
2457
|
+
let parser;
|
|
2458
|
+
switch (mode) {
|
|
2459
|
+
case "closure":
|
|
2460
|
+
parser = new Parser(closureGrammar, Lexer.create(looseRules, expression), void 0, {
|
|
2461
|
+
module,
|
|
2462
|
+
strictMode,
|
|
2463
|
+
asyncFunctionBody,
|
|
2464
|
+
classContext,
|
|
2465
|
+
range,
|
|
2466
|
+
rangeStart,
|
|
2467
|
+
loc,
|
|
2468
|
+
locStart
|
|
2469
|
+
});
|
|
2470
|
+
break;
|
|
2471
|
+
case "jsdoc":
|
|
2472
|
+
parser = new Parser(jsdocGrammar, Lexer.create(looseRules, expression), void 0, {
|
|
2473
|
+
module,
|
|
2474
|
+
strictMode,
|
|
2475
|
+
asyncFunctionBody,
|
|
2476
|
+
classContext,
|
|
2477
|
+
range,
|
|
2478
|
+
rangeStart,
|
|
2479
|
+
loc,
|
|
2480
|
+
locStart
|
|
2481
|
+
});
|
|
2482
|
+
break;
|
|
2483
|
+
case "typescript":
|
|
2484
|
+
parser = new Parser(
|
|
2485
|
+
typescriptGrammar,
|
|
2486
|
+
Lexer.create(rules, expression),
|
|
2487
|
+
void 0,
|
|
2488
|
+
{
|
|
2489
|
+
module,
|
|
2490
|
+
strictMode,
|
|
2491
|
+
asyncFunctionBody,
|
|
2492
|
+
classContext,
|
|
2493
|
+
range,
|
|
2494
|
+
rangeStart,
|
|
2495
|
+
loc,
|
|
2496
|
+
locStart,
|
|
2497
|
+
externalParsers: {
|
|
2498
|
+
computedPropertyParser
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
);
|
|
2502
|
+
break;
|
|
2503
|
+
}
|
|
2504
|
+
const result = parser.parse();
|
|
2505
|
+
return assertResultIsNotReservedWord(parser, result);
|
|
2506
|
+
}
|
|
2507
|
+
function tryParse(expression, modes = ["typescript", "closure", "jsdoc"], {
|
|
2508
|
+
module = true,
|
|
2509
|
+
strictMode = true,
|
|
2510
|
+
asyncFunctionBody = true,
|
|
2511
|
+
classContext = false,
|
|
2512
|
+
range,
|
|
2513
|
+
rangeStart,
|
|
2514
|
+
loc = false,
|
|
2515
|
+
locStart = {
|
|
2516
|
+
column: 0,
|
|
2517
|
+
line: 1
|
|
2518
|
+
}
|
|
2519
|
+
} = {}) {
|
|
2520
|
+
let error;
|
|
2521
|
+
for (const mode of modes) {
|
|
2522
|
+
try {
|
|
2523
|
+
return parse$1(expression, mode, {
|
|
2524
|
+
module,
|
|
2525
|
+
strictMode,
|
|
2526
|
+
asyncFunctionBody,
|
|
2527
|
+
classContext,
|
|
2528
|
+
range,
|
|
2529
|
+
rangeStart,
|
|
2530
|
+
loc,
|
|
2531
|
+
locStart
|
|
2532
|
+
});
|
|
2533
|
+
} catch (e) {
|
|
2534
|
+
error = e;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
throw error;
|
|
2538
|
+
}
|
|
2539
|
+
function parseNamePath(expression, mode, {
|
|
2540
|
+
includeSpecial = false
|
|
2541
|
+
} = {}) {
|
|
2542
|
+
switch (mode) {
|
|
2543
|
+
case "closure":
|
|
2544
|
+
return new Parser(
|
|
2545
|
+
includeSpecial ? closureNamePathSpecialGrammar : closureNamePathGrammar,
|
|
2546
|
+
Lexer.create(looseRules, expression)
|
|
2547
|
+
).parse();
|
|
2548
|
+
case "jsdoc":
|
|
2549
|
+
return new Parser(
|
|
2550
|
+
includeSpecial ? jsdocNamePathSpecialGrammar : jsdocNamePathGrammar,
|
|
2551
|
+
Lexer.create(looseRules, expression)
|
|
2552
|
+
).parse();
|
|
2553
|
+
case "typescript": {
|
|
2554
|
+
return new Parser(
|
|
2555
|
+
includeSpecial ? typescriptNamePathSpecialGrammar : typescriptNamePathGrammar,
|
|
2556
|
+
Lexer.create(rules, expression)
|
|
2557
|
+
).parse();
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
function parseName(expression, mode) {
|
|
2562
|
+
switch (mode) {
|
|
2563
|
+
case "closure":
|
|
2564
|
+
return new Parser(closureNameGrammar, Lexer.create(looseRules, expression)).parse();
|
|
2565
|
+
case "jsdoc":
|
|
2566
|
+
return new Parser(jsdocNameGrammar, Lexer.create(looseRules, expression)).parse();
|
|
2567
|
+
case "typescript":
|
|
2568
|
+
return new Parser(
|
|
2569
|
+
typescriptNameGrammar,
|
|
2570
|
+
Lexer.create(rules, expression)
|
|
2571
|
+
).parse();
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
// src/transforms/transform.ts
|
|
2576
|
+
function transform(rules2, parseResult) {
|
|
2577
|
+
const rule = rules2[parseResult.type];
|
|
2578
|
+
if (rule === void 0) {
|
|
2579
|
+
throw new Error(`In this set of transform rules exists no rule for type ${parseResult.type}.`);
|
|
2580
|
+
}
|
|
2581
|
+
return rule(parseResult, (aParseResult) => transform(rules2, aParseResult));
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
// src/transforms/stringify.ts
|
|
2585
|
+
function applyPosition(position, target, value) {
|
|
2586
|
+
return position === "prefix" ? value + target : target + value;
|
|
2587
|
+
}
|
|
2588
|
+
function quote(value, quote2) {
|
|
2589
|
+
switch (quote2) {
|
|
2590
|
+
case "double":
|
|
2591
|
+
return `"${value}"`;
|
|
2592
|
+
case "single":
|
|
2593
|
+
return `'${value}'`;
|
|
2594
|
+
case void 0:
|
|
2595
|
+
return value;
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
function stringifyRules({
|
|
2599
|
+
computedPropertyStringifier
|
|
2600
|
+
} = {}) {
|
|
2601
|
+
return {
|
|
2602
|
+
JsdocTypeParenthesis: (result, transform2) => `(${result.element !== void 0 ? transform2(result.element) : ""})`,
|
|
2603
|
+
JsdocTypeKeyof: (result, transform2) => `keyof ${transform2(result.element)}`,
|
|
2604
|
+
JsdocTypeFunction: (result, transform2) => {
|
|
2605
|
+
if (!result.arrow) {
|
|
2606
|
+
let stringified = result.constructor ? "new" : "function";
|
|
2607
|
+
if (!result.parenthesis) {
|
|
2608
|
+
return stringified;
|
|
2609
|
+
}
|
|
2610
|
+
stringified += `(${result.parameters.map(transform2).join(`,${result.meta?.parameterSpacing ?? " "}`)})`;
|
|
2611
|
+
if (result.returnType !== void 0) {
|
|
2612
|
+
stringified += `${result.meta?.preReturnMarkerSpacing ?? ""}:${result.meta?.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`;
|
|
2613
|
+
}
|
|
2614
|
+
return stringified;
|
|
2615
|
+
} else {
|
|
2616
|
+
if (result.returnType === void 0) {
|
|
2617
|
+
throw new Error("Arrow function needs a return type.");
|
|
2618
|
+
}
|
|
2619
|
+
let stringified = `${result.typeParameters !== void 0 ? `<${result.typeParameters.map(transform2).join(`,${result.meta?.typeParameterSpacing ?? " "}`)}>${result.meta?.postGenericSpacing ?? ""}` : ""}(${result.parameters.map(transform2).join(`,${result.meta?.parameterSpacing ?? " "}`)})${result.meta?.preReturnMarkerSpacing ?? " "}=>${result.meta?.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`;
|
|
2620
|
+
if (result.constructor) {
|
|
2621
|
+
stringified = `new ${stringified}`;
|
|
2622
|
+
}
|
|
2623
|
+
return stringified;
|
|
2624
|
+
}
|
|
2625
|
+
},
|
|
2626
|
+
JsdocTypeName: (result) => result.value,
|
|
2627
|
+
JsdocTypeInfer: (result, transform2) => `infer ${transform2(result.element)}`,
|
|
2628
|
+
JsdocTypeTuple: (result, transform2) => `[${result.elements.map(transform2).join(`,${result.meta?.elementSpacing ?? " "}`)}]`,
|
|
2629
|
+
JsdocTypeVariadic: (result, transform2) => result.meta.position === void 0 ? "..." : applyPosition(result.meta.position, transform2(result.element), "..."),
|
|
2630
|
+
JsdocTypeNamePath: (result, transform2) => {
|
|
2631
|
+
const left = transform2(result.left);
|
|
2632
|
+
const right = transform2(result.right);
|
|
2633
|
+
switch (result.pathType) {
|
|
2634
|
+
case "inner":
|
|
2635
|
+
return `${left}~${right}`;
|
|
2636
|
+
case "instance":
|
|
2637
|
+
return `${left}#${right}`;
|
|
2638
|
+
case "property":
|
|
2639
|
+
return `${left}.${right}`;
|
|
2640
|
+
case "property-brackets":
|
|
2641
|
+
return `${left}[${right}]`;
|
|
2642
|
+
}
|
|
2643
|
+
},
|
|
2644
|
+
JsdocTypeStringValue: (result) => quote(result.value, result.meta.quote),
|
|
2645
|
+
JsdocTypeAny: () => "*",
|
|
2646
|
+
JsdocTypeGeneric: (result, transform2) => {
|
|
2647
|
+
if (result.meta.brackets === "square") {
|
|
2648
|
+
const element = result.elements[0];
|
|
2649
|
+
const transformed = transform2(element);
|
|
2650
|
+
if (element.type === "JsdocTypeUnion" || element.type === "JsdocTypeIntersection") {
|
|
2651
|
+
return `(${transformed})[]`;
|
|
2652
|
+
} else {
|
|
2653
|
+
return `${transformed}[]`;
|
|
2654
|
+
}
|
|
2655
|
+
} else {
|
|
2656
|
+
return `${transform2(result.left)}${result.meta.dot ? "." : ""}<${result.elements.map(transform2).join(`,${result.meta.elementSpacing ?? " "}`)}>`;
|
|
2657
|
+
}
|
|
2658
|
+
},
|
|
2659
|
+
JsdocTypeImport: (result, transform2) => `import(${transform2(result.element)})`,
|
|
2660
|
+
JsdocTypeObjectField: (result, transform2) => {
|
|
2661
|
+
let text = "";
|
|
2662
|
+
if (result.readonly) {
|
|
2663
|
+
text += "readonly ";
|
|
2664
|
+
}
|
|
2665
|
+
let optionalBeforeParentheses = false;
|
|
2666
|
+
if (typeof result.key === "string") {
|
|
2667
|
+
text += quote(result.key, result.meta.quote);
|
|
2668
|
+
} else {
|
|
2669
|
+
if (result.key.type === "JsdocTypeComputedMethod") {
|
|
2670
|
+
optionalBeforeParentheses = true;
|
|
2671
|
+
}
|
|
2672
|
+
text += transform2(result.key);
|
|
2673
|
+
}
|
|
2674
|
+
text += result.meta.postKeySpacing ?? "";
|
|
2675
|
+
if (!optionalBeforeParentheses && result.optional) {
|
|
2676
|
+
text += "?";
|
|
2677
|
+
text += result.meta.postOptionalSpacing ?? "";
|
|
2678
|
+
}
|
|
2679
|
+
if (result.right === void 0) {
|
|
2680
|
+
return text;
|
|
2681
|
+
} else {
|
|
2682
|
+
return `${text}:${result.meta.postColonSpacing ?? " "}${transform2(result.right)}`;
|
|
2683
|
+
}
|
|
2684
|
+
},
|
|
2685
|
+
JsdocTypeJsdocObjectField: (result, transform2) => `${transform2(result.left)}: ${transform2(result.right)}`,
|
|
2686
|
+
JsdocTypeKeyValue: (result, transform2) => {
|
|
2687
|
+
let text = result.key;
|
|
2688
|
+
if (result.optional) {
|
|
2689
|
+
text += `${result.meta?.postKeySpacing ?? ""}?${result.meta?.postOptionalSpacing ?? ""}`;
|
|
2690
|
+
} else if (result.variadic) {
|
|
2691
|
+
text = `...${result.meta?.postVariadicSpacing ?? ""}${text}`;
|
|
2692
|
+
} else if (result.right !== void 0) {
|
|
2693
|
+
text += result.meta?.postKeySpacing ?? "";
|
|
2694
|
+
}
|
|
2695
|
+
if (result.right === void 0) {
|
|
2696
|
+
return text;
|
|
2697
|
+
} else {
|
|
2698
|
+
return `${text}:${result.meta?.postColonSpacing ?? " "}${transform2(result.right)}`;
|
|
2699
|
+
}
|
|
2700
|
+
},
|
|
2701
|
+
JsdocTypeSpecialNamePath: (result) => `${result.specialType}:${quote(result.value, result.meta.quote)}`,
|
|
2702
|
+
JsdocTypeNotNullable: (result, transform2) => applyPosition(result.meta.position, transform2(result.element), "!"),
|
|
2703
|
+
JsdocTypeNull: () => "null",
|
|
2704
|
+
JsdocTypeNullable: (result, transform2) => applyPosition(result.meta.position, transform2(result.element), "?"),
|
|
2705
|
+
JsdocTypeNumber: (result) => result.value.toString(),
|
|
2706
|
+
JsdocTypeObject: (result, transform2) => {
|
|
2707
|
+
const lbType = (result.meta.separator ?? "").endsWith("linebreak");
|
|
2708
|
+
const lbEnding = result.meta.separator === "comma-and-linebreak" ? ",\n" : result.meta.separator === "semicolon-and-linebreak" ? ";\n" : result.meta.separator === "linebreak" ? "\n" : "";
|
|
2709
|
+
const separatorForSingleObjectField = result.meta.separatorForSingleObjectField ?? false;
|
|
2710
|
+
const trailingPunctuation = result.meta.trailingPunctuation ?? false;
|
|
2711
|
+
const bracketSpacing = result.meta.bracketSpacing ?? "";
|
|
2712
|
+
return `{${/* c8 ignore next -- Guard */
|
|
2713
|
+
(lbType && (separatorForSingleObjectField || result.elements.length > 1) ? `
|
|
2714
|
+
${result.meta.propertyIndent ?? ""}` : bracketSpacing) + result.elements.map(transform2).join(
|
|
2715
|
+
result.meta.separator === "comma" ? ", " : lbType ? lbEnding + /* c8 ignore next -- Guard */
|
|
2716
|
+
(result.meta.propertyIndent ?? "") : "; "
|
|
2717
|
+
) + (separatorForSingleObjectField && result.elements.length === 1 ? result.meta.separator === "comma" ? "," : lbType ? lbEnding : ";" : trailingPunctuation && result.meta.separator !== void 0 ? result.meta.separator.startsWith("comma") ? "," : result.meta.separator.startsWith("semicolon") ? ";" : "" : "") + (lbType && result.elements.length > 1 ? "\n" : bracketSpacing)}}`;
|
|
2718
|
+
},
|
|
2719
|
+
JsdocTypeOptional: (result, transform2) => applyPosition(result.meta.position, transform2(result.element), "="),
|
|
2720
|
+
JsdocTypeSymbol: (result, transform2) => `${result.value}(${result.element !== void 0 ? transform2(result.element) : ""})`,
|
|
2721
|
+
JsdocTypeTypeof: (result, transform2) => `typeof ${transform2(result.element)}`,
|
|
2722
|
+
JsdocTypeUndefined: () => "undefined",
|
|
2723
|
+
JsdocTypeUnion: (result, transform2) => result.elements.map(transform2).join(
|
|
2724
|
+
result.meta?.spacing === void 0 ? " | " : `${result.meta.spacing}|${result.meta.spacing}`
|
|
2725
|
+
),
|
|
2726
|
+
JsdocTypeUnknown: () => "?",
|
|
2727
|
+
JsdocTypeIntersection: (result, transform2) => result.elements.map(transform2).join(" & "),
|
|
2728
|
+
JsdocTypeProperty: (result) => quote(result.value, result.meta.quote),
|
|
2729
|
+
JsdocTypePredicate: (result, transform2) => `${transform2(result.left)} is ${transform2(result.right)}`,
|
|
2730
|
+
JsdocTypeIndexSignature: (result, transform2) => `[${result.key}: ${transform2(result.right)}]`,
|
|
2731
|
+
JsdocTypeMappedType: (result, transform2) => `[${result.key} in ${transform2(result.right)}]`,
|
|
2732
|
+
JsdocTypeAsserts: (result, transform2) => `asserts ${transform2(result.left)} is ${transform2(result.right)}`,
|
|
2733
|
+
JsdocTypeReadonlyArray: (result, transform2) => `readonly ${transform2(result.element)}`,
|
|
2734
|
+
JsdocTypeAssertsPlain: (result, transform2) => `asserts ${transform2(result.element)}`,
|
|
2735
|
+
JsdocTypeConditional: (result, transform2) => `${transform2(result.checksType)} extends ${transform2(result.extendsType)} ? ${transform2(result.trueType)} : ${transform2(result.falseType)}`,
|
|
2736
|
+
JsdocTypeTypeParameter: (result, transform2) => `${transform2(result.name)}${result.constraint !== void 0 ? ` extends ${transform2(result.constraint)}` : ""}${result.defaultValue !== void 0 ? `${result.meta?.defaultValueSpacing ?? " "}=${result.meta?.defaultValueSpacing ?? " "}${transform2(result.defaultValue)}` : ""}`,
|
|
2737
|
+
JsdocTypeCallSignature: (result, transform2) => `${result.typeParameters !== void 0 ? `<${result.typeParameters.map(transform2).join(`,${result.meta?.typeParameterSpacing ?? " "}`)}>${result.meta?.postGenericSpacing ?? ""}` : ""}(${result.parameters.map(transform2).join(`,${result.meta?.parameterSpacing ?? " "}`)})${result.meta?.preReturnMarkerSpacing ?? ""}:${result.meta?.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`,
|
|
2738
|
+
JsdocTypeConstructorSignature: (result, transform2) => `new${result.meta?.postNewSpacing ?? " "}${result.typeParameters !== void 0 ? `<${result.typeParameters.map(transform2).join(`,${result.meta?.typeParameterSpacing ?? " "}`)}>${result.meta?.postGenericSpacing ?? ""}` : ""}(${result.parameters.map(transform2).join(`,${result.meta?.parameterSpacing ?? " "}`)})${result.meta?.preReturnMarkerSpacing ?? ""}:${result.meta?.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`,
|
|
2739
|
+
JsdocTypeMethodSignature: (result, transform2) => {
|
|
2740
|
+
const quote2 = result.meta.quote === "double" ? '"' : result.meta.quote === "single" ? "'" : "";
|
|
2741
|
+
return `${quote2}${result.name}${quote2}${result.meta.postMethodNameSpacing ?? ""}${result.typeParameters !== void 0 ? `<${result.typeParameters.map(transform2).join(`,${result.meta.typeParameterSpacing ?? " "}`)}>${result.meta.postGenericSpacing ?? ""}` : ""}(${result.parameters.map(transform2).join(`,${result.meta.parameterSpacing ?? " "}`)})${result.meta.preReturnMarkerSpacing ?? ""}:${result.meta.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`;
|
|
2742
|
+
},
|
|
2743
|
+
JsdocTypeIndexedAccessIndex: (result, transform2) => transform2(result.right),
|
|
2744
|
+
JsdocTypeTemplateLiteral: (result, transform2) => `\`${// starts with a literal (even empty string) then alternating
|
|
2745
|
+
// interpolations and literals and also ending in literal
|
|
2746
|
+
// (even empty string)
|
|
2747
|
+
result.literals.slice(0, -1).map(
|
|
2748
|
+
(literal, idx) => `${literal.replace(/`/gv, "\\`")}\${${transform2(result.interpolations[idx])}}`
|
|
2749
|
+
).join("") + result.literals.slice(-1)[0].replace(/`/gv, "\\`")}\``,
|
|
2750
|
+
JsdocTypeComputedProperty: (result, transform2) => {
|
|
2751
|
+
if (result.value.type.startsWith("JsdocType")) {
|
|
2752
|
+
return `[${transform2(result.value)}]`;
|
|
2753
|
+
} else {
|
|
2754
|
+
if (computedPropertyStringifier === void 0) {
|
|
2755
|
+
throw new Error("Must have a computed property stringifier");
|
|
2756
|
+
}
|
|
2757
|
+
return `[${computedPropertyStringifier(result.value).replace(/;$/v, "")}]`;
|
|
2758
|
+
}
|
|
2759
|
+
},
|
|
2760
|
+
JsdocTypeComputedMethod: (result, transform2) => {
|
|
2761
|
+
if (result.value.type.startsWith("JsdocType")) {
|
|
2762
|
+
return `[${transform2(result.value)}]${result.optional ? "?" : ""}${result.typeParameters !== void 0 ? `<${result.typeParameters.map(transform2).join(`,${result.meta?.typeParameterSpacing ?? " "}`)}>${result.meta?.postGenericSpacing ?? ""}` : ""}(${result.parameters.map(transform2).join(`,${result.meta?.parameterSpacing ?? " "}`)})${result.meta?.preReturnMarkerSpacing ?? ""}:${result.meta?.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`;
|
|
2763
|
+
} else {
|
|
2764
|
+
if (computedPropertyStringifier === void 0) {
|
|
2765
|
+
throw new Error("Must have a computed property stringifier");
|
|
2766
|
+
}
|
|
2767
|
+
return `[${computedPropertyStringifier(result.value).replace(/;$/v, "")}](${result.parameters.map(transform2).join(`,${result.meta?.parameterSpacing ?? " "}`)})${result.meta?.preReturnMarkerSpacing ?? ""}:${result.meta?.postReturnMarkerSpacing ?? " "}${transform2(result.returnType)}`;
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
var storedStringifyRules = stringifyRules();
|
|
2773
|
+
function stringify$1(result, stringificationRules = storedStringifyRules) {
|
|
2774
|
+
if (typeof stringificationRules === "function") {
|
|
2775
|
+
stringificationRules = stringifyRules({
|
|
2776
|
+
computedPropertyStringifier: stringificationRules
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
return transform(stringificationRules, result);
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
// src/visitorKeys.ts
|
|
2783
|
+
var visitorKeys = {
|
|
2784
|
+
JsdocTypeAny: [],
|
|
2785
|
+
JsdocTypeFunction: ["typeParameters", "parameters", "returnType"],
|
|
2786
|
+
JsdocTypeGeneric: ["left", "elements"],
|
|
2787
|
+
JsdocTypeImport: ["element"],
|
|
2788
|
+
JsdocTypeIndexSignature: ["right"],
|
|
2789
|
+
JsdocTypeIntersection: ["elements"],
|
|
2790
|
+
JsdocTypeKeyof: ["element"],
|
|
2791
|
+
JsdocTypeKeyValue: ["right"],
|
|
2792
|
+
JsdocTypeMappedType: ["right"],
|
|
2793
|
+
JsdocTypeName: [],
|
|
2794
|
+
JsdocTypeInfer: ["element"],
|
|
2795
|
+
JsdocTypeNamePath: ["left", "right"],
|
|
2796
|
+
JsdocTypeNotNullable: ["element"],
|
|
2797
|
+
JsdocTypeNull: [],
|
|
2798
|
+
JsdocTypeNullable: ["element"],
|
|
2799
|
+
JsdocTypeNumber: [],
|
|
2800
|
+
JsdocTypeObject: ["elements"],
|
|
2801
|
+
JsdocTypeObjectField: ["key", "right"],
|
|
2802
|
+
JsdocTypeJsdocObjectField: ["left", "right"],
|
|
2803
|
+
JsdocTypeOptional: ["element"],
|
|
2804
|
+
JsdocTypeParenthesis: ["element"],
|
|
2805
|
+
JsdocTypeSpecialNamePath: [],
|
|
2806
|
+
JsdocTypeStringValue: [],
|
|
2807
|
+
JsdocTypeSymbol: ["element"],
|
|
2808
|
+
JsdocTypeTuple: ["elements"],
|
|
2809
|
+
JsdocTypeTypeof: ["element"],
|
|
2810
|
+
JsdocTypeUndefined: [],
|
|
2811
|
+
JsdocTypeUnion: ["elements"],
|
|
2812
|
+
JsdocTypeUnknown: [],
|
|
2813
|
+
JsdocTypeVariadic: ["element"],
|
|
2814
|
+
JsdocTypeProperty: [],
|
|
2815
|
+
JsdocTypePredicate: ["left", "right"],
|
|
2816
|
+
JsdocTypeAsserts: ["left", "right"],
|
|
2817
|
+
JsdocTypeReadonlyArray: ["element"],
|
|
2818
|
+
JsdocTypeAssertsPlain: ["element"],
|
|
2819
|
+
JsdocTypeConditional: ["checksType", "extendsType", "trueType", "falseType"],
|
|
2820
|
+
JsdocTypeTypeParameter: ["name", "constraint", "defaultValue"],
|
|
2821
|
+
JsdocTypeCallSignature: ["typeParameters", "parameters", "returnType"],
|
|
2822
|
+
JsdocTypeConstructorSignature: ["typeParameters", "parameters", "returnType"],
|
|
2823
|
+
JsdocTypeMethodSignature: ["typeParameters", "parameters", "returnType"],
|
|
2824
|
+
JsdocTypeIndexedAccessIndex: ["right"],
|
|
2825
|
+
JsdocTypeTemplateLiteral: ["interpolations"],
|
|
2826
|
+
JsdocTypeComputedProperty: ["value"],
|
|
2827
|
+
JsdocTypeComputedMethod: ["value", "typeParameters", "parameters", "returnType"]
|
|
2828
|
+
};
|
|
2829
|
+
|
|
2830
|
+
// src/traverse.ts
|
|
2831
|
+
function _traverse(node, parentNode, property, index, onEnter, onLeave) {
|
|
2832
|
+
onEnter?.(node, parentNode, property, index);
|
|
2833
|
+
const keysToVisit = visitorKeys[node.type];
|
|
2834
|
+
for (const key of keysToVisit) {
|
|
2835
|
+
const value = node[key];
|
|
2836
|
+
if (value !== void 0) {
|
|
2837
|
+
if (Array.isArray(value)) {
|
|
2838
|
+
for (const [index2, element] of value.entries()) {
|
|
2839
|
+
_traverse(element, node, key, index2, onEnter);
|
|
2840
|
+
}
|
|
2841
|
+
} else if (value !== null && typeof value === "object" && "type" in value) {
|
|
2842
|
+
_traverse(value, node, key, void 0, onEnter);
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
function traverse(node, onEnter, onLeave) {
|
|
2848
|
+
_traverse(node, void 0, void 0, void 0, onEnter);
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
/** @deprecated */
|
|
2852
|
+
var Markers;
|
|
2853
|
+
(function (Markers) {
|
|
2854
|
+
Markers["start"] = "/**";
|
|
2855
|
+
Markers["nostart"] = "/***";
|
|
2856
|
+
Markers["delim"] = "*";
|
|
2857
|
+
Markers["end"] = "*/";
|
|
2858
|
+
})(Markers || (Markers = {}));
|
|
2859
|
+
|
|
2860
|
+
function isSpace(source) {
|
|
2861
|
+
return /^\s+$/.test(source);
|
|
2862
|
+
}
|
|
2863
|
+
function splitCR(source) {
|
|
2864
|
+
const matches = source.match(/\r+$/);
|
|
2865
|
+
return matches == null
|
|
2866
|
+
? ['', source]
|
|
2867
|
+
: [source.slice(-matches[0].length), source.slice(0, -matches[0].length)];
|
|
2868
|
+
}
|
|
2869
|
+
function splitSpace(source) {
|
|
2870
|
+
const matches = source.match(/^\s+/);
|
|
2871
|
+
return matches == null
|
|
2872
|
+
? ['', source]
|
|
2873
|
+
: [source.slice(0, matches[0].length), source.slice(matches[0].length)];
|
|
2874
|
+
}
|
|
2875
|
+
function splitLines(source) {
|
|
2876
|
+
return source.split(/\n/);
|
|
2877
|
+
}
|
|
2878
|
+
function seedSpec(spec = {}) {
|
|
2879
|
+
return Object.assign({ tag: '', name: '', type: '', optional: false, description: '', problems: [], source: [] }, spec);
|
|
2880
|
+
}
|
|
2881
|
+
function seedTokens(tokens = {}) {
|
|
2882
|
+
return Object.assign({ start: '', delimiter: '', postDelimiter: '', tag: '', postTag: '', name: '', postName: '', type: '', postType: '', description: '', end: '', lineEnd: '' }, tokens);
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Assures Block.tags[].source contains references to the Block.source items,
|
|
2886
|
+
* using Block.source as a source of truth. This is a counterpart of rewireSpecs
|
|
2887
|
+
* @param block parsed coments block
|
|
2888
|
+
*/
|
|
2889
|
+
function rewireSource(block) {
|
|
2890
|
+
const source = block.source.reduce((acc, line) => acc.set(line.number, line), new Map());
|
|
2891
|
+
for (const spec of block.tags) {
|
|
2892
|
+
spec.source = spec.source.map((line) => source.get(line.number));
|
|
2893
|
+
}
|
|
2894
|
+
return block;
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
2897
|
+
* Assures Block.source contains references to the Block.tags[].source items,
|
|
2898
|
+
* using Block.tags[].source as a source of truth. This is a counterpart of rewireSource
|
|
2899
|
+
* @param block parsed coments block
|
|
2900
|
+
*/
|
|
2901
|
+
function rewireSpecs(block) {
|
|
2902
|
+
const source = block.tags.reduce((acc, spec) => spec.source.reduce((acc, line) => acc.set(line.number, line), acc), new Map());
|
|
2903
|
+
block.source = block.source.map((line) => source.get(line.number) || line);
|
|
2904
|
+
return block;
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
const reTag = /^@[^\s/]+(?=\s|$)/;
|
|
2908
|
+
/**
|
|
2909
|
+
* Creates configured `Parser`
|
|
2910
|
+
* @param {Partial<Options>} options
|
|
2911
|
+
*/
|
|
2912
|
+
function getParser$3({ fence = '```', } = {}) {
|
|
2913
|
+
const fencer = getFencer(fence);
|
|
2914
|
+
const toggleFence = (source, isFenced) => fencer(source) ? !isFenced : isFenced;
|
|
2915
|
+
return function parseBlock(source) {
|
|
2916
|
+
// start with description section
|
|
2917
|
+
const sections = [[]];
|
|
2918
|
+
let isFenced = false;
|
|
2919
|
+
for (const line of source) {
|
|
2920
|
+
if (reTag.test(line.tokens.description) && !isFenced) {
|
|
2921
|
+
sections.push([line]);
|
|
2922
|
+
}
|
|
2923
|
+
else {
|
|
2924
|
+
sections[sections.length - 1].push(line);
|
|
2925
|
+
}
|
|
2926
|
+
isFenced = toggleFence(line.tokens.description, isFenced);
|
|
2927
|
+
}
|
|
2928
|
+
return sections;
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
function getFencer(fence) {
|
|
2932
|
+
if (typeof fence === 'string')
|
|
2933
|
+
return (source) => source.split(fence).length % 2 === 0;
|
|
2934
|
+
return fence;
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
function getParser$2({ startLine = 0, markers = Markers, } = {}) {
|
|
2938
|
+
let block = null;
|
|
2939
|
+
let num = startLine;
|
|
2940
|
+
return function parseSource(source) {
|
|
2941
|
+
let rest = source;
|
|
2942
|
+
const tokens = seedTokens();
|
|
2943
|
+
[tokens.lineEnd, rest] = splitCR(rest);
|
|
2944
|
+
[tokens.start, rest] = splitSpace(rest);
|
|
2945
|
+
if (block === null &&
|
|
2946
|
+
rest.startsWith(markers.start) &&
|
|
2947
|
+
!rest.startsWith(markers.nostart)) {
|
|
2948
|
+
block = [];
|
|
2949
|
+
tokens.delimiter = rest.slice(0, markers.start.length);
|
|
2950
|
+
rest = rest.slice(markers.start.length);
|
|
2951
|
+
[tokens.postDelimiter, rest] = splitSpace(rest);
|
|
2952
|
+
}
|
|
2953
|
+
if (block === null) {
|
|
2954
|
+
num++;
|
|
2955
|
+
return null;
|
|
2956
|
+
}
|
|
2957
|
+
const isClosed = rest.trimRight().endsWith(markers.end);
|
|
2958
|
+
if (tokens.delimiter === '' &&
|
|
2959
|
+
rest.startsWith(markers.delim) &&
|
|
2960
|
+
!rest.startsWith(markers.end)) {
|
|
2961
|
+
tokens.delimiter = markers.delim;
|
|
2962
|
+
rest = rest.slice(markers.delim.length);
|
|
2963
|
+
[tokens.postDelimiter, rest] = splitSpace(rest);
|
|
2964
|
+
}
|
|
2965
|
+
if (isClosed) {
|
|
2966
|
+
const trimmed = rest.trimRight();
|
|
2967
|
+
tokens.end = rest.slice(trimmed.length - markers.end.length);
|
|
2968
|
+
rest = trimmed.slice(0, -markers.end.length);
|
|
2969
|
+
}
|
|
2970
|
+
tokens.description = rest;
|
|
2971
|
+
block.push({ number: num, source, tokens });
|
|
2972
|
+
num++;
|
|
2973
|
+
if (isClosed) {
|
|
2974
|
+
const result = block.slice();
|
|
2975
|
+
block = null;
|
|
2976
|
+
return result;
|
|
2977
|
+
}
|
|
2978
|
+
return null;
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
function getParser$1({ tokenizers }) {
|
|
2983
|
+
return function parseSpec(source) {
|
|
2984
|
+
var _a;
|
|
2985
|
+
let spec = seedSpec({ source });
|
|
2986
|
+
for (const tokenize of tokenizers) {
|
|
2987
|
+
spec = tokenize(spec);
|
|
2988
|
+
if ((_a = spec.problems[spec.problems.length - 1]) === null || _a === void 0 ? void 0 : _a.critical)
|
|
2989
|
+
break;
|
|
2990
|
+
}
|
|
2991
|
+
return spec;
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
/**
|
|
2996
|
+
* Splits the `@prefix` from remaining `Spec.lines[].token.description` into the `tag` token,
|
|
2997
|
+
* and populates `spec.tag`
|
|
2998
|
+
*/
|
|
2999
|
+
function tagTokenizer() {
|
|
3000
|
+
return (spec) => {
|
|
3001
|
+
const { tokens } = spec.source[0];
|
|
3002
|
+
const match = tokens.description.match(/\s*(@(\S+))(\s*)/);
|
|
3003
|
+
if (match === null) {
|
|
3004
|
+
spec.problems.push({
|
|
3005
|
+
code: 'spec:tag:prefix',
|
|
3006
|
+
message: 'tag should start with "@" symbol',
|
|
3007
|
+
line: spec.source[0].number,
|
|
3008
|
+
critical: true,
|
|
3009
|
+
});
|
|
3010
|
+
return spec;
|
|
3011
|
+
}
|
|
3012
|
+
if (match[1].includes('/')) {
|
|
3013
|
+
return spec;
|
|
3014
|
+
}
|
|
3015
|
+
tokens.tag = match[1];
|
|
3016
|
+
tokens.postTag = match[3];
|
|
3017
|
+
tokens.description = tokens.description.slice(match[0].length);
|
|
3018
|
+
spec.tag = match[2];
|
|
3019
|
+
return spec;
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
/**
|
|
3024
|
+
* Sets splits remaining `Spec.lines[].tokens.description` into `type` and `description`
|
|
3025
|
+
* tokens and populates Spec.type`
|
|
3026
|
+
*
|
|
3027
|
+
* @param {Spacing} spacing tells how to deal with a whitespace
|
|
3028
|
+
* for type values going over multiple lines
|
|
3029
|
+
*/
|
|
3030
|
+
function typeTokenizer(spacing = 'compact') {
|
|
3031
|
+
const join = getJoiner$1(spacing);
|
|
3032
|
+
return (spec) => {
|
|
3033
|
+
let curlies = 0;
|
|
3034
|
+
let lines = [];
|
|
3035
|
+
let descriptionBegun = false;
|
|
3036
|
+
let firstTypeIteration = true;
|
|
3037
|
+
for (const { tokens } of spec.source.values()) {
|
|
3038
|
+
let type = '';
|
|
3039
|
+
if (!descriptionBegun && tokens.description.trim()) {
|
|
3040
|
+
descriptionBegun = true;
|
|
3041
|
+
}
|
|
3042
|
+
else if (!descriptionBegun) {
|
|
3043
|
+
continue;
|
|
3044
|
+
}
|
|
3045
|
+
if (firstTypeIteration && tokens.description[0] !== '{')
|
|
3046
|
+
return spec;
|
|
3047
|
+
firstTypeIteration = false;
|
|
3048
|
+
for (const ch of tokens.description) {
|
|
3049
|
+
if (ch === '{')
|
|
3050
|
+
curlies++;
|
|
3051
|
+
if (ch === '}')
|
|
3052
|
+
curlies--;
|
|
3053
|
+
type += ch;
|
|
3054
|
+
if (curlies === 0)
|
|
3055
|
+
break;
|
|
3056
|
+
}
|
|
3057
|
+
lines.push([tokens, type]);
|
|
3058
|
+
if (curlies === 0)
|
|
3059
|
+
break;
|
|
3060
|
+
}
|
|
3061
|
+
if (!descriptionBegun) {
|
|
3062
|
+
return spec;
|
|
3063
|
+
}
|
|
3064
|
+
if (curlies !== 0) {
|
|
3065
|
+
spec.problems.push({
|
|
3066
|
+
code: 'spec:type:unpaired-curlies',
|
|
3067
|
+
message: 'unpaired curlies',
|
|
3068
|
+
line: spec.source[0].number,
|
|
3069
|
+
critical: true,
|
|
3070
|
+
});
|
|
3071
|
+
return spec;
|
|
3072
|
+
}
|
|
3073
|
+
const parts = [];
|
|
3074
|
+
const offset = lines[0][0].postDelimiter.length;
|
|
3075
|
+
for (const [i, [tokens, type]] of lines.entries()) {
|
|
3076
|
+
tokens.type = type;
|
|
3077
|
+
if (i > 0) {
|
|
3078
|
+
tokens.type = tokens.postDelimiter.slice(offset) + type;
|
|
3079
|
+
tokens.postDelimiter = tokens.postDelimiter.slice(0, offset);
|
|
3080
|
+
}
|
|
3081
|
+
[tokens.postType, tokens.description] = splitSpace(tokens.description.slice(type.length));
|
|
3082
|
+
parts.push(tokens.type);
|
|
3083
|
+
}
|
|
3084
|
+
parts[0] = parts[0].slice(1);
|
|
3085
|
+
parts[parts.length - 1] = parts[parts.length - 1].slice(0, -1);
|
|
3086
|
+
spec.type = join(parts);
|
|
3087
|
+
return spec;
|
|
3088
|
+
};
|
|
3089
|
+
}
|
|
3090
|
+
const trim = (x) => x.trim();
|
|
3091
|
+
function getJoiner$1(spacing) {
|
|
3092
|
+
if (spacing === 'compact')
|
|
3093
|
+
return (t) => t.map(trim).join('');
|
|
3094
|
+
else if (spacing === 'preserve')
|
|
3095
|
+
return (t) => t.join('\n');
|
|
3096
|
+
else
|
|
3097
|
+
return spacing;
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
const isQuoted = (s) => s && s.startsWith('"') && s.endsWith('"');
|
|
3101
|
+
/**
|
|
3102
|
+
* Splits remaining `spec.lines[].tokens.description` into `name` and `descriptions` tokens,
|
|
3103
|
+
* and populates the `spec.name`
|
|
3104
|
+
*/
|
|
3105
|
+
function nameTokenizer() {
|
|
3106
|
+
const typeEnd = (num, { tokens }, i) => tokens.type === '' ? num : i;
|
|
3107
|
+
return (spec) => {
|
|
3108
|
+
// look for the name starting in the line where {type} ends
|
|
3109
|
+
let finalTypeLine = spec.source.reduce(typeEnd, 0);
|
|
3110
|
+
let tokens;
|
|
3111
|
+
if (spec.type) {
|
|
3112
|
+
do {
|
|
3113
|
+
({ tokens } = spec.source[finalTypeLine]);
|
|
3114
|
+
if (tokens.description.trim()) {
|
|
3115
|
+
break;
|
|
3116
|
+
}
|
|
3117
|
+
finalTypeLine++;
|
|
3118
|
+
} while (spec.source[finalTypeLine]);
|
|
3119
|
+
}
|
|
3120
|
+
else {
|
|
3121
|
+
({ tokens } = spec.source[finalTypeLine]);
|
|
3122
|
+
}
|
|
3123
|
+
const source = tokens.description.trimStart();
|
|
3124
|
+
const quotedGroups = source.split('"');
|
|
3125
|
+
// if it starts with quoted group, assume it is a literal
|
|
3126
|
+
if (quotedGroups.length > 1 &&
|
|
3127
|
+
quotedGroups[0] === '' &&
|
|
3128
|
+
quotedGroups.length % 2 === 1) {
|
|
3129
|
+
spec.name = quotedGroups[1];
|
|
3130
|
+
tokens.name = `"${quotedGroups[1]}"`;
|
|
3131
|
+
[tokens.postName, tokens.description] = splitSpace(source.slice(tokens.name.length));
|
|
3132
|
+
return spec;
|
|
3133
|
+
}
|
|
3134
|
+
let brackets = 0;
|
|
3135
|
+
let name = '';
|
|
3136
|
+
let optional = false;
|
|
3137
|
+
let defaultValue;
|
|
3138
|
+
// assume name is non-space string or anything wrapped into brackets
|
|
3139
|
+
for (const ch of source) {
|
|
3140
|
+
if (brackets === 0 && isSpace(ch))
|
|
3141
|
+
break;
|
|
3142
|
+
if (ch === '[')
|
|
3143
|
+
brackets++;
|
|
3144
|
+
if (ch === ']')
|
|
3145
|
+
brackets--;
|
|
3146
|
+
name += ch;
|
|
3147
|
+
}
|
|
3148
|
+
if (brackets !== 0) {
|
|
3149
|
+
spec.problems.push({
|
|
3150
|
+
code: 'spec:name:unpaired-brackets',
|
|
3151
|
+
message: 'unpaired brackets',
|
|
3152
|
+
line: spec.source[0].number,
|
|
3153
|
+
critical: true,
|
|
3154
|
+
});
|
|
3155
|
+
return spec;
|
|
3156
|
+
}
|
|
3157
|
+
const nameToken = name;
|
|
3158
|
+
if (name[0] === '[' && name[name.length - 1] === ']') {
|
|
3159
|
+
optional = true;
|
|
3160
|
+
name = name.slice(1, -1);
|
|
3161
|
+
const parts = name.split('=');
|
|
3162
|
+
name = parts[0].trim();
|
|
3163
|
+
if (parts[1] !== undefined)
|
|
3164
|
+
defaultValue = parts.slice(1).join('=').trim();
|
|
3165
|
+
if (name === '') {
|
|
3166
|
+
spec.problems.push({
|
|
3167
|
+
code: 'spec:name:empty-name',
|
|
3168
|
+
message: 'empty name',
|
|
3169
|
+
line: spec.source[0].number,
|
|
3170
|
+
critical: true,
|
|
3171
|
+
});
|
|
3172
|
+
return spec;
|
|
3173
|
+
}
|
|
3174
|
+
if (defaultValue === '') {
|
|
3175
|
+
spec.problems.push({
|
|
3176
|
+
code: 'spec:name:empty-default',
|
|
3177
|
+
message: 'empty default value',
|
|
3178
|
+
line: spec.source[0].number,
|
|
3179
|
+
critical: true,
|
|
3180
|
+
});
|
|
3181
|
+
return spec;
|
|
3182
|
+
}
|
|
3183
|
+
// has "=" and is not a string, except for "=>"
|
|
3184
|
+
if (!isQuoted(defaultValue) && /=(?!>)/.test(defaultValue)) {
|
|
3185
|
+
spec.problems.push({
|
|
3186
|
+
code: 'spec:name:invalid-default',
|
|
3187
|
+
message: 'invalid default value syntax',
|
|
3188
|
+
line: spec.source[0].number,
|
|
3189
|
+
critical: true,
|
|
3190
|
+
});
|
|
3191
|
+
return spec;
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
spec.optional = optional;
|
|
3195
|
+
spec.name = name;
|
|
3196
|
+
tokens.name = nameToken;
|
|
3197
|
+
if (defaultValue !== undefined)
|
|
3198
|
+
spec.default = defaultValue;
|
|
3199
|
+
[tokens.postName, tokens.description] = splitSpace(source.slice(tokens.name.length));
|
|
3200
|
+
return spec;
|
|
3201
|
+
};
|
|
3202
|
+
}
|
|
3203
|
+
|
|
3204
|
+
/**
|
|
3205
|
+
* Makes no changes to `spec.lines[].tokens` but joins them into `spec.description`
|
|
3206
|
+
* following given spacing srtategy
|
|
3207
|
+
* @param {Spacing} spacing tells how to handle the whitespace
|
|
3208
|
+
* @param {BlockMarkers} markers tells how to handle comment block delimitation
|
|
3209
|
+
*/
|
|
3210
|
+
function descriptionTokenizer(spacing = 'compact', markers = Markers) {
|
|
3211
|
+
const join = getJoiner(spacing);
|
|
3212
|
+
return (spec) => {
|
|
3213
|
+
spec.description = join(spec.source, markers);
|
|
3214
|
+
return spec;
|
|
3215
|
+
};
|
|
3216
|
+
}
|
|
3217
|
+
function getJoiner(spacing) {
|
|
3218
|
+
if (spacing === 'compact')
|
|
3219
|
+
return compactJoiner;
|
|
3220
|
+
if (spacing === 'preserve')
|
|
3221
|
+
return preserveJoiner;
|
|
3222
|
+
return spacing;
|
|
3223
|
+
}
|
|
3224
|
+
function compactJoiner(lines, markers = Markers) {
|
|
3225
|
+
return lines
|
|
3226
|
+
.map(({ tokens: { description } }) => description.trim())
|
|
3227
|
+
.filter((description) => description !== '')
|
|
3228
|
+
.join(' ');
|
|
3229
|
+
}
|
|
3230
|
+
const lineNo = (num, { tokens }, i) => tokens.type === '' ? num : i;
|
|
3231
|
+
const getDescription = ({ tokens }) => (tokens.delimiter === '' ? tokens.start : tokens.postDelimiter.slice(1)) +
|
|
3232
|
+
tokens.description;
|
|
3233
|
+
function preserveJoiner(lines, markers = Markers) {
|
|
3234
|
+
if (lines.length === 0)
|
|
3235
|
+
return '';
|
|
3236
|
+
// skip the opening line with no description
|
|
3237
|
+
if (lines[0].tokens.description === '' &&
|
|
3238
|
+
lines[0].tokens.delimiter === markers.start)
|
|
3239
|
+
lines = lines.slice(1);
|
|
3240
|
+
// skip the closing line with no description
|
|
3241
|
+
const lastLine = lines[lines.length - 1];
|
|
3242
|
+
if (lastLine !== undefined &&
|
|
3243
|
+
lastLine.tokens.description === '' &&
|
|
3244
|
+
lastLine.tokens.end.endsWith(markers.end))
|
|
3245
|
+
lines = lines.slice(0, -1);
|
|
3246
|
+
// description starts at the last line of type definition
|
|
3247
|
+
lines = lines.slice(lines.reduce(lineNo, 0));
|
|
3248
|
+
return lines.map(getDescription).join('\n');
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
function getParser({ startLine = 0, fence = '```', spacing = 'compact', markers = Markers, tokenizers = [
|
|
3252
|
+
tagTokenizer(),
|
|
3253
|
+
typeTokenizer(spacing),
|
|
3254
|
+
nameTokenizer(),
|
|
3255
|
+
descriptionTokenizer(spacing),
|
|
3256
|
+
], } = {}) {
|
|
3257
|
+
if (startLine < 0 || startLine % 1 > 0)
|
|
3258
|
+
throw new Error('Invalid startLine');
|
|
3259
|
+
const parseSource = getParser$2({ startLine, markers });
|
|
3260
|
+
const parseBlock = getParser$3({ fence });
|
|
3261
|
+
const parseSpec = getParser$1({ tokenizers });
|
|
3262
|
+
const joinDescription = getJoiner(spacing);
|
|
3263
|
+
return function (source) {
|
|
3264
|
+
const blocks = [];
|
|
3265
|
+
for (const line of splitLines(source)) {
|
|
3266
|
+
const lines = parseSource(line);
|
|
3267
|
+
if (lines === null)
|
|
3268
|
+
continue;
|
|
3269
|
+
const sections = parseBlock(lines);
|
|
3270
|
+
const specs = sections.slice(1).map(parseSpec);
|
|
3271
|
+
blocks.push({
|
|
3272
|
+
description: joinDescription(sections[0], markers),
|
|
3273
|
+
tags: specs,
|
|
3274
|
+
source: lines,
|
|
3275
|
+
problems: specs.reduce((acc, spec) => acc.concat(spec.problems), []),
|
|
3276
|
+
});
|
|
3277
|
+
}
|
|
3278
|
+
return blocks;
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
function join(tokens) {
|
|
3283
|
+
return (tokens.start +
|
|
3284
|
+
tokens.delimiter +
|
|
3285
|
+
tokens.postDelimiter +
|
|
3286
|
+
tokens.tag +
|
|
3287
|
+
tokens.postTag +
|
|
3288
|
+
tokens.type +
|
|
3289
|
+
tokens.postType +
|
|
3290
|
+
tokens.name +
|
|
3291
|
+
tokens.postName +
|
|
3292
|
+
tokens.description +
|
|
3293
|
+
tokens.end +
|
|
3294
|
+
tokens.lineEnd);
|
|
3295
|
+
}
|
|
3296
|
+
function getStringifier() {
|
|
3297
|
+
return (block) => block.source.map(({ tokens }) => join(tokens)).join('\n');
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
(undefined && undefined.__rest) || function (s, e) {
|
|
3301
|
+
var t = {};
|
|
3302
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
3303
|
+
t[p] = s[p];
|
|
3304
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
3305
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
3306
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
3307
|
+
t[p[i]] = s[p[i]];
|
|
3308
|
+
}
|
|
3309
|
+
return t;
|
|
3310
|
+
};
|
|
3311
|
+
|
|
3312
|
+
(undefined && undefined.__rest) || function (s, e) {
|
|
3313
|
+
var t = {};
|
|
3314
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
3315
|
+
t[p] = s[p];
|
|
3316
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
3317
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
3318
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
3319
|
+
t[p[i]] = s[p[i]];
|
|
3320
|
+
}
|
|
3321
|
+
return t;
|
|
3322
|
+
};
|
|
3323
|
+
|
|
3324
|
+
(undefined && undefined.__rest) || function (s, e) {
|
|
3325
|
+
var t = {};
|
|
3326
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
3327
|
+
t[p] = s[p];
|
|
3328
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
3329
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
3330
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
3331
|
+
t[p[i]] = s[p[i]];
|
|
3332
|
+
}
|
|
3333
|
+
return t;
|
|
3334
|
+
};
|
|
3335
|
+
|
|
3336
|
+
function flow(...transforms) {
|
|
3337
|
+
return (block) => transforms.reduce((block, t) => t(block), block);
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
function parse(source, options = {}) {
|
|
3341
|
+
return getParser(options)(source);
|
|
3342
|
+
}
|
|
3343
|
+
const stringify = getStringifier();
|
|
3344
|
+
const transforms = {
|
|
3345
|
+
flow: flow};
|
|
3346
|
+
const tokenizers = {
|
|
3347
|
+
tag: tagTokenizer,
|
|
3348
|
+
type: typeTokenizer,
|
|
3349
|
+
name: nameTokenizer,
|
|
3350
|
+
description: descriptionTokenizer,
|
|
3351
|
+
};
|
|
3352
|
+
const util = { rewireSpecs, rewireSource, seedTokens };
|
|
3353
|
+
|
|
3354
|
+
exports.parse = parse$1;
|
|
3355
|
+
exports.parse$1 = parse;
|
|
3356
|
+
exports.parseName = parseName;
|
|
3357
|
+
exports.parseNamePath = parseNamePath;
|
|
3358
|
+
exports.stringify = stringify$1;
|
|
3359
|
+
exports.stringify$1 = stringify;
|
|
3360
|
+
exports.tokenizers = tokenizers;
|
|
3361
|
+
exports.transforms = transforms;
|
|
3362
|
+
exports.traverse = traverse;
|
|
3363
|
+
exports.tryParse = tryParse;
|
|
3364
|
+
exports.util = util;
|
|
3365
|
+
exports.visitorKeys = visitorKeys;
|