1 | var babylonToEspree = require("./babylon-to-espree");
|
2 | var Module = require("module");
|
3 | var path = require("path");
|
4 | var parse = require("babylon").parse;
|
5 | var t = require("babel-types");
|
6 | var tt = require("babylon").tokTypes;
|
7 | var traverse = require("babel-traverse").default;
|
8 | var codeFrameColumns = require("babel-code-frame").codeFrameColumns;
|
9 |
|
10 | var hasPatched = false;
|
11 | var eslintOptions = {};
|
12 |
|
13 | function getModules() {
|
14 | try {
|
15 |
|
16 | var eslintLoc = Module._resolveFilename("eslint", module.parent);
|
17 | } catch (err) {
|
18 | try {
|
19 |
|
20 | eslintLoc = require.resolve("eslint");
|
21 | } catch (err) {
|
22 | throw new ReferenceError("couldn't resolve eslint");
|
23 | }
|
24 | }
|
25 |
|
26 |
|
27 | var eslintMod = new Module(eslintLoc);
|
28 | eslintMod.filename = eslintLoc;
|
29 | eslintMod.paths = Module._nodeModulePaths(path.dirname(eslintLoc));
|
30 |
|
31 | try {
|
32 | var escope = eslintMod.require("eslint-scope");
|
33 | var Definition = eslintMod.require("eslint-scope/lib/definition")
|
34 | .Definition;
|
35 | var referencer = eslintMod.require("eslint-scope/lib/referencer");
|
36 | } catch (err) {
|
37 | escope = eslintMod.require("escope");
|
38 | Definition = eslintMod.require("escope/lib/definition").Definition;
|
39 | referencer = eslintMod.require("escope/lib/referencer");
|
40 | }
|
41 |
|
42 | var estraverse = eslintMod.require("estraverse");
|
43 |
|
44 | if (referencer.__esModule) referencer = referencer.default;
|
45 |
|
46 | return {
|
47 | Definition,
|
48 | escope,
|
49 | estraverse,
|
50 | referencer,
|
51 | };
|
52 | }
|
53 |
|
54 | function monkeypatch(modules) {
|
55 | var Definition = modules.Definition;
|
56 | var escope = modules.escope;
|
57 | var estraverse = modules.estraverse;
|
58 | var referencer = modules.referencer;
|
59 |
|
60 | Object.assign(estraverse.VisitorKeys, t.VISITOR_KEYS);
|
61 | estraverse.VisitorKeys.MethodDefinition.push("decorators");
|
62 | estraverse.VisitorKeys.Property.push("decorators");
|
63 |
|
64 | var analyze = escope.analyze;
|
65 | escope.analyze = function(ast, opts) {
|
66 | opts = opts || {};
|
67 | opts.ecmaVersion = eslintOptions.ecmaVersion;
|
68 | opts.sourceType = eslintOptions.sourceType;
|
69 | if (eslintOptions.globalReturn !== undefined) {
|
70 | opts.nodejsScope = eslintOptions.globalReturn;
|
71 | }
|
72 |
|
73 | var results = analyze.call(this, ast, opts);
|
74 | return results;
|
75 | };
|
76 |
|
77 |
|
78 | function visitDecorators(node) {
|
79 | if (!node.decorators) {
|
80 | return;
|
81 | }
|
82 | for (var i = 0; i < node.decorators.length; i++) {
|
83 | if (node.decorators[i].expression) {
|
84 | this.visit(node.decorators[i]);
|
85 | }
|
86 | }
|
87 | }
|
88 |
|
89 |
|
90 | var flowFlippedAliasKeys = t.FLIPPED_ALIAS_KEYS.Flow.concat([
|
91 | "ArrayPattern",
|
92 | "ClassDeclaration",
|
93 | "ClassExpression",
|
94 | "FunctionDeclaration",
|
95 | "FunctionExpression",
|
96 | "Identifier",
|
97 | "ObjectPattern",
|
98 | "RestElement",
|
99 | ]);
|
100 | var visitorKeysMap = Object.keys(t.VISITOR_KEYS).reduce(function(acc, key) {
|
101 | var value = t.VISITOR_KEYS[key];
|
102 | if (flowFlippedAliasKeys.indexOf(value) === -1) {
|
103 | acc[key] = value;
|
104 | }
|
105 | return acc;
|
106 | }, {});
|
107 |
|
108 | var propertyTypes = {
|
109 |
|
110 | callProperties: { type: "loop", values: ["value"] },
|
111 | indexers: { type: "loop", values: ["key", "value"] },
|
112 | properties: { type: "loop", values: ["argument", "value"] },
|
113 | types: { type: "loop" },
|
114 | params: { type: "loop" },
|
115 |
|
116 | argument: { type: "single" },
|
117 | elementType: { type: "single" },
|
118 | qualification: { type: "single" },
|
119 | rest: { type: "single" },
|
120 | returnType: { type: "single" },
|
121 |
|
122 | typeAnnotation: { type: "typeAnnotation" },
|
123 | typeParameters: { type: "typeParameters" },
|
124 | id: { type: "id" },
|
125 | };
|
126 |
|
127 | function visitTypeAnnotation(node) {
|
128 |
|
129 | var visitorValues = visitorKeysMap[node.type];
|
130 | if (!visitorValues) {
|
131 | return;
|
132 | }
|
133 |
|
134 |
|
135 | for (var i = 0; i < visitorValues.length; i++) {
|
136 | var visitorValue = visitorValues[i];
|
137 | var propertyType = propertyTypes[visitorValue];
|
138 | var nodeProperty = node[visitorValue];
|
139 |
|
140 | if (propertyType == null || nodeProperty == null) {
|
141 | continue;
|
142 | }
|
143 | if (propertyType.type === "loop") {
|
144 | for (var j = 0; j < nodeProperty.length; j++) {
|
145 | if (Array.isArray(propertyType.values)) {
|
146 | for (var k = 0; k < propertyType.values.length; k++) {
|
147 | var loopPropertyNode = nodeProperty[j][propertyType.values[k]];
|
148 | if (loopPropertyNode) {
|
149 | checkIdentifierOrVisit.call(this, loopPropertyNode);
|
150 | }
|
151 | }
|
152 | } else {
|
153 | checkIdentifierOrVisit.call(this, nodeProperty[j]);
|
154 | }
|
155 | }
|
156 | } else if (propertyType.type === "single") {
|
157 | checkIdentifierOrVisit.call(this, nodeProperty);
|
158 | } else if (propertyType.type === "typeAnnotation") {
|
159 | visitTypeAnnotation.call(this, node.typeAnnotation);
|
160 | } else if (propertyType.type === "typeParameters") {
|
161 | for (var l = 0; l < node.typeParameters.params.length; l++) {
|
162 | checkIdentifierOrVisit.call(this, node.typeParameters.params[l]);
|
163 | }
|
164 | } else if (propertyType.type === "id") {
|
165 | if (node.id.type === "Identifier") {
|
166 | checkIdentifierOrVisit.call(this, node.id);
|
167 | } else {
|
168 | visitTypeAnnotation.call(this, node.id);
|
169 | }
|
170 | }
|
171 | }
|
172 | }
|
173 |
|
174 | function checkIdentifierOrVisit(node) {
|
175 | if (node.typeAnnotation) {
|
176 | visitTypeAnnotation.call(this, node.typeAnnotation);
|
177 | } else if (node.type === "Identifier") {
|
178 | this.visit(node);
|
179 | } else {
|
180 | visitTypeAnnotation.call(this, node);
|
181 | }
|
182 | }
|
183 |
|
184 | function nestTypeParamScope(manager, node) {
|
185 | var parentScope = manager.__currentScope;
|
186 | var scope = new escope.Scope(
|
187 | manager,
|
188 | "type-parameters",
|
189 | parentScope,
|
190 | node,
|
191 | false
|
192 | );
|
193 | manager.__nestScope(scope);
|
194 | for (var j = 0; j < node.typeParameters.params.length; j++) {
|
195 | var name = node.typeParameters.params[j];
|
196 | scope.__define(name, new Definition("TypeParameter", name, name));
|
197 | if (name.typeAnnotation) {
|
198 | checkIdentifierOrVisit.call(this, name);
|
199 | }
|
200 | }
|
201 | scope.__define = function() {
|
202 | return parentScope.__define.apply(parentScope, arguments);
|
203 | };
|
204 | return scope;
|
205 | }
|
206 |
|
207 |
|
208 | var visitClass = referencer.prototype.visitClass;
|
209 | referencer.prototype.visitClass = function(node) {
|
210 | visitDecorators.call(this, node);
|
211 | var typeParamScope;
|
212 | if (node.typeParameters) {
|
213 | typeParamScope = nestTypeParamScope.call(this, this.scopeManager, node);
|
214 | }
|
215 |
|
216 | if (node.implements) {
|
217 | for (var i = 0; i < node.implements.length; i++) {
|
218 | checkIdentifierOrVisit.call(this, node.implements[i]);
|
219 | }
|
220 | }
|
221 | if (node.superTypeParameters) {
|
222 | for (var k = 0; k < node.superTypeParameters.params.length; k++) {
|
223 | checkIdentifierOrVisit.call(this, node.superTypeParameters.params[k]);
|
224 | }
|
225 | }
|
226 | visitClass.call(this, node);
|
227 | if (typeParamScope) {
|
228 | this.close(node);
|
229 | }
|
230 | };
|
231 |
|
232 |
|
233 | var visitProperty = referencer.prototype.visitProperty;
|
234 | referencer.prototype.visitProperty = function(node) {
|
235 | if (node.value && node.value.type === "TypeCastExpression") {
|
236 | visitTypeAnnotation.call(this, node.value);
|
237 | }
|
238 | visitDecorators.call(this, node);
|
239 | visitProperty.call(this, node);
|
240 | };
|
241 |
|
242 | function visitClassProperty(node) {
|
243 | if (node.typeAnnotation) {
|
244 | visitTypeAnnotation.call(this, node.typeAnnotation);
|
245 | }
|
246 | this.visitProperty(node);
|
247 | }
|
248 |
|
249 |
|
250 | referencer.prototype.ClassProperty = visitClassProperty;
|
251 |
|
252 |
|
253 | referencer.prototype.ClassPrivateProperty = visitClassProperty;
|
254 |
|
255 |
|
256 | var visitFunction = referencer.prototype.visitFunction;
|
257 | referencer.prototype.visitFunction = function(node) {
|
258 | var typeParamScope;
|
259 | if (node.typeParameters) {
|
260 | typeParamScope = nestTypeParamScope.call(this, this.scopeManager, node);
|
261 | }
|
262 | if (node.returnType) {
|
263 | checkIdentifierOrVisit.call(this, node.returnType);
|
264 | }
|
265 |
|
266 | if (node.params) {
|
267 | for (var i = 0; i < node.params.length; i++) {
|
268 | var param = node.params[i];
|
269 | if (param.typeAnnotation) {
|
270 | checkIdentifierOrVisit.call(this, param);
|
271 | } else if (t.isAssignmentPattern(param)) {
|
272 | if (param.left.typeAnnotation) {
|
273 | checkIdentifierOrVisit.call(this, param.left);
|
274 | }
|
275 | }
|
276 | }
|
277 | }
|
278 |
|
279 |
|
280 | estraverse.VisitorKeys.ObjectPattern = ["properties"];
|
281 | estraverse.VisitorKeys.ArrayPattern = ["elements"];
|
282 | visitFunction.call(this, node);
|
283 |
|
284 | estraverse.VisitorKeys.ObjectPattern = t.VISITOR_KEYS.ObjectPattern;
|
285 | estraverse.VisitorKeys.ArrayPattern = t.VISITOR_KEYS.ArrayPattern;
|
286 | if (typeParamScope) {
|
287 | this.close(node);
|
288 | }
|
289 | };
|
290 |
|
291 |
|
292 | var variableDeclaration = referencer.prototype.VariableDeclaration;
|
293 | referencer.prototype.VariableDeclaration = function(node) {
|
294 | if (node.declarations) {
|
295 | for (var i = 0; i < node.declarations.length; i++) {
|
296 | var id = node.declarations[i].id;
|
297 | var typeAnnotation = id.typeAnnotation;
|
298 | if (typeAnnotation) {
|
299 | checkIdentifierOrVisit.call(this, typeAnnotation);
|
300 | }
|
301 | }
|
302 | }
|
303 | variableDeclaration.call(this, node);
|
304 | };
|
305 |
|
306 | function createScopeVariable(node, name) {
|
307 | this.currentScope().variableScope.__define(
|
308 | name,
|
309 | new Definition("Variable", name, node, null, null, null)
|
310 | );
|
311 | }
|
312 |
|
313 | referencer.prototype.InterfaceDeclaration = function(node) {
|
314 | createScopeVariable.call(this, node, node.id);
|
315 | var typeParamScope;
|
316 | if (node.typeParameters) {
|
317 | typeParamScope = nestTypeParamScope.call(this, this.scopeManager, node);
|
318 | }
|
319 |
|
320 | for (var i = 0; i < node.extends.length; i++) {
|
321 | visitTypeAnnotation.call(this, node.extends[i]);
|
322 | }
|
323 | visitTypeAnnotation.call(this, node.body);
|
324 | if (typeParamScope) {
|
325 | this.close(node);
|
326 | }
|
327 | };
|
328 |
|
329 | referencer.prototype.TypeAlias = function(node) {
|
330 | createScopeVariable.call(this, node, node.id);
|
331 | var typeParamScope;
|
332 | if (node.typeParameters) {
|
333 | typeParamScope = nestTypeParamScope.call(this, this.scopeManager, node);
|
334 | }
|
335 | if (node.right) {
|
336 | visitTypeAnnotation.call(this, node.right);
|
337 | }
|
338 | if (typeParamScope) {
|
339 | this.close(node);
|
340 | }
|
341 | };
|
342 |
|
343 | referencer.prototype.DeclareModule = referencer.prototype.DeclareFunction = referencer.prototype.DeclareVariable = referencer.prototype.DeclareClass = function(
|
344 | node
|
345 | ) {
|
346 | if (node.id) {
|
347 | createScopeVariable.call(this, node, node.id);
|
348 | }
|
349 |
|
350 | var typeParamScope;
|
351 | if (node.typeParameters) {
|
352 | typeParamScope = nestTypeParamScope.call(this, this.scopeManager, node);
|
353 | }
|
354 | if (typeParamScope) {
|
355 | this.close(node);
|
356 | }
|
357 | };
|
358 | }
|
359 |
|
360 | exports.parse = function(code, options) {
|
361 | options = options || {};
|
362 | eslintOptions.ecmaVersion = options.ecmaVersion = options.ecmaVersion || 6;
|
363 | eslintOptions.sourceType = options.sourceType =
|
364 | options.sourceType || "module";
|
365 | eslintOptions.allowImportExportEverywhere = options.allowImportExportEverywhere =
|
366 | options.allowImportExportEverywhere || false;
|
367 | if (options.sourceType === "module") {
|
368 | eslintOptions.globalReturn = false;
|
369 | } else {
|
370 | delete eslintOptions.globalReturn;
|
371 | }
|
372 |
|
373 | if (!hasPatched) {
|
374 | hasPatched = true;
|
375 | try {
|
376 | monkeypatch(getModules());
|
377 | } catch (err) {
|
378 | console.error(err.stack);
|
379 | process.exit(1);
|
380 | }
|
381 | }
|
382 |
|
383 | return exports.parseNoPatch(code, options);
|
384 | };
|
385 |
|
386 | exports.parseNoPatch = function(code, options) {
|
387 | var opts = {
|
388 | codeFrame: options.hasOwnProperty("codeFrame") ? options.codeFrame : true,
|
389 | sourceType: options.sourceType,
|
390 | allowImportExportEverywhere: options.allowImportExportEverywhere,
|
391 | allowReturnOutsideFunction: true,
|
392 | allowSuperOutsideMethod: true,
|
393 | ranges: true,
|
394 | tokens: true,
|
395 | plugins: [
|
396 | "flow",
|
397 | "jsx",
|
398 | "estree",
|
399 | "asyncFunctions",
|
400 | "asyncGenerators",
|
401 | "classConstructorCall",
|
402 | "classProperties",
|
403 | "decorators",
|
404 | "doExpressions",
|
405 | "exponentiationOperator",
|
406 | "exportExtensions",
|
407 | "functionBind",
|
408 | "functionSent",
|
409 | "objectRestSpread",
|
410 | "trailingFunctionCommas",
|
411 | "dynamicImport",
|
412 | "numericSeparator",
|
413 | "optionalChaining",
|
414 | "importMeta",
|
415 | "classPrivateProperties",
|
416 | "bigInt",
|
417 | "optionalCatchBinding",
|
418 | ],
|
419 | };
|
420 |
|
421 | var ast;
|
422 | try {
|
423 | ast = parse(code, opts);
|
424 | } catch (err) {
|
425 | if (err instanceof SyntaxError) {
|
426 | err.lineNumber = err.loc.line;
|
427 | err.column = err.loc.column;
|
428 |
|
429 | if (opts.codeFrame) {
|
430 | err.lineNumber = err.loc.line;
|
431 | err.column = err.loc.column + 1;
|
432 |
|
433 |
|
434 | err.message =
|
435 | "Line " +
|
436 | err.lineNumber +
|
437 | ": " +
|
438 | err.message.replace(/ \((\d+):(\d+)\)$/, "") +
|
439 |
|
440 | "\n\n" +
|
441 | codeFrameColumns(
|
442 | code,
|
443 | {
|
444 | start: {
|
445 | line: err.lineNumber,
|
446 | column: err.column,
|
447 | },
|
448 | },
|
449 | { highlightCode: true }
|
450 | );
|
451 | }
|
452 | }
|
453 |
|
454 | throw err;
|
455 | }
|
456 |
|
457 | babylonToEspree(ast, traverse, tt, code);
|
458 |
|
459 | return ast;
|
460 | };
|