@alexlit/lint-kit 182.0.0 → 182.1.0
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/package.json +1 -1
- package/packages/config-commitlint/package.json +3 -3
- package/packages/config-eslint/package.json +7 -7
- package/packages/config-stylelint/package.json +3 -3
- package/packages/config-eslint/node_modules/eslint-visitor-keys/LICENSE +0 -201
- package/packages/config-eslint/node_modules/eslint-visitor-keys/README.md +0 -121
- package/packages/config-eslint/node_modules/eslint-visitor-keys/dist/eslint-visitor-keys.cjs +0 -396
- package/packages/config-eslint/node_modules/eslint-visitor-keys/dist/eslint-visitor-keys.d.cts +0 -28
- package/packages/config-eslint/node_modules/eslint-visitor-keys/dist/index.d.ts +0 -16
- package/packages/config-eslint/node_modules/eslint-visitor-keys/dist/visitor-keys.d.ts +0 -12
- package/packages/config-eslint/node_modules/eslint-visitor-keys/lib/index.js +0 -67
- package/packages/config-eslint/node_modules/eslint-visitor-keys/lib/visitor-keys.js +0 -327
- package/packages/config-eslint/node_modules/eslint-visitor-keys/package.json +0 -59
- package/packages/config-eslint/node_modules/jsonc-eslint-parser/LICENSE +0 -21
- package/packages/config-eslint/node_modules/jsonc-eslint-parser/README.md +0 -109
- package/packages/config-eslint/node_modules/jsonc-eslint-parser/lib/chunk-C7Uep-_p.mjs +0 -20
- package/packages/config-eslint/node_modules/jsonc-eslint-parser/lib/index.d.mts +0 -210
- package/packages/config-eslint/node_modules/jsonc-eslint-parser/lib/index.mjs +0 -1305
- package/packages/config-eslint/node_modules/jsonc-eslint-parser/package.json +0 -98
|
@@ -1,1305 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./chunk-C7Uep-_p.mjs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import * as Evk from "eslint-visitor-keys";
|
|
4
|
-
import evkPkg from "eslint-visitor-keys/package.json" with { type: "json" };
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { lte } from "semver";
|
|
7
|
-
import * as acorn from "acorn";
|
|
8
|
-
import acornPkg from "acorn/package.json" with { type: "json" };
|
|
9
|
-
|
|
10
|
-
//#region src/parser/modules/require-utils.ts
|
|
11
|
-
/**
|
|
12
|
-
* Get NodeJS.Require from Linter
|
|
13
|
-
*/
|
|
14
|
-
function getRequireFromLinter() {
|
|
15
|
-
try {
|
|
16
|
-
const eslintPkgPath = getRequireFromCwd()?.resolve("eslint/package.json");
|
|
17
|
-
if (!eslintPkgPath) return null;
|
|
18
|
-
return createRequire(path.join(path.dirname(eslintPkgPath), "__placeholder__.js"));
|
|
19
|
-
} catch {}
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Get NodeJS.Require from Cwd
|
|
24
|
-
*/
|
|
25
|
-
function getRequireFromCwd() {
|
|
26
|
-
try {
|
|
27
|
-
const cwd = process.cwd();
|
|
28
|
-
return createRequire(path.join(cwd, "__placeholder__.js"));
|
|
29
|
-
} catch {}
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Get module from Linter
|
|
34
|
-
*/
|
|
35
|
-
function requireFromLinter(module) {
|
|
36
|
-
try {
|
|
37
|
-
return getRequireFromLinter()?.(module);
|
|
38
|
-
} catch {}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Get module path from Linter
|
|
43
|
-
*/
|
|
44
|
-
function resolveFromLinter(module) {
|
|
45
|
-
try {
|
|
46
|
-
return getRequireFromLinter()?.resolve(module) ?? null;
|
|
47
|
-
} catch {}
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Get module from Cwd
|
|
52
|
-
*/
|
|
53
|
-
function requireFromCwd(module) {
|
|
54
|
-
try {
|
|
55
|
-
return getRequireFromCwd()?.(module);
|
|
56
|
-
} catch {}
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Get module path from Cwd
|
|
61
|
-
*/
|
|
62
|
-
function resolveFromCwd(module) {
|
|
63
|
-
try {
|
|
64
|
-
return getRequireFromCwd()?.resolve(module) ?? null;
|
|
65
|
-
} catch {}
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Get the newest `espree` kind from the loaded ESLint or dependency.
|
|
70
|
-
*/
|
|
71
|
-
function loadNewest(items) {
|
|
72
|
-
let target = null;
|
|
73
|
-
for (const item of items) {
|
|
74
|
-
const pkg = item.getPkg();
|
|
75
|
-
if (pkg != null && (!target || lte(target.version, pkg.version))) target = {
|
|
76
|
-
version: pkg.version,
|
|
77
|
-
get: item.get
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
return target.get();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/parser/visitor-keys.ts
|
|
85
|
-
const jsonKeys = {
|
|
86
|
-
Program: ["body"],
|
|
87
|
-
JSONExpressionStatement: ["expression"],
|
|
88
|
-
JSONArrayExpression: ["elements"],
|
|
89
|
-
JSONObjectExpression: ["properties"],
|
|
90
|
-
JSONProperty: ["key", "value"],
|
|
91
|
-
JSONIdentifier: [],
|
|
92
|
-
JSONLiteral: [],
|
|
93
|
-
JSONUnaryExpression: ["argument"],
|
|
94
|
-
JSONTemplateLiteral: ["quasis", "expressions"],
|
|
95
|
-
JSONTemplateElement: [],
|
|
96
|
-
JSONBinaryExpression: ["left", "right"]
|
|
97
|
-
};
|
|
98
|
-
let cache = null;
|
|
99
|
-
/**
|
|
100
|
-
* Get visitor keys
|
|
101
|
-
*/
|
|
102
|
-
function getVisitorKeys() {
|
|
103
|
-
if (!cache) cache = loadNewest([
|
|
104
|
-
{
|
|
105
|
-
getPkg() {
|
|
106
|
-
return requireFromCwd("eslint-visitor-keys/package.json");
|
|
107
|
-
},
|
|
108
|
-
get() {
|
|
109
|
-
return requireFromCwd("eslint-visitor-keys");
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
getPkg() {
|
|
114
|
-
return requireFromLinter("eslint-visitor-keys/package.json");
|
|
115
|
-
},
|
|
116
|
-
get() {
|
|
117
|
-
return requireFromLinter("eslint-visitor-keys");
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
getPkg() {
|
|
122
|
-
return evkPkg;
|
|
123
|
-
},
|
|
124
|
-
get() {
|
|
125
|
-
return Evk;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
]).unionWith(jsonKeys);
|
|
129
|
-
return cache;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
//#endregion
|
|
133
|
-
//#region src/parser/utils.ts
|
|
134
|
-
/**
|
|
135
|
-
* Check if the given node is RegExpLiteral
|
|
136
|
-
*/
|
|
137
|
-
function isRegExpLiteral(node) {
|
|
138
|
-
return Boolean(node.regex) || node.raw.startsWith("/");
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
//#endregion
|
|
142
|
-
//#region src/parser/errors.ts
|
|
143
|
-
/**
|
|
144
|
-
* JSON parse errors.
|
|
145
|
-
*/
|
|
146
|
-
var ParseError = class extends SyntaxError {
|
|
147
|
-
/**
|
|
148
|
-
* Initialize this ParseError instance.
|
|
149
|
-
* @param message The error message.
|
|
150
|
-
* @param code The error code. See also: https://html.spec.whatwg.org/multipage/parsing.html#parse-errors
|
|
151
|
-
* @param offset The offset number of this error.
|
|
152
|
-
* @param line The line number of this error.
|
|
153
|
-
* @param column The column number of this error.
|
|
154
|
-
*/
|
|
155
|
-
constructor(message, offset, line, column) {
|
|
156
|
-
super(message);
|
|
157
|
-
this.index = offset;
|
|
158
|
-
this.lineNumber = line;
|
|
159
|
-
this.column = column;
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
/**
|
|
163
|
-
* Throw syntax error for expected token.
|
|
164
|
-
* @param name The token name.
|
|
165
|
-
* @param token The token object to get that location.
|
|
166
|
-
*/
|
|
167
|
-
function throwExpectedTokenError(name, beforeToken) {
|
|
168
|
-
const locs = getLocation(beforeToken);
|
|
169
|
-
throw new ParseError(`Expected token '${name}'.`, locs.end, locs.loc.end.line, locs.loc.end.column + 1);
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Throw syntax error for unexpected name.
|
|
173
|
-
* @param name The unexpected name.
|
|
174
|
-
* @param token The token object to get that location.
|
|
175
|
-
*/
|
|
176
|
-
function throwUnexpectedError(name, token) {
|
|
177
|
-
const locs = getLocation(token);
|
|
178
|
-
throw new ParseError(`Unexpected ${name}.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Throw syntax error for unexpected token.
|
|
182
|
-
* @param name The token name.
|
|
183
|
-
* @param token The token object to get that location.
|
|
184
|
-
*/
|
|
185
|
-
function throwUnexpectedTokenError(name, token) {
|
|
186
|
-
return throwUnexpectedError(`token '${name}'`, token);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Throw syntax error for unexpected comment.
|
|
190
|
-
* @param name The token name.
|
|
191
|
-
* @param token The token object to get that location.
|
|
192
|
-
*/
|
|
193
|
-
function throwUnexpectedCommentError(token) {
|
|
194
|
-
return throwUnexpectedError("comment", token);
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Throw syntax error for unexpected whitespace.
|
|
198
|
-
*/
|
|
199
|
-
function throwUnexpectedSpaceError(beforeToken) {
|
|
200
|
-
const locs = getLocation(beforeToken);
|
|
201
|
-
throw new ParseError("Unexpected whitespace.", locs.end, locs.loc.end.line, locs.loc.end.column + 1);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Throw syntax error for unexpected invalid number.
|
|
205
|
-
*/
|
|
206
|
-
function throwInvalidNumberError(text, token) {
|
|
207
|
-
const locs = getLocation(token);
|
|
208
|
-
throw new ParseError(`Invalid number ${text}.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Throw syntax error for unexpected token.
|
|
212
|
-
* @param node The token object to get that location.
|
|
213
|
-
*/
|
|
214
|
-
function throwUnexpectedNodeError(node, tokens, offset) {
|
|
215
|
-
if (node.type === "Identifier" || node.type === "JSONIdentifier") {
|
|
216
|
-
const locs = getLocation(node);
|
|
217
|
-
throw new ParseError(`Unexpected identifier '${node.name}'.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
218
|
-
}
|
|
219
|
-
if (node.type === "Literal" || node.type === "JSONLiteral") {
|
|
220
|
-
const type = node.bigint ? "bigint" : isRegExpLiteral(node) ? "regex" : node.value === null ? "null" : typeof node.value;
|
|
221
|
-
const locs = getLocation(node);
|
|
222
|
-
throw new ParseError(`Unexpected ${type} literal.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
223
|
-
}
|
|
224
|
-
if (node.type === "TemplateLiteral" || node.type === "JSONTemplateLiteral") {
|
|
225
|
-
const locs = getLocation(node);
|
|
226
|
-
throw new ParseError("Unexpected template literal.", locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
227
|
-
}
|
|
228
|
-
if (node.type.endsWith("Expression") && node.type !== "FunctionExpression") {
|
|
229
|
-
const name = node.type.replace(/^JSON/u, "").replace(/\B([A-Z])/gu, " $1").toLowerCase();
|
|
230
|
-
const locs = getLocation(node);
|
|
231
|
-
throw new ParseError(`Unexpected ${name}.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
232
|
-
}
|
|
233
|
-
const index = node.range[0] + (offset || 0);
|
|
234
|
-
const t = tokens.findTokenByOffset(index);
|
|
235
|
-
const name = t?.value || "unknown";
|
|
236
|
-
const locs = getLocation(t || node);
|
|
237
|
-
throw new ParseError(`Unexpected token '${name}'.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1);
|
|
238
|
-
}
|
|
239
|
-
/** get locations */
|
|
240
|
-
function getLocation(token) {
|
|
241
|
-
return {
|
|
242
|
-
start: token.range?.[0] ?? token.start,
|
|
243
|
-
end: token.range?.[1] ?? token.end,
|
|
244
|
-
loc: token.loc
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
//#endregion
|
|
249
|
-
//#region src/parser/token-store.ts
|
|
250
|
-
var TokenStore = class {
|
|
251
|
-
constructor(tokens) {
|
|
252
|
-
this.tokens = tokens;
|
|
253
|
-
}
|
|
254
|
-
add(token) {
|
|
255
|
-
this.tokens.push(token);
|
|
256
|
-
}
|
|
257
|
-
findIndexByOffset(offset) {
|
|
258
|
-
return this.tokens.findIndex((token) => token.range[0] <= offset && offset < token.range[1]);
|
|
259
|
-
}
|
|
260
|
-
findTokenByOffset(offset) {
|
|
261
|
-
return this.tokens[this.findIndexByOffset(offset)];
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Get the first token representing the given node.
|
|
265
|
-
*
|
|
266
|
-
*/
|
|
267
|
-
getFirstToken(nodeOrToken) {
|
|
268
|
-
return this.findTokenByOffset(nodeOrToken.range[0]);
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Get the last token representing the given node.
|
|
272
|
-
*
|
|
273
|
-
*/
|
|
274
|
-
getLastToken(nodeOrToken) {
|
|
275
|
-
return this.findTokenByOffset(nodeOrToken.range[1] - 1);
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Get the first token before the given node or token.
|
|
279
|
-
*/
|
|
280
|
-
getTokenBefore(nodeOrToken, filter) {
|
|
281
|
-
const tokenIndex = this.findIndexByOffset(nodeOrToken.range[0]);
|
|
282
|
-
for (let index = tokenIndex - 1; index >= 0; index--) {
|
|
283
|
-
const token = this.tokens[index];
|
|
284
|
-
if (!filter || filter(token)) return token;
|
|
285
|
-
}
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Get the first token after the given node or token.
|
|
290
|
-
*/
|
|
291
|
-
getTokenAfter(nodeOrToken, filter) {
|
|
292
|
-
const tokenIndex = this.findIndexByOffset(nodeOrToken.range[0]);
|
|
293
|
-
for (let index = tokenIndex + 1; index < this.tokens.length; index++) {
|
|
294
|
-
const token = this.tokens[index];
|
|
295
|
-
if (!filter || filter(token)) return token;
|
|
296
|
-
}
|
|
297
|
-
return null;
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
/**
|
|
301
|
-
* Checks if given token is comma
|
|
302
|
-
*/
|
|
303
|
-
function isComma(token) {
|
|
304
|
-
return token.type === "Punctuator" && token.value === ",";
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
//#endregion
|
|
308
|
-
//#region src/parser/validate.ts
|
|
309
|
-
const lineBreakPattern = /\r\n|[\n\r\u2028\u2029]/u;
|
|
310
|
-
const octalNumericLiteralPattern = /^0o/iu;
|
|
311
|
-
const legacyOctalNumericLiteralPattern = /^0\d/u;
|
|
312
|
-
const binaryNumericLiteralPattern = /^0b/iu;
|
|
313
|
-
const unicodeCodepointEscapePattern = /\\u\{[\dA-Fa-f]+\}/uy;
|
|
314
|
-
/**
|
|
315
|
-
* Check if given string has unicode codepoint escape
|
|
316
|
-
*/
|
|
317
|
-
function hasUnicodeCodepointEscapes(code) {
|
|
318
|
-
let escaped = false;
|
|
319
|
-
for (let index = 0; index < code.length - 4; index++) {
|
|
320
|
-
if (escaped) {
|
|
321
|
-
escaped = false;
|
|
322
|
-
continue;
|
|
323
|
-
}
|
|
324
|
-
if (code[index] === "\\") {
|
|
325
|
-
unicodeCodepointEscapePattern.lastIndex = index;
|
|
326
|
-
if (unicodeCodepointEscapePattern.test(code)) return true;
|
|
327
|
-
escaped = true;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return false;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Validate ES node
|
|
334
|
-
*/
|
|
335
|
-
function validateNode(node, tokens, ctx) {
|
|
336
|
-
if (node.type === "ObjectExpression") {
|
|
337
|
-
validateObjectExpressionNode(node, tokens, ctx);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
if (node.type === "Property") {
|
|
341
|
-
validatePropertyNode(node, tokens, ctx);
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
if (node.type === "ArrayExpression") {
|
|
345
|
-
validateArrayExpressionNode(node, tokens, ctx);
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
if (node.type === "Literal") {
|
|
349
|
-
validateLiteralNode(node, tokens, ctx);
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
if (node.type === "UnaryExpression") {
|
|
353
|
-
validateUnaryExpressionNode(node, tokens, ctx);
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
if (node.type === "Identifier") {
|
|
357
|
-
validateIdentifierNode(node, tokens, ctx);
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
if (node.type === "TemplateLiteral") {
|
|
361
|
-
validateTemplateLiteralNode(node, tokens, ctx);
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
if (node.type === "TemplateElement") {
|
|
365
|
-
validateTemplateElementNode(node, tokens);
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
if (node.type === "BinaryExpression") {
|
|
369
|
-
validateBinaryExpressionNode(node, tokens, ctx);
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
throw throwUnexpectedNodeError(node, tokens);
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Validate ObjectExpression node
|
|
376
|
-
*/
|
|
377
|
-
function validateObjectExpressionNode(node, tokens, ctx) {
|
|
378
|
-
/* istanbul ignore next */
|
|
379
|
-
if (node.type !== "ObjectExpression") throw throwUnexpectedNodeError(node, tokens);
|
|
380
|
-
for (const prop of node.properties) setParent$1(prop, node);
|
|
381
|
-
if (!ctx.trailingCommas) {
|
|
382
|
-
const token = tokens.getTokenBefore(tokens.getLastToken(node));
|
|
383
|
-
if (token && isComma(token)) throw throwUnexpectedTokenError(",", token);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Validate Property node
|
|
388
|
-
*/
|
|
389
|
-
function validatePropertyNode(node, tokens, ctx) {
|
|
390
|
-
if (node.type !== "Property") throw throwUnexpectedNodeError(node, tokens);
|
|
391
|
-
setParent$1(node.key, node);
|
|
392
|
-
setParent$1(node.value, node);
|
|
393
|
-
if (node.computed) throw throwUnexpectedNodeError(node, tokens);
|
|
394
|
-
if (node.method) throw throwUnexpectedNodeError(node.value, tokens);
|
|
395
|
-
if (node.shorthand) throw throwExpectedTokenError(":", node);
|
|
396
|
-
if (node.kind !== "init") throw throwExpectedTokenError(":", tokens.getFirstToken(node));
|
|
397
|
-
if (node.key.type === "Literal") {
|
|
398
|
-
const keyValueType = typeof node.key.value;
|
|
399
|
-
if (keyValueType === "number") {
|
|
400
|
-
if (!ctx.numberProperties) throw throwUnexpectedNodeError(node.key, tokens);
|
|
401
|
-
} else if (keyValueType !== "string") throw throwUnexpectedNodeError(node.key, tokens);
|
|
402
|
-
} else if (node.key.type === "Identifier") {
|
|
403
|
-
if (!ctx.unquoteProperties) throw throwUnexpectedNodeError(node.key, tokens);
|
|
404
|
-
} else throw throwUnexpectedNodeError(node.key, tokens);
|
|
405
|
-
if (node.value.type === "Identifier") {
|
|
406
|
-
if (!isStaticValueIdentifier(node.value, ctx)) throw throwUnexpectedNodeError(node.value, tokens);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* Validate ArrayExpression node
|
|
411
|
-
*/
|
|
412
|
-
function validateArrayExpressionNode(node, tokens, ctx) {
|
|
413
|
-
/* istanbul ignore next */
|
|
414
|
-
if (node.type !== "ArrayExpression") throw throwUnexpectedNodeError(node, tokens);
|
|
415
|
-
if (!ctx.trailingCommas) {
|
|
416
|
-
const token = tokens.getTokenBefore(tokens.getLastToken(node));
|
|
417
|
-
if (token && isComma(token)) throw throwUnexpectedTokenError(",", token);
|
|
418
|
-
}
|
|
419
|
-
node.elements.forEach((child, index) => {
|
|
420
|
-
if (!child) {
|
|
421
|
-
if (ctx.sparseArrays) return;
|
|
422
|
-
const beforeIndex = index - 1;
|
|
423
|
-
const before = beforeIndex >= 0 ? tokens.getLastToken(node.elements[beforeIndex]) : tokens.getFirstToken(node);
|
|
424
|
-
throw throwUnexpectedTokenError(",", tokens.getTokenAfter(before, isComma));
|
|
425
|
-
}
|
|
426
|
-
if (child.type === "Identifier") {
|
|
427
|
-
if (!isStaticValueIdentifier(child, ctx)) throw throwUnexpectedNodeError(child, tokens);
|
|
428
|
-
}
|
|
429
|
-
setParent$1(child, node);
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
/**
|
|
433
|
-
* Validate Literal node
|
|
434
|
-
*/
|
|
435
|
-
function validateLiteralNode(node, tokens, ctx) {
|
|
436
|
-
/* istanbul ignore next */
|
|
437
|
-
if (node.type !== "Literal") throw throwUnexpectedNodeError(node, tokens);
|
|
438
|
-
if (isRegExpLiteral(node)) {
|
|
439
|
-
if (!ctx.regExpLiterals) throw throwUnexpectedNodeError(node, tokens);
|
|
440
|
-
} else if (node.bigint) {
|
|
441
|
-
if (!ctx.bigintLiterals) throw throwUnexpectedNodeError(node, tokens);
|
|
442
|
-
} else validateLiteral(node, ctx);
|
|
443
|
-
}
|
|
444
|
-
/**
|
|
445
|
-
* Validate literal
|
|
446
|
-
*/
|
|
447
|
-
function validateLiteral(node, ctx) {
|
|
448
|
-
const value = node.value;
|
|
449
|
-
if ((!ctx.invalidJsonNumbers || !ctx.leadingOrTrailingDecimalPoints || !ctx.numericSeparators) && typeof value === "number") {
|
|
450
|
-
const text = node.raw;
|
|
451
|
-
if (!ctx.leadingOrTrailingDecimalPoints) {
|
|
452
|
-
if (text.startsWith(".")) throw throwUnexpectedTokenError(".", node);
|
|
453
|
-
if (text.endsWith(".")) throw throwUnexpectedTokenError(".", {
|
|
454
|
-
range: [node.range[1] - 1, node.range[1]],
|
|
455
|
-
loc: {
|
|
456
|
-
start: {
|
|
457
|
-
line: node.loc.end.line,
|
|
458
|
-
column: node.loc.end.column - 1
|
|
459
|
-
},
|
|
460
|
-
end: node.loc.end
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
if (!ctx.numericSeparators) {
|
|
465
|
-
if (text.includes("_")) {
|
|
466
|
-
const index = text.indexOf("_");
|
|
467
|
-
throw throwUnexpectedTokenError("_", {
|
|
468
|
-
range: [node.range[0] + index, node.range[0] + index + 1],
|
|
469
|
-
loc: {
|
|
470
|
-
start: {
|
|
471
|
-
line: node.loc.start.line,
|
|
472
|
-
column: node.loc.start.column + index
|
|
473
|
-
},
|
|
474
|
-
end: {
|
|
475
|
-
line: node.loc.start.line,
|
|
476
|
-
column: node.loc.start.column + index + 1
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
if (!ctx.octalNumericLiterals) {
|
|
483
|
-
if (octalNumericLiteralPattern.test(text)) throw throwUnexpectedError("octal numeric literal", node);
|
|
484
|
-
}
|
|
485
|
-
if (!ctx.legacyOctalNumericLiterals) {
|
|
486
|
-
if (legacyOctalNumericLiteralPattern.test(text)) throw throwUnexpectedError("legacy octal numeric literal", node);
|
|
487
|
-
}
|
|
488
|
-
if (!ctx.binaryNumericLiterals) {
|
|
489
|
-
if (binaryNumericLiteralPattern.test(text)) throw throwUnexpectedError("binary numeric literal", node);
|
|
490
|
-
}
|
|
491
|
-
if (!ctx.invalidJsonNumbers) try {
|
|
492
|
-
JSON.parse(text);
|
|
493
|
-
} catch {
|
|
494
|
-
throw throwInvalidNumberError(text, node);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
if ((!ctx.multilineStrings || !ctx.singleQuotes || !ctx.unicodeCodepointEscapes) && typeof value === "string") {
|
|
498
|
-
if (!ctx.singleQuotes) {
|
|
499
|
-
if (node.raw.startsWith("'")) throw throwUnexpectedError("single quoted", node);
|
|
500
|
-
}
|
|
501
|
-
if (!ctx.multilineStrings) {
|
|
502
|
-
if (lineBreakPattern.test(node.raw)) throw throwUnexpectedError("multiline string", node);
|
|
503
|
-
}
|
|
504
|
-
if (!ctx.unicodeCodepointEscapes) {
|
|
505
|
-
if (hasUnicodeCodepointEscapes(node.raw)) throw throwUnexpectedError("unicode codepoint escape", node);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* Validate UnaryExpression node
|
|
511
|
-
*/
|
|
512
|
-
function validateUnaryExpressionNode(node, tokens, ctx) {
|
|
513
|
-
/* istanbul ignore next */
|
|
514
|
-
if (node.type !== "UnaryExpression") throw throwUnexpectedNodeError(node, tokens);
|
|
515
|
-
const operator = node.operator;
|
|
516
|
-
if (operator === "+") {
|
|
517
|
-
if (!ctx.plusSigns) throw throwUnexpectedTokenError("+", node);
|
|
518
|
-
} else if (operator !== "-") throw throwUnexpectedNodeError(node, tokens);
|
|
519
|
-
const argument = node.argument;
|
|
520
|
-
if (argument.type === "Literal") {
|
|
521
|
-
if (typeof argument.value !== "number") throw throwUnexpectedNodeError(argument, tokens);
|
|
522
|
-
} else if (argument.type === "Identifier") {
|
|
523
|
-
if (!isNumberIdentifier$1(argument, ctx)) throw throwUnexpectedNodeError(argument, tokens);
|
|
524
|
-
} else throw throwUnexpectedNodeError(argument, tokens);
|
|
525
|
-
if (!ctx.spacedSigns) {
|
|
526
|
-
if (node.range[0] + 1 < argument.range[0]) throw throwUnexpectedSpaceError(tokens.getFirstToken(node));
|
|
527
|
-
}
|
|
528
|
-
setParent$1(argument, node);
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Validate Identifier node
|
|
532
|
-
*/
|
|
533
|
-
function validateIdentifierNode(node, tokens, ctx) {
|
|
534
|
-
/* istanbul ignore next */
|
|
535
|
-
if (node.type !== "Identifier") throw throwUnexpectedNodeError(node, tokens);
|
|
536
|
-
if (!ctx.escapeSequenceInIdentifier) {
|
|
537
|
-
if (node.name.length < node.range[1] - node.range[0]) throw throwUnexpectedError("escape sequence", node);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Validate TemplateLiteral node
|
|
542
|
-
*/
|
|
543
|
-
function validateTemplateLiteralNode(node, tokens, ctx) {
|
|
544
|
-
/* istanbul ignore next */
|
|
545
|
-
if (node.type !== "TemplateLiteral") throw throwUnexpectedNodeError(node, tokens);
|
|
546
|
-
if (!ctx.templateLiterals) throw throwUnexpectedNodeError(node, tokens);
|
|
547
|
-
if (node.expressions.length) {
|
|
548
|
-
const token = tokens.getFirstToken(node.quasis[0]);
|
|
549
|
-
throw throwUnexpectedTokenError("$", {
|
|
550
|
-
loc: {
|
|
551
|
-
start: {
|
|
552
|
-
line: token.loc.end.line,
|
|
553
|
-
column: token.loc.end.column - 2
|
|
554
|
-
},
|
|
555
|
-
end: token.loc.end
|
|
556
|
-
},
|
|
557
|
-
range: [token.range[1] - 2, token.range[1]]
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
if (!ctx.unicodeCodepointEscapes) {
|
|
561
|
-
if (hasUnicodeCodepointEscapes(node.quasis[0].value.raw)) throw throwUnexpectedError("unicode codepoint escape", node);
|
|
562
|
-
}
|
|
563
|
-
for (const q of node.quasis) setParent$1(q, node);
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* Validate TemplateElement node
|
|
567
|
-
*/
|
|
568
|
-
function validateTemplateElementNode(node, tokens) {
|
|
569
|
-
/* istanbul ignore next */
|
|
570
|
-
if (node.type !== "TemplateElement") throw throwUnexpectedNodeError(node, tokens);
|
|
571
|
-
const { cooked } = node.value;
|
|
572
|
-
if (cooked == null) throw throwUnexpectedNodeError(node, tokens);
|
|
573
|
-
const startOffset = -1;
|
|
574
|
-
const endOffset = node.tail ? 1 : 2;
|
|
575
|
-
node.start += startOffset;
|
|
576
|
-
node.end += endOffset;
|
|
577
|
-
node.range[0] += startOffset;
|
|
578
|
-
node.range[1] += endOffset;
|
|
579
|
-
node.loc.start.column += startOffset;
|
|
580
|
-
node.loc.end.column += endOffset;
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Validate BinaryExpression node
|
|
584
|
-
*/
|
|
585
|
-
function validateBinaryExpressionNode(node, tokens, ctx) {
|
|
586
|
-
/* istanbul ignore next */
|
|
587
|
-
if (node.type !== "BinaryExpression") throw throwUnexpectedNodeError(node, tokens);
|
|
588
|
-
if (!ctx.staticExpressions) throw throwUnexpectedNodeError(node, tokens);
|
|
589
|
-
const { operator, left, right } = node;
|
|
590
|
-
if (operator !== "+" && operator !== "-" && operator !== "*" && operator !== "/" && operator !== "%" && operator !== "**") throw throwOperatorError();
|
|
591
|
-
if (left.type === "PrivateIdentifier") throw throwUnexpectedNodeError(left, tokens);
|
|
592
|
-
validateExpr(left, throwOperatorError);
|
|
593
|
-
validateExpr(right, () => throwUnexpectedNodeError(right, tokens));
|
|
594
|
-
/**
|
|
595
|
-
* Validate Expression node
|
|
596
|
-
*/
|
|
597
|
-
function validateExpr(expr, throwError) {
|
|
598
|
-
if (expr.type === "Literal") {
|
|
599
|
-
if (typeof expr.value !== "number") throw throwError();
|
|
600
|
-
} else if (expr.type !== "BinaryExpression" && expr.type !== "UnaryExpression") throw throwError();
|
|
601
|
-
setParent$1(expr, node);
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Throw error
|
|
605
|
-
*/
|
|
606
|
-
function throwOperatorError() {
|
|
607
|
-
throw throwUnexpectedTokenError(operator, tokens.getTokenAfter(tokens.getFirstToken(node), (t) => t.value === operator) || node);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Check if given node is NaN or Infinity or undefined
|
|
612
|
-
*/
|
|
613
|
-
function isStaticValueIdentifier(node, ctx) {
|
|
614
|
-
if (isNumberIdentifier$1(node, ctx)) return true;
|
|
615
|
-
return node.name === "undefined" && ctx.undefinedKeywords;
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Check if given node is NaN or Infinity
|
|
619
|
-
*/
|
|
620
|
-
function isNumberIdentifier$1(node, ctx) {
|
|
621
|
-
if (node.name === "Infinity" && ctx.infinities) return true;
|
|
622
|
-
if (node.name === "NaN" && ctx.nans) return true;
|
|
623
|
-
return false;
|
|
624
|
-
}
|
|
625
|
-
/** Set parent node */
|
|
626
|
-
function setParent$1(prop, parent) {
|
|
627
|
-
prop.parent = parent;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
//#endregion
|
|
631
|
-
//#region src/parser/modules/espree.ts
|
|
632
|
-
let espreeCache = null;
|
|
633
|
-
/**
|
|
634
|
-
* Get the path to the loaded `espree`'s package.json.
|
|
635
|
-
* If the loaded ESLint was not found, just returns `require.resolve("espree/package.json")`.
|
|
636
|
-
*/
|
|
637
|
-
function getEspreePath() {
|
|
638
|
-
const data = getEspreeData();
|
|
639
|
-
if (!data) return null;
|
|
640
|
-
return path.dirname(data.packageJsonPath);
|
|
641
|
-
}
|
|
642
|
-
/**
|
|
643
|
-
*
|
|
644
|
-
*/
|
|
645
|
-
function getEspreeData() {
|
|
646
|
-
if (!espreeCache) espreeCache = loadNewest([{
|
|
647
|
-
getPkg() {
|
|
648
|
-
return requireFromCwd("espree/package.json");
|
|
649
|
-
},
|
|
650
|
-
get() {
|
|
651
|
-
const packageJsonPath = resolveFromCwd("espree/package.json");
|
|
652
|
-
if (!packageJsonPath) return null;
|
|
653
|
-
return {
|
|
654
|
-
packageJsonPath,
|
|
655
|
-
kind: "cwd"
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
}, {
|
|
659
|
-
getPkg() {
|
|
660
|
-
return requireFromLinter("espree/package.json");
|
|
661
|
-
},
|
|
662
|
-
get() {
|
|
663
|
-
const packageJsonPath = resolveFromLinter("espree/package.json");
|
|
664
|
-
if (!packageJsonPath) return null;
|
|
665
|
-
return {
|
|
666
|
-
packageJsonPath,
|
|
667
|
-
kind: "linter"
|
|
668
|
-
};
|
|
669
|
-
}
|
|
670
|
-
}]);
|
|
671
|
-
return espreeCache;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
//#endregion
|
|
675
|
-
//#region src/parser/modules/acorn.ts
|
|
676
|
-
let acornCache;
|
|
677
|
-
/**
|
|
678
|
-
* Load `acorn` from the loaded ESLint.
|
|
679
|
-
* If the loaded ESLint was not found, just returns `require("acorn")`.
|
|
680
|
-
*/
|
|
681
|
-
function getAcorn() {
|
|
682
|
-
if (!acornCache) acornCache = loadNewest([
|
|
683
|
-
{
|
|
684
|
-
getPkg() {
|
|
685
|
-
return requireFromCwd("acorn/package.json");
|
|
686
|
-
},
|
|
687
|
-
get() {
|
|
688
|
-
return requireFromCwd("acorn");
|
|
689
|
-
}
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
getPkg() {
|
|
693
|
-
return requireFromEspree("acorn/package.json");
|
|
694
|
-
},
|
|
695
|
-
get() {
|
|
696
|
-
return requireFromEspree("acorn");
|
|
697
|
-
}
|
|
698
|
-
},
|
|
699
|
-
{
|
|
700
|
-
getPkg() {
|
|
701
|
-
return acornPkg;
|
|
702
|
-
},
|
|
703
|
-
get() {
|
|
704
|
-
return acorn;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
]);
|
|
708
|
-
return acornCache;
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Get module from espree
|
|
712
|
-
*/
|
|
713
|
-
function requireFromEspree(module) {
|
|
714
|
-
try {
|
|
715
|
-
const espreePath = getEspreePath();
|
|
716
|
-
if (!espreePath) return null;
|
|
717
|
-
return createRequire(path.join(espreePath, "__placeholder__.js"))(module);
|
|
718
|
-
} catch {}
|
|
719
|
-
return null;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
//#endregion
|
|
723
|
-
//#region src/parser/convert.ts
|
|
724
|
-
var TokenConvertor = class {
|
|
725
|
-
constructor(ctx, code) {
|
|
726
|
-
this.templateBuffer = [];
|
|
727
|
-
this.ctx = ctx;
|
|
728
|
-
this.code = code;
|
|
729
|
-
this.tokTypes = getAcorn().tokTypes;
|
|
730
|
-
}
|
|
731
|
-
convertToken(token) {
|
|
732
|
-
const { tokTypes } = this;
|
|
733
|
-
let type, value;
|
|
734
|
-
const additional = {};
|
|
735
|
-
if (token.type === tokTypes.string) {
|
|
736
|
-
type = "String";
|
|
737
|
-
value = this.code.slice(...token.range);
|
|
738
|
-
} else if (token.type === tokTypes.num) {
|
|
739
|
-
type = "Numeric";
|
|
740
|
-
value = this.code.slice(...token.range);
|
|
741
|
-
} else if (token.type.keyword) {
|
|
742
|
-
if (token.type.keyword === "true" || token.type.keyword === "false") type = "Boolean";
|
|
743
|
-
else if (token.type.keyword === "null") type = "Null";
|
|
744
|
-
else type = "Keyword";
|
|
745
|
-
value = token.value;
|
|
746
|
-
} else if (token.type === tokTypes.braceL || token.type === tokTypes.braceR || token.type === tokTypes.bracketL || token.type === tokTypes.bracketR || token.type === tokTypes.colon || token.type === tokTypes.comma || token.type === tokTypes.plusMin) {
|
|
747
|
-
type = "Punctuator";
|
|
748
|
-
value = this.code.slice(...token.range);
|
|
749
|
-
} else if (token.type === tokTypes.name) {
|
|
750
|
-
type = "Identifier";
|
|
751
|
-
value = token.value;
|
|
752
|
-
} else if (token.type === tokTypes.backQuote) {
|
|
753
|
-
if (this.templateBuffer.length > 0) {
|
|
754
|
-
const first = this.templateBuffer[0];
|
|
755
|
-
this.templateBuffer.length = 0;
|
|
756
|
-
return {
|
|
757
|
-
type: "Template",
|
|
758
|
-
value: this.code.slice(first.start, token.end),
|
|
759
|
-
range: [first.start, token.end],
|
|
760
|
-
loc: {
|
|
761
|
-
start: first.loc.start,
|
|
762
|
-
end: token.loc.end
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
this.templateBuffer.push(token);
|
|
767
|
-
return null;
|
|
768
|
-
} else if (token.type === tokTypes.template) {
|
|
769
|
-
if (this.templateBuffer.length === 0) return throwUnexpectedTokenError(this.code.slice(...token.range), token);
|
|
770
|
-
this.templateBuffer.push(token);
|
|
771
|
-
return null;
|
|
772
|
-
} else if (token.type === tokTypes.regexp) {
|
|
773
|
-
const reValue = token.value;
|
|
774
|
-
type = "RegularExpression";
|
|
775
|
-
additional.regex = {
|
|
776
|
-
flags: reValue.flags,
|
|
777
|
-
pattern: reValue.pattern
|
|
778
|
-
};
|
|
779
|
-
value = `/${reValue.pattern}/${reValue.flags}`;
|
|
780
|
-
} else if (this.ctx.parentheses && (token.type === tokTypes.parenL || token.type === tokTypes.parenR)) {
|
|
781
|
-
type = "Punctuator";
|
|
782
|
-
value = this.code.slice(...token.range);
|
|
783
|
-
} else if (this.ctx.staticExpressions && (token.type === tokTypes.star || token.type === tokTypes.slash || token.type === tokTypes.modulo || token.type === tokTypes.starstar)) {
|
|
784
|
-
type = "Punctuator";
|
|
785
|
-
value = this.code.slice(...token.range);
|
|
786
|
-
} else return throwUnexpectedTokenError(this.code.slice(...token.range), token);
|
|
787
|
-
token.type = type;
|
|
788
|
-
token.value = value;
|
|
789
|
-
for (const k in additional) token[k] = additional[k];
|
|
790
|
-
return token;
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
/**
|
|
794
|
-
* Convert root expression node to JSONProgram node
|
|
795
|
-
*/
|
|
796
|
-
function convertProgramNode(node, tokens, ctx, code) {
|
|
797
|
-
/* istanbul ignore next */
|
|
798
|
-
if (node.type !== "JSONObjectExpression" && node.type !== "JSONArrayExpression" && node.type !== "JSONLiteral" && node.type !== "JSONUnaryExpression" && node.type !== "JSONIdentifier" && node.type !== "JSONTemplateLiteral" && node.type !== "JSONBinaryExpression") return throwUnexpectedNodeError(node, tokens);
|
|
799
|
-
if (node.type === "JSONIdentifier") {
|
|
800
|
-
if (!isStaticValueIdentifier(node, ctx)) return throwUnexpectedNodeError(node, tokens);
|
|
801
|
-
}
|
|
802
|
-
const body = {
|
|
803
|
-
type: "JSONExpressionStatement",
|
|
804
|
-
expression: node,
|
|
805
|
-
...cloneLocation(node),
|
|
806
|
-
parent: null
|
|
807
|
-
};
|
|
808
|
-
setParent(node, body);
|
|
809
|
-
const end = code.length;
|
|
810
|
-
const endLoc = getAcorn().getLineInfo(code, end);
|
|
811
|
-
const nn = {
|
|
812
|
-
type: "Program",
|
|
813
|
-
body: [body],
|
|
814
|
-
comments: [],
|
|
815
|
-
tokens: [],
|
|
816
|
-
range: [0, end],
|
|
817
|
-
loc: {
|
|
818
|
-
start: {
|
|
819
|
-
line: 1,
|
|
820
|
-
column: 0
|
|
821
|
-
},
|
|
822
|
-
end: {
|
|
823
|
-
line: endLoc.line,
|
|
824
|
-
column: endLoc.column
|
|
825
|
-
}
|
|
826
|
-
},
|
|
827
|
-
parent: null
|
|
828
|
-
};
|
|
829
|
-
setParent(body, nn);
|
|
830
|
-
return nn;
|
|
831
|
-
}
|
|
832
|
-
/** Clone locations */
|
|
833
|
-
function cloneLocation(node) {
|
|
834
|
-
const range = node.range;
|
|
835
|
-
const loc = node.loc;
|
|
836
|
-
return {
|
|
837
|
-
range: [range[0], range[1]],
|
|
838
|
-
loc: {
|
|
839
|
-
start: {
|
|
840
|
-
line: loc.start.line,
|
|
841
|
-
column: loc.start.column
|
|
842
|
-
},
|
|
843
|
-
end: {
|
|
844
|
-
line: loc.end.line,
|
|
845
|
-
column: loc.end.column
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
};
|
|
849
|
-
}
|
|
850
|
-
/** Set parent node */
|
|
851
|
-
function setParent(prop, parent) {
|
|
852
|
-
prop.parent = parent;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
//#endregion
|
|
856
|
-
//#region src/parser/extend-parser.ts
|
|
857
|
-
let parserCache;
|
|
858
|
-
const PRIVATE = Symbol("ExtendParser#private");
|
|
859
|
-
const PRIVATE_PROCESS_NODE = Symbol("ExtendParser#processNode");
|
|
860
|
-
/** Get extend parser */
|
|
861
|
-
function getParser() {
|
|
862
|
-
if (parserCache) return parserCache;
|
|
863
|
-
parserCache = class ExtendParser extends getAcorn().Parser {
|
|
864
|
-
constructor(options, code, pos) {
|
|
865
|
-
super((() => {
|
|
866
|
-
const tokenConvertor = new TokenConvertor(options.ctx, code);
|
|
867
|
-
const onToken = options.onToken || ((token) => {
|
|
868
|
-
const t = tokenConvertor.convertToken(token);
|
|
869
|
-
if (t) this[PRIVATE].tokenStore.add(t);
|
|
870
|
-
});
|
|
871
|
-
return {
|
|
872
|
-
ecmaVersion: options.ecmaVersion,
|
|
873
|
-
sourceType: options.sourceType,
|
|
874
|
-
ranges: true,
|
|
875
|
-
locations: true,
|
|
876
|
-
allowReserved: true,
|
|
877
|
-
onToken,
|
|
878
|
-
onComment: (block, text, start, end, startLoc, endLoc) => {
|
|
879
|
-
const comment = {
|
|
880
|
-
type: block ? "Block" : "Line",
|
|
881
|
-
value: text,
|
|
882
|
-
range: [start, end],
|
|
883
|
-
loc: {
|
|
884
|
-
start: startLoc,
|
|
885
|
-
end: endLoc
|
|
886
|
-
}
|
|
887
|
-
};
|
|
888
|
-
if (!this[PRIVATE].ctx.comments) throw throwUnexpectedCommentError(comment);
|
|
889
|
-
this[PRIVATE].comments.push(comment);
|
|
890
|
-
}
|
|
891
|
-
};
|
|
892
|
-
})(), code, pos);
|
|
893
|
-
this[PRIVATE] = {
|
|
894
|
-
code,
|
|
895
|
-
ctx: options.ctx,
|
|
896
|
-
tokenStore: options.tokenStore,
|
|
897
|
-
comments: options.comments,
|
|
898
|
-
nodes: options.nodes
|
|
899
|
-
};
|
|
900
|
-
}
|
|
901
|
-
finishNode(...args) {
|
|
902
|
-
const result = super.finishNode(...args);
|
|
903
|
-
return this[PRIVATE_PROCESS_NODE](result);
|
|
904
|
-
}
|
|
905
|
-
finishNodeAt(...args) {
|
|
906
|
-
const result = super.finishNodeAt(...args);
|
|
907
|
-
return this[PRIVATE_PROCESS_NODE](result);
|
|
908
|
-
}
|
|
909
|
-
[PRIVATE_PROCESS_NODE](node) {
|
|
910
|
-
const { tokenStore, ctx, nodes } = this[PRIVATE];
|
|
911
|
-
validateNode(node, tokenStore, ctx);
|
|
912
|
-
nodes.push(node);
|
|
913
|
-
return node;
|
|
914
|
-
}
|
|
915
|
-
raise(pos, message) {
|
|
916
|
-
const loc = getAcorn().getLineInfo(this[PRIVATE].code, pos);
|
|
917
|
-
throw new ParseError(message, pos, loc.line, loc.column + 1);
|
|
918
|
-
}
|
|
919
|
-
raiseRecoverable(pos, message) {
|
|
920
|
-
this.raise(pos, message);
|
|
921
|
-
}
|
|
922
|
-
unexpected(pos) {
|
|
923
|
-
if (pos != null) {
|
|
924
|
-
this.raise(pos, "Unexpected token.");
|
|
925
|
-
return;
|
|
926
|
-
}
|
|
927
|
-
const start = this.start;
|
|
928
|
-
const end = this.end;
|
|
929
|
-
const token = this[PRIVATE].code.slice(start, end);
|
|
930
|
-
if (token) {
|
|
931
|
-
const message = `Unexpected token '${token}'.`;
|
|
932
|
-
this.raise(start, message);
|
|
933
|
-
} else {
|
|
934
|
-
if (!this[PRIVATE].nodes.length) this.raise(0, "Expected to be an expression, but got empty.");
|
|
935
|
-
if (this[PRIVATE].tokenStore.tokens.length) {
|
|
936
|
-
const last = this[PRIVATE].tokenStore.tokens[this[PRIVATE].tokenStore.tokens.length - 1];
|
|
937
|
-
this.raise(last.range[0], `Unexpected token '${last.value}'.`);
|
|
938
|
-
}
|
|
939
|
-
this.raise(start, "Unexpected token.");
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
};
|
|
943
|
-
return parserCache;
|
|
944
|
-
}
|
|
945
|
-
/** Get extend parser */
|
|
946
|
-
function getAnyTokenErrorParser() {
|
|
947
|
-
return class ExtendParser extends getParser() {
|
|
948
|
-
constructor(options, code, pos) {
|
|
949
|
-
super({
|
|
950
|
-
...options,
|
|
951
|
-
onToken: (token) => {
|
|
952
|
-
return throwUnexpectedTokenError(code.slice(...token.range), token);
|
|
953
|
-
}
|
|
954
|
-
}, code, pos);
|
|
955
|
-
}
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
//#endregion
|
|
960
|
-
//#region src/parser/parser.ts
|
|
961
|
-
/**
|
|
962
|
-
* Parse JSON source code
|
|
963
|
-
*/
|
|
964
|
-
function parseJSON(code, options) {
|
|
965
|
-
const parserOptions = Object.assign({
|
|
966
|
-
filePath: "<input>",
|
|
967
|
-
ecmaVersion: "latest"
|
|
968
|
-
}, options || {}, {
|
|
969
|
-
loc: true,
|
|
970
|
-
range: true,
|
|
971
|
-
raw: true,
|
|
972
|
-
tokens: true,
|
|
973
|
-
comment: true,
|
|
974
|
-
eslintVisitorKeys: true,
|
|
975
|
-
eslintScopeManager: true
|
|
976
|
-
});
|
|
977
|
-
const ctx = getJSONSyntaxContext(parserOptions.jsonSyntax);
|
|
978
|
-
const tokens = [];
|
|
979
|
-
const comments = [];
|
|
980
|
-
const tokenStore = new TokenStore(tokens);
|
|
981
|
-
const nodes = [];
|
|
982
|
-
parserOptions.ctx = ctx;
|
|
983
|
-
parserOptions.tokenStore = tokenStore;
|
|
984
|
-
parserOptions.comments = comments;
|
|
985
|
-
parserOptions.nodes = nodes;
|
|
986
|
-
const baseAst = getParser().parseExpressionAt(code, 0, parserOptions);
|
|
987
|
-
for (const node of nodes) node.type = `JSON${node.type}`;
|
|
988
|
-
const ast = convertProgramNode(baseAst, tokenStore, ctx, code);
|
|
989
|
-
let lastIndex = Math.max(baseAst.range[1], tokens[tokens.length - 1]?.range[1] ?? 0, comments[comments.length - 1]?.range[1] ?? 0);
|
|
990
|
-
let lastChar = code[lastIndex];
|
|
991
|
-
while (lastChar === "\n" || lastChar === "\r" || lastChar === " " || lastChar === " ") {
|
|
992
|
-
lastIndex++;
|
|
993
|
-
lastChar = code[lastIndex];
|
|
994
|
-
}
|
|
995
|
-
if (lastIndex < code.length) getAnyTokenErrorParser().parseExpressionAt(code, lastIndex, parserOptions);
|
|
996
|
-
ast.tokens = tokens;
|
|
997
|
-
ast.comments = comments;
|
|
998
|
-
return ast;
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* Parse source code
|
|
1002
|
-
*/
|
|
1003
|
-
function parseForESLint(code, options) {
|
|
1004
|
-
return {
|
|
1005
|
-
ast: parseJSON(code, options),
|
|
1006
|
-
visitorKeys: getVisitorKeys(),
|
|
1007
|
-
services: { isJSON: true }
|
|
1008
|
-
};
|
|
1009
|
-
}
|
|
1010
|
-
/**
|
|
1011
|
-
* Normalize json syntax option
|
|
1012
|
-
*/
|
|
1013
|
-
function getJSONSyntaxContext(str) {
|
|
1014
|
-
const upperCase = str?.toUpperCase();
|
|
1015
|
-
if (upperCase === "JSON") return {
|
|
1016
|
-
trailingCommas: false,
|
|
1017
|
-
comments: false,
|
|
1018
|
-
plusSigns: false,
|
|
1019
|
-
spacedSigns: false,
|
|
1020
|
-
leadingOrTrailingDecimalPoints: false,
|
|
1021
|
-
infinities: false,
|
|
1022
|
-
nans: false,
|
|
1023
|
-
numericSeparators: false,
|
|
1024
|
-
binaryNumericLiterals: false,
|
|
1025
|
-
octalNumericLiterals: false,
|
|
1026
|
-
legacyOctalNumericLiterals: false,
|
|
1027
|
-
invalidJsonNumbers: false,
|
|
1028
|
-
multilineStrings: false,
|
|
1029
|
-
unquoteProperties: false,
|
|
1030
|
-
singleQuotes: false,
|
|
1031
|
-
numberProperties: false,
|
|
1032
|
-
undefinedKeywords: false,
|
|
1033
|
-
sparseArrays: false,
|
|
1034
|
-
regExpLiterals: false,
|
|
1035
|
-
templateLiterals: false,
|
|
1036
|
-
bigintLiterals: false,
|
|
1037
|
-
unicodeCodepointEscapes: false,
|
|
1038
|
-
escapeSequenceInIdentifier: false,
|
|
1039
|
-
parentheses: false,
|
|
1040
|
-
staticExpressions: false
|
|
1041
|
-
};
|
|
1042
|
-
if (upperCase === "JSONC") return {
|
|
1043
|
-
trailingCommas: true,
|
|
1044
|
-
comments: true,
|
|
1045
|
-
plusSigns: false,
|
|
1046
|
-
spacedSigns: false,
|
|
1047
|
-
leadingOrTrailingDecimalPoints: false,
|
|
1048
|
-
infinities: false,
|
|
1049
|
-
nans: false,
|
|
1050
|
-
numericSeparators: false,
|
|
1051
|
-
binaryNumericLiterals: false,
|
|
1052
|
-
octalNumericLiterals: false,
|
|
1053
|
-
legacyOctalNumericLiterals: false,
|
|
1054
|
-
invalidJsonNumbers: false,
|
|
1055
|
-
multilineStrings: false,
|
|
1056
|
-
unquoteProperties: false,
|
|
1057
|
-
singleQuotes: false,
|
|
1058
|
-
numberProperties: false,
|
|
1059
|
-
undefinedKeywords: false,
|
|
1060
|
-
sparseArrays: false,
|
|
1061
|
-
regExpLiterals: false,
|
|
1062
|
-
templateLiterals: false,
|
|
1063
|
-
bigintLiterals: false,
|
|
1064
|
-
unicodeCodepointEscapes: false,
|
|
1065
|
-
escapeSequenceInIdentifier: false,
|
|
1066
|
-
parentheses: false,
|
|
1067
|
-
staticExpressions: false
|
|
1068
|
-
};
|
|
1069
|
-
if (upperCase === "JSON5") return {
|
|
1070
|
-
trailingCommas: true,
|
|
1071
|
-
comments: true,
|
|
1072
|
-
plusSigns: true,
|
|
1073
|
-
spacedSigns: true,
|
|
1074
|
-
leadingOrTrailingDecimalPoints: true,
|
|
1075
|
-
infinities: true,
|
|
1076
|
-
nans: true,
|
|
1077
|
-
numericSeparators: false,
|
|
1078
|
-
binaryNumericLiterals: false,
|
|
1079
|
-
octalNumericLiterals: false,
|
|
1080
|
-
legacyOctalNumericLiterals: false,
|
|
1081
|
-
invalidJsonNumbers: true,
|
|
1082
|
-
multilineStrings: true,
|
|
1083
|
-
unquoteProperties: true,
|
|
1084
|
-
singleQuotes: true,
|
|
1085
|
-
numberProperties: false,
|
|
1086
|
-
undefinedKeywords: false,
|
|
1087
|
-
sparseArrays: false,
|
|
1088
|
-
regExpLiterals: false,
|
|
1089
|
-
templateLiterals: false,
|
|
1090
|
-
bigintLiterals: false,
|
|
1091
|
-
unicodeCodepointEscapes: false,
|
|
1092
|
-
escapeSequenceInIdentifier: false,
|
|
1093
|
-
parentheses: false,
|
|
1094
|
-
staticExpressions: false
|
|
1095
|
-
};
|
|
1096
|
-
return {
|
|
1097
|
-
trailingCommas: true,
|
|
1098
|
-
comments: true,
|
|
1099
|
-
plusSigns: true,
|
|
1100
|
-
spacedSigns: true,
|
|
1101
|
-
leadingOrTrailingDecimalPoints: true,
|
|
1102
|
-
infinities: true,
|
|
1103
|
-
nans: true,
|
|
1104
|
-
numericSeparators: true,
|
|
1105
|
-
binaryNumericLiterals: true,
|
|
1106
|
-
octalNumericLiterals: true,
|
|
1107
|
-
legacyOctalNumericLiterals: true,
|
|
1108
|
-
invalidJsonNumbers: true,
|
|
1109
|
-
multilineStrings: true,
|
|
1110
|
-
unquoteProperties: true,
|
|
1111
|
-
singleQuotes: true,
|
|
1112
|
-
numberProperties: true,
|
|
1113
|
-
undefinedKeywords: true,
|
|
1114
|
-
sparseArrays: true,
|
|
1115
|
-
regExpLiterals: true,
|
|
1116
|
-
templateLiterals: true,
|
|
1117
|
-
bigintLiterals: true,
|
|
1118
|
-
unicodeCodepointEscapes: true,
|
|
1119
|
-
escapeSequenceInIdentifier: true,
|
|
1120
|
-
parentheses: true,
|
|
1121
|
-
staticExpressions: true
|
|
1122
|
-
};
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
//#endregion
|
|
1126
|
-
//#region src/parser/traverse.ts
|
|
1127
|
-
/**
|
|
1128
|
-
* Check that the given key should be traversed or not.
|
|
1129
|
-
* @this {Traversable}
|
|
1130
|
-
* @param key The key to check.
|
|
1131
|
-
* @returns `true` if the key should be traversed.
|
|
1132
|
-
*/
|
|
1133
|
-
function fallbackKeysFilter(key) {
|
|
1134
|
-
let value = null;
|
|
1135
|
-
return key !== "comments" && key !== "leadingComments" && key !== "loc" && key !== "parent" && key !== "range" && key !== "tokens" && key !== "trailingComments" && (value = this[key]) !== null && typeof value === "object" && (typeof value.type === "string" || Array.isArray(value));
|
|
1136
|
-
}
|
|
1137
|
-
/**
|
|
1138
|
-
* Get the keys of the given node to traverse it.
|
|
1139
|
-
* @param node The node to get.
|
|
1140
|
-
* @returns The keys to traverse.
|
|
1141
|
-
*/
|
|
1142
|
-
function getFallbackKeys(node) {
|
|
1143
|
-
return Object.keys(node).filter(fallbackKeysFilter, node);
|
|
1144
|
-
}
|
|
1145
|
-
/**
|
|
1146
|
-
* Get the keys of the given node to traverse it.
|
|
1147
|
-
* @param node The node to get.
|
|
1148
|
-
* @returns The keys to traverse.
|
|
1149
|
-
*/
|
|
1150
|
-
function getKeys(node, visitorKeys) {
|
|
1151
|
-
return ((visitorKeys || getVisitorKeys())[node.type] || getFallbackKeys(node)).filter((key) => !getNodes(node, key).next().done);
|
|
1152
|
-
}
|
|
1153
|
-
/**
|
|
1154
|
-
* Get the nodes of the given node.
|
|
1155
|
-
* @param node The node to get.
|
|
1156
|
-
*/
|
|
1157
|
-
function* getNodes(node, key) {
|
|
1158
|
-
const child = node[key];
|
|
1159
|
-
if (Array.isArray(child)) {
|
|
1160
|
-
for (const c of child) if (isNode(c)) yield c;
|
|
1161
|
-
} else if (isNode(child)) yield child;
|
|
1162
|
-
}
|
|
1163
|
-
/**
|
|
1164
|
-
* Check whether a given value is a node.
|
|
1165
|
-
* @param x The value to check.
|
|
1166
|
-
* @returns `true` if the value is a node.
|
|
1167
|
-
*/
|
|
1168
|
-
function isNode(x) {
|
|
1169
|
-
return x !== null && typeof x === "object" && typeof x.type === "string";
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* Traverse the given node.
|
|
1173
|
-
* @param node The node to traverse.
|
|
1174
|
-
* @param parent The parent node.
|
|
1175
|
-
* @param visitor The node visitor.
|
|
1176
|
-
*/
|
|
1177
|
-
function traverse(node, parent, visitor) {
|
|
1178
|
-
visitor.enterNode(node, parent);
|
|
1179
|
-
const keys = getKeys(node, visitor.visitorKeys);
|
|
1180
|
-
for (const key of keys) for (const child of getNodes(node, key)) traverse(child, node, visitor);
|
|
1181
|
-
visitor.leaveNode(node, parent);
|
|
1182
|
-
}
|
|
1183
|
-
/**
|
|
1184
|
-
* Traverse the given AST tree.
|
|
1185
|
-
* @param node Root node to traverse.
|
|
1186
|
-
* @param visitor Visitor.
|
|
1187
|
-
*/
|
|
1188
|
-
function traverseNodes(node, visitor) {
|
|
1189
|
-
traverse(node, null, visitor);
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
//#endregion
|
|
1193
|
-
//#region src/utils/ast.ts
|
|
1194
|
-
/**
|
|
1195
|
-
* Checks if given node is JSONExpression
|
|
1196
|
-
*/
|
|
1197
|
-
function isExpression(node) {
|
|
1198
|
-
if (node.type === "JSONIdentifier" || node.type === "JSONLiteral") {
|
|
1199
|
-
const parent = node.parent;
|
|
1200
|
-
if (parent.type === "JSONProperty" && parent.key === node) return false;
|
|
1201
|
-
return true;
|
|
1202
|
-
}
|
|
1203
|
-
if (node.type === "JSONObjectExpression" || node.type === "JSONArrayExpression" || node.type === "JSONUnaryExpression" || node.type === "JSONTemplateLiteral" || node.type === "JSONBinaryExpression") return true;
|
|
1204
|
-
return false;
|
|
1205
|
-
}
|
|
1206
|
-
/**
|
|
1207
|
-
* Checks if given node is JSONNumberIdentifier
|
|
1208
|
-
*/
|
|
1209
|
-
function isNumberIdentifier(node) {
|
|
1210
|
-
return isExpression(node) && (node.name === "Infinity" || node.name === "NaN");
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* Checks if given node is JSONUndefinedIdentifier
|
|
1214
|
-
*/
|
|
1215
|
-
function isUndefinedIdentifier(node) {
|
|
1216
|
-
return isExpression(node) && node.name === "undefined";
|
|
1217
|
-
}
|
|
1218
|
-
const resolver = {
|
|
1219
|
-
Program(node) {
|
|
1220
|
-
if (node.body.length !== 1 || node.body[0].type !== "JSONExpressionStatement") throw new Error("Illegal argument");
|
|
1221
|
-
return getStaticJSONValue(node.body[0]);
|
|
1222
|
-
},
|
|
1223
|
-
JSONExpressionStatement(node) {
|
|
1224
|
-
return getStaticJSONValue(node.expression);
|
|
1225
|
-
},
|
|
1226
|
-
JSONObjectExpression(node) {
|
|
1227
|
-
const object = {};
|
|
1228
|
-
for (const prop of node.properties) Object.assign(object, getStaticJSONValue(prop));
|
|
1229
|
-
return object;
|
|
1230
|
-
},
|
|
1231
|
-
JSONProperty(node) {
|
|
1232
|
-
return { [node.key.type === "JSONLiteral" ? `${node.key.value}` : node.key.name]: getStaticJSONValue(node.value) };
|
|
1233
|
-
},
|
|
1234
|
-
JSONArrayExpression(node) {
|
|
1235
|
-
const array = [];
|
|
1236
|
-
for (let index = 0; index < node.elements.length; index++) {
|
|
1237
|
-
const element = node.elements[index];
|
|
1238
|
-
if (element) array[index] = getStaticJSONValue(element);
|
|
1239
|
-
}
|
|
1240
|
-
return array;
|
|
1241
|
-
},
|
|
1242
|
-
JSONLiteral(node) {
|
|
1243
|
-
if (node.regex) try {
|
|
1244
|
-
return new RegExp(node.regex.pattern, node.regex.flags);
|
|
1245
|
-
} catch {
|
|
1246
|
-
return `/${node.regex.pattern}/${node.regex.flags}`;
|
|
1247
|
-
}
|
|
1248
|
-
if (node.bigint != null) try {
|
|
1249
|
-
return BigInt(node.bigint);
|
|
1250
|
-
} catch {
|
|
1251
|
-
return `${node.bigint}`;
|
|
1252
|
-
}
|
|
1253
|
-
return node.value;
|
|
1254
|
-
},
|
|
1255
|
-
JSONUnaryExpression(node) {
|
|
1256
|
-
const value = getStaticJSONValue(node.argument);
|
|
1257
|
-
return node.operator === "-" ? -value : value;
|
|
1258
|
-
},
|
|
1259
|
-
JSONBinaryExpression(node) {
|
|
1260
|
-
const left = getStaticJSONValue(node.left);
|
|
1261
|
-
const right = getStaticJSONValue(node.right);
|
|
1262
|
-
return node.operator === "+" ? left + right : node.operator === "-" ? left - right : node.operator === "*" ? left * right : node.operator === "/" ? left / right : node.operator === "%" ? left % right : node.operator === "**" ? left ** right : (() => {
|
|
1263
|
-
throw new Error(`Unknown operator: ${node.operator}`);
|
|
1264
|
-
})();
|
|
1265
|
-
},
|
|
1266
|
-
JSONIdentifier(node) {
|
|
1267
|
-
if (node.name === "Infinity") return Infinity;
|
|
1268
|
-
if (node.name === "NaN") return NaN;
|
|
1269
|
-
if (node.name === "undefined") return;
|
|
1270
|
-
throw new Error("Illegal argument");
|
|
1271
|
-
},
|
|
1272
|
-
JSONTemplateLiteral(node) {
|
|
1273
|
-
return getStaticJSONValue(node.quasis[0]);
|
|
1274
|
-
},
|
|
1275
|
-
JSONTemplateElement(node) {
|
|
1276
|
-
return node.value.cooked;
|
|
1277
|
-
}
|
|
1278
|
-
};
|
|
1279
|
-
/**
|
|
1280
|
-
* Gets the static value for the given node.
|
|
1281
|
-
*/
|
|
1282
|
-
function getStaticJSONValue(node) {
|
|
1283
|
-
return resolver[node.type](node);
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
//#endregion
|
|
1287
|
-
//#region package.json
|
|
1288
|
-
var name$1 = "jsonc-eslint-parser";
|
|
1289
|
-
var version$1 = "3.0.0";
|
|
1290
|
-
|
|
1291
|
-
//#endregion
|
|
1292
|
-
//#region src/meta.ts
|
|
1293
|
-
var meta_exports = /* @__PURE__ */ __exportAll({
|
|
1294
|
-
name: () => name,
|
|
1295
|
-
version: () => version
|
|
1296
|
-
});
|
|
1297
|
-
const name = name$1;
|
|
1298
|
-
const version = version$1;
|
|
1299
|
-
|
|
1300
|
-
//#endregion
|
|
1301
|
-
//#region src/index.ts
|
|
1302
|
-
const VisitorKeys = getVisitorKeys();
|
|
1303
|
-
|
|
1304
|
-
//#endregion
|
|
1305
|
-
export { VisitorKeys, getStaticJSONValue, isExpression, isNumberIdentifier, isUndefinedIdentifier, meta_exports as meta, name, parseForESLint, parseJSON, traverseNodes };
|