[babel 8] Move ESLint parsing to a Worker (#13199)
This commit is contained in:
parent
c2181343f1
commit
9d620c2d42
@ -37,9 +37,9 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"packages/*/src/**/*.{js,ts}",
|
"packages/*/src/**/*.{js,ts,cjs}",
|
||||||
"codemods/*/src/**/*.{js,ts}",
|
"codemods/*/src/**/*.{js,ts,cjs}",
|
||||||
"eslint/*/src/**/*.{js,ts}",
|
"eslint/*/src/**/*.{js,ts,cjs}",
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
"@babel/development/no-undefined-identifier": "error",
|
"@babel/development/no-undefined-identifier": "error",
|
||||||
@ -130,6 +130,12 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ["eslint/babel-eslint-parser/src/**/*.js"],
|
||||||
|
rules: {
|
||||||
|
"no-restricted-imports": ["error", "@babel/core"],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: ["packages/babel-plugin-transform-runtime/scripts/**/*.js"],
|
files: ["packages/babel-plugin-transform-runtime/scripts/**/*.js"],
|
||||||
rules: {
|
rules: {
|
||||||
|
|||||||
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -196,6 +196,12 @@ jobs:
|
|||||||
BABEL_ENV: test
|
BABEL_ENV: test
|
||||||
BABEL_8_BREAKING: true
|
BABEL_8_BREAKING: true
|
||||||
STRIP_BABEL_8_FLAG: true
|
STRIP_BABEL_8_FLAG: true
|
||||||
|
- name: Lint
|
||||||
|
run: make lint
|
||||||
|
env:
|
||||||
|
BABEL_ENV: test
|
||||||
|
BABEL_8_BREAKING: true
|
||||||
|
BABEL_TYPES_8_BREAKING: true
|
||||||
- name: Test
|
- name: Test
|
||||||
# Hack: --color has supports-color@5 returned true for GitHub CI
|
# Hack: --color has supports-color@5 returned true for GitHub CI
|
||||||
# Remove once `chalk` is bumped to 4.0.
|
# Remove once `chalk` is bumped to 4.0.
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"overrides": [{
|
"overrides": [{
|
||||||
"files": [
|
"files": [
|
||||||
"**/{codemods,eslint,packages}/*/{src,test}/**/*.{js,ts}"
|
"**/{codemods,eslint,packages}/*/{src,test}/**/*.{js,ts,cjs}"
|
||||||
],
|
],
|
||||||
"excludeFiles": ["**/packages/babel-helpers/src/helpers/**/*.js"],
|
"excludeFiles": ["**/packages/babel-helpers/src/helpers/**/*.js"],
|
||||||
"options": {
|
"options": {
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": "^10.13.0 || ^12.13.0 || >=14.0.0"
|
"node": "^10.13.0 || ^12.13.0 || >=14.0.0"
|
||||||
},
|
},
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.cjs",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./lib/index.js",
|
".": "./lib/index.cjs",
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@ -1,31 +1,37 @@
|
|||||||
import { types as t } from "@babel/core";
|
const escope = require("eslint-scope");
|
||||||
import escope from "eslint-scope";
|
const { Definition } = require("eslint-scope/lib/definition");
|
||||||
import { Definition } from "eslint-scope/lib/definition";
|
const OriginalPatternVisitor = require("eslint-scope/lib/pattern-visitor");
|
||||||
import OriginalPatternVisitor from "eslint-scope/lib/pattern-visitor";
|
const OriginalReferencer = require("eslint-scope/lib/referencer");
|
||||||
import OriginalReferencer from "eslint-scope/lib/referencer";
|
const { getKeys: fallback } = require("eslint-visitor-keys");
|
||||||
import { getKeys as fallback } from "eslint-visitor-keys";
|
|
||||||
import childVisitorKeys from "./visitor-keys";
|
|
||||||
|
|
||||||
const flowFlippedAliasKeys = t.FLIPPED_ALIAS_KEYS.Flow.concat([
|
const { getTypesInfo, getVisitorKeys } = require("./client.cjs");
|
||||||
"ArrayPattern",
|
|
||||||
"ClassDeclaration",
|
|
||||||
"ClassExpression",
|
|
||||||
"FunctionDeclaration",
|
|
||||||
"FunctionExpression",
|
|
||||||
"Identifier",
|
|
||||||
"ObjectPattern",
|
|
||||||
"RestElement",
|
|
||||||
]);
|
|
||||||
|
|
||||||
const visitorKeysMap = Object.entries(t.VISITOR_KEYS).reduce(
|
let visitorKeysMap;
|
||||||
(acc, [key, value]) => {
|
function getVisitorValues(nodeType) {
|
||||||
|
if (visitorKeysMap) return visitorKeysMap[nodeType];
|
||||||
|
|
||||||
|
const { FLOW_FLIPPED_ALIAS_KEYS, VISITOR_KEYS } = getTypesInfo();
|
||||||
|
|
||||||
|
const flowFlippedAliasKeys = FLOW_FLIPPED_ALIAS_KEYS.concat([
|
||||||
|
"ArrayPattern",
|
||||||
|
"ClassDeclaration",
|
||||||
|
"ClassExpression",
|
||||||
|
"FunctionDeclaration",
|
||||||
|
"FunctionExpression",
|
||||||
|
"Identifier",
|
||||||
|
"ObjectPattern",
|
||||||
|
"RestElement",
|
||||||
|
]);
|
||||||
|
|
||||||
|
visitorKeysMap = Object.entries(VISITOR_KEYS).reduce((acc, [key, value]) => {
|
||||||
if (!flowFlippedAliasKeys.includes(value)) {
|
if (!flowFlippedAliasKeys.includes(value)) {
|
||||||
acc[key] = value;
|
acc[key] = value;
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
},
|
}, {});
|
||||||
{},
|
|
||||||
);
|
return visitorKeysMap[nodeType];
|
||||||
|
}
|
||||||
|
|
||||||
const propertyTypes = {
|
const propertyTypes = {
|
||||||
// loops
|
// loops
|
||||||
@ -65,7 +71,7 @@ class Referencer extends OriginalReferencer {
|
|||||||
|
|
||||||
// Visit type annotations.
|
// Visit type annotations.
|
||||||
this._checkIdentifierOrVisit(node.typeAnnotation);
|
this._checkIdentifierOrVisit(node.typeAnnotation);
|
||||||
if (t.isAssignmentPattern(node)) {
|
if (node.type === "AssignmentPattern") {
|
||||||
this._checkIdentifierOrVisit(node.left.typeAnnotation);
|
this._checkIdentifierOrVisit(node.left.typeAnnotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +264,7 @@ class Referencer extends OriginalReferencer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get property to check (params, id, etc...)
|
// get property to check (params, id, etc...)
|
||||||
const visitorValues = visitorKeysMap[node.type];
|
const visitorValues = getVisitorValues(node.type);
|
||||||
if (!visitorValues) {
|
if (!visitorValues) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -322,7 +328,7 @@ class Referencer extends OriginalReferencer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function analyzeScope(ast, parserOptions) {
|
module.exports = function analyzeScope(ast, parserOptions) {
|
||||||
const options = {
|
const options = {
|
||||||
ignoreEval: true,
|
ignoreEval: true,
|
||||||
optimistic: false,
|
optimistic: false,
|
||||||
@ -337,7 +343,7 @@ export default function analyzeScope(ast, parserOptions) {
|
|||||||
fallback,
|
fallback,
|
||||||
};
|
};
|
||||||
|
|
||||||
options.childVisitorKeys = childVisitorKeys;
|
options.childVisitorKeys = getVisitorKeys();
|
||||||
|
|
||||||
const scopeManager = new escope.ScopeManager(options);
|
const scopeManager = new escope.ScopeManager(options);
|
||||||
const referencer = new Referencer(options, scopeManager);
|
const referencer = new Referencer(options, scopeManager);
|
||||||
@ -345,4 +351,4 @@ export default function analyzeScope(ast, parserOptions) {
|
|||||||
referencer.visit(ast);
|
referencer.visit(ast);
|
||||||
|
|
||||||
return scopeManager;
|
return scopeManager;
|
||||||
}
|
};
|
||||||
67
eslint/babel-eslint-parser/src/client.cjs
Normal file
67
eslint/babel-eslint-parser/src/client.cjs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
let send;
|
||||||
|
|
||||||
|
exports.getVersion = sendCached("GET_VERSION");
|
||||||
|
|
||||||
|
exports.getTypesInfo = sendCached("GET_TYPES_INFO");
|
||||||
|
|
||||||
|
exports.getVisitorKeys = sendCached("GET_VISITOR_KEYS");
|
||||||
|
|
||||||
|
exports.getTokLabels = sendCached("GET_TOKEN_LABELS");
|
||||||
|
|
||||||
|
exports.maybeParse = (code, options) => send("MAYBE_PARSE", { code, options });
|
||||||
|
|
||||||
|
function sendCached(action) {
|
||||||
|
let cache = null;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (!cache) cache = send(action, undefined);
|
||||||
|
return cache;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.BABEL_8_BREAKING) {
|
||||||
|
const {
|
||||||
|
Worker,
|
||||||
|
receiveMessageOnPort,
|
||||||
|
MessageChannel,
|
||||||
|
SHARE_ENV,
|
||||||
|
} = require("worker_threads");
|
||||||
|
|
||||||
|
// We need to run Babel in a worker for two reasons:
|
||||||
|
// 1. ESLint workers must be CJS files, and this is a problem
|
||||||
|
// since Babel 8+ uses native ESM
|
||||||
|
// 2. ESLint parsers must run synchronously, but many steps
|
||||||
|
// of Babel's config loading (which is done for each file)
|
||||||
|
// can be asynchronous
|
||||||
|
// If ESLint starts supporting async parsers, we can move
|
||||||
|
// everything back to the main thread.
|
||||||
|
const worker = new Worker(
|
||||||
|
path.resolve(__dirname, "../lib/worker/index.cjs"),
|
||||||
|
{ env: SHARE_ENV },
|
||||||
|
);
|
||||||
|
|
||||||
|
// The worker will never exit by itself. Prevent it from keeping
|
||||||
|
// the main process alive.
|
||||||
|
worker.unref();
|
||||||
|
|
||||||
|
const signal = new Int32Array(new SharedArrayBuffer(4));
|
||||||
|
|
||||||
|
send = (action, payload) => {
|
||||||
|
signal[0] = 0;
|
||||||
|
const subChannel = new MessageChannel();
|
||||||
|
|
||||||
|
worker.postMessage({ signal, port: subChannel.port1, action, payload }, [
|
||||||
|
subChannel.port1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Atomics.wait(signal, 0, 0);
|
||||||
|
const { message } = receiveMessageOnPort(subChannel.port2);
|
||||||
|
|
||||||
|
if (message.error) throw Object.assign(message.error, message.errorData);
|
||||||
|
else return message.result;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
send = require("./worker/index.cjs");
|
||||||
|
}
|
||||||
20
eslint/babel-eslint-parser/src/configuration.cjs
Normal file
20
eslint/babel-eslint-parser/src/configuration.cjs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
exports.normalizeESLintConfig = function (options) {
|
||||||
|
const {
|
||||||
|
babelOptions = {},
|
||||||
|
// ESLint sets ecmaVersion: undefined when ecmaVersion is not set in the config.
|
||||||
|
ecmaVersion = 2020,
|
||||||
|
sourceType = "module",
|
||||||
|
allowImportExportEverywhere = false,
|
||||||
|
requireConfigFile = true,
|
||||||
|
...otherOptions
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
return {
|
||||||
|
babelOptions,
|
||||||
|
ecmaVersion,
|
||||||
|
sourceType,
|
||||||
|
allowImportExportEverywhere,
|
||||||
|
requireConfigFile,
|
||||||
|
...otherOptions,
|
||||||
|
};
|
||||||
|
};
|
||||||
138
eslint/babel-eslint-parser/src/convert/convertAST.cjs
Normal file
138
eslint/babel-eslint-parser/src/convert/convertAST.cjs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
function* it(children) {
|
||||||
|
if (Array.isArray(children)) yield* children;
|
||||||
|
else yield children;
|
||||||
|
}
|
||||||
|
|
||||||
|
function traverse(node, visitorKeys, visitor) {
|
||||||
|
const { type } = node;
|
||||||
|
if (!type) return;
|
||||||
|
const keys = visitorKeys[type];
|
||||||
|
if (!keys) return;
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
for (const child of it(node[key])) {
|
||||||
|
if (child && typeof child === "object") {
|
||||||
|
visitor.enter(child);
|
||||||
|
traverse(child, visitorKeys, visitor);
|
||||||
|
visitor.exit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertNodesVisitor = {
|
||||||
|
enter(node) {
|
||||||
|
if (node.innerComments) {
|
||||||
|
delete node.innerComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.trailingComments) {
|
||||||
|
delete node.trailingComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.leadingComments) {
|
||||||
|
delete node.leadingComments;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exit(node) {
|
||||||
|
// Used internally by @babel/parser.
|
||||||
|
if (node.extra) {
|
||||||
|
delete node.extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node?.loc.identifierName) {
|
||||||
|
delete node.loc.identifierName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.type === "TypeParameter") {
|
||||||
|
node.type = "Identifier";
|
||||||
|
node.typeAnnotation = node.bound;
|
||||||
|
delete node.bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flow: prevent "no-undef"
|
||||||
|
// for "Component" in: "let x: React.Component"
|
||||||
|
if (node.type === "QualifiedTypeIdentifier") {
|
||||||
|
delete node.id;
|
||||||
|
}
|
||||||
|
// for "b" in: "var a: { b: Foo }"
|
||||||
|
if (node.type === "ObjectTypeProperty") {
|
||||||
|
delete node.key;
|
||||||
|
}
|
||||||
|
// for "indexer" in: "var a: {[indexer: string]: number}"
|
||||||
|
if (node.type === "ObjectTypeIndexer") {
|
||||||
|
delete node.id;
|
||||||
|
}
|
||||||
|
// for "param" in: "var a: { func(param: Foo): Bar };"
|
||||||
|
if (node.type === "FunctionTypeParam") {
|
||||||
|
delete node.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// modules
|
||||||
|
if (node.type === "ImportDeclaration") {
|
||||||
|
delete node.isType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// template string range fixes
|
||||||
|
if (node.type === "TemplateLiteral") {
|
||||||
|
for (let i = 0; i < node.quasis.length; i++) {
|
||||||
|
const q = node.quasis[i];
|
||||||
|
q.range[0] -= 1;
|
||||||
|
if (q.tail) {
|
||||||
|
q.range[1] += 1;
|
||||||
|
} else {
|
||||||
|
q.range[1] += 2;
|
||||||
|
}
|
||||||
|
q.loc.start.column -= 1;
|
||||||
|
if (q.tail) {
|
||||||
|
q.loc.end.column += 1;
|
||||||
|
} else {
|
||||||
|
q.loc.end.column += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function convertNodes(ast, visitorKeys) {
|
||||||
|
traverse(ast, visitorKeys, convertNodesVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertProgramNode(ast) {
|
||||||
|
ast.type = "Program";
|
||||||
|
ast.sourceType = ast.program.sourceType;
|
||||||
|
ast.body = ast.program.body;
|
||||||
|
delete ast.program;
|
||||||
|
delete ast.errors;
|
||||||
|
|
||||||
|
if (ast.comments.length) {
|
||||||
|
const lastComment = ast.comments[ast.comments.length - 1];
|
||||||
|
|
||||||
|
if (ast.tokens.length) {
|
||||||
|
const lastToken = ast.tokens[ast.tokens.length - 1];
|
||||||
|
|
||||||
|
if (lastComment.end > lastToken.end) {
|
||||||
|
// If there is a comment after the last token, the program ends at the
|
||||||
|
// last token and not the comment
|
||||||
|
ast.range[1] = lastToken.end;
|
||||||
|
ast.loc.end.line = lastToken.loc.end.line;
|
||||||
|
ast.loc.end.column = lastToken.loc.end.column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!ast.tokens.length) {
|
||||||
|
ast.loc.start.line = 1;
|
||||||
|
ast.loc.end.line = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast.body && ast.body.length > 0) {
|
||||||
|
ast.loc.start.line = ast.body[0].loc.start.line;
|
||||||
|
ast.range[0] = ast.body[0].start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function convertAST(ast, visitorKeys) {
|
||||||
|
convertNodes(ast, visitorKeys);
|
||||||
|
convertProgramNode(ast);
|
||||||
|
};
|
||||||
@ -1,148 +0,0 @@
|
|||||||
import { types as t, traverse } from "@babel/core";
|
|
||||||
import { newTypes, conflictTypes } from "../visitor-keys";
|
|
||||||
|
|
||||||
function convertNodes(ast, code) {
|
|
||||||
const astTransformVisitor = {
|
|
||||||
noScope: true,
|
|
||||||
enter(path) {
|
|
||||||
const { node } = path;
|
|
||||||
|
|
||||||
if (node.innerComments) {
|
|
||||||
delete node.innerComments;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.trailingComments) {
|
|
||||||
delete node.trailingComments;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.leadingComments) {
|
|
||||||
delete node.leadingComments;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
exit(path) {
|
|
||||||
const { node } = path;
|
|
||||||
|
|
||||||
// Used internally by @babel/parser.
|
|
||||||
if (node.extra) {
|
|
||||||
delete node.extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node?.loc.identifierName) {
|
|
||||||
delete node.loc.identifierName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.isTypeParameter()) {
|
|
||||||
node.type = "Identifier";
|
|
||||||
node.typeAnnotation = node.bound;
|
|
||||||
delete node.bound;
|
|
||||||
}
|
|
||||||
|
|
||||||
// flow: prevent "no-undef"
|
|
||||||
// for "Component" in: "let x: React.Component"
|
|
||||||
if (path.isQualifiedTypeIdentifier()) {
|
|
||||||
delete node.id;
|
|
||||||
}
|
|
||||||
// for "b" in: "var a: { b: Foo }"
|
|
||||||
if (path.isObjectTypeProperty()) {
|
|
||||||
delete node.key;
|
|
||||||
}
|
|
||||||
// for "indexer" in: "var a: {[indexer: string]: number}"
|
|
||||||
if (path.isObjectTypeIndexer()) {
|
|
||||||
delete node.id;
|
|
||||||
}
|
|
||||||
// for "param" in: "var a: { func(param: Foo): Bar };"
|
|
||||||
if (path.isFunctionTypeParam()) {
|
|
||||||
delete node.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// modules
|
|
||||||
if (path.isImportDeclaration()) {
|
|
||||||
delete node.isType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// template string range fixes
|
|
||||||
if (path.isTemplateLiteral()) {
|
|
||||||
for (let i = 0; i < node.quasis.length; i++) {
|
|
||||||
const q = node.quasis[i];
|
|
||||||
q.range[0] -= 1;
|
|
||||||
if (q.tail) {
|
|
||||||
q.range[1] += 1;
|
|
||||||
} else {
|
|
||||||
q.range[1] += 2;
|
|
||||||
}
|
|
||||||
q.loc.start.column -= 1;
|
|
||||||
if (q.tail) {
|
|
||||||
q.loc.end.column += 1;
|
|
||||||
} else {
|
|
||||||
q.loc.end.column += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const state = { source: code };
|
|
||||||
const oldVisitorKeys = new Map();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (const [type, visitorKey] of Object.entries(conflictTypes)) {
|
|
||||||
// backup conflicted visitor keys
|
|
||||||
oldVisitorKeys.set(type, t.VISITOR_KEYS[type]);
|
|
||||||
|
|
||||||
t.VISITOR_KEYS[type] = visitorKey;
|
|
||||||
}
|
|
||||||
for (const [type, visitorKey] of Object.entries(newTypes)) {
|
|
||||||
t.VISITOR_KEYS[type] = visitorKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
traverse(ast, astTransformVisitor, null, state);
|
|
||||||
} finally {
|
|
||||||
// These can be safely deleted because they are not defined in the original visitor keys.
|
|
||||||
for (const type of Object.keys(newTypes)) {
|
|
||||||
delete t.VISITOR_KEYS[type];
|
|
||||||
}
|
|
||||||
|
|
||||||
// These should be restored
|
|
||||||
for (const type of Object.keys(conflictTypes)) {
|
|
||||||
t.VISITOR_KEYS[type] = oldVisitorKeys.get(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertProgramNode(ast) {
|
|
||||||
ast.type = "Program";
|
|
||||||
ast.sourceType = ast.program.sourceType;
|
|
||||||
ast.body = ast.program.body;
|
|
||||||
delete ast.program;
|
|
||||||
delete ast.errors;
|
|
||||||
|
|
||||||
if (ast.comments.length) {
|
|
||||||
const lastComment = ast.comments[ast.comments.length - 1];
|
|
||||||
|
|
||||||
if (ast.tokens.length) {
|
|
||||||
const lastToken = ast.tokens[ast.tokens.length - 1];
|
|
||||||
|
|
||||||
if (lastComment.end > lastToken.end) {
|
|
||||||
// If there is a comment after the last token, the program ends at the
|
|
||||||
// last token and not the comment
|
|
||||||
ast.range[1] = lastToken.end;
|
|
||||||
ast.loc.end.line = lastToken.loc.end.line;
|
|
||||||
ast.loc.end.column = lastToken.loc.end.column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!ast.tokens.length) {
|
|
||||||
ast.loc.start.line = 1;
|
|
||||||
ast.loc.end.line = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ast.body && ast.body.length > 0) {
|
|
||||||
ast.loc.start.line = ast.body[0].loc.start.line;
|
|
||||||
ast.range[0] = ast.body[0].start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function convertAST(ast, code) {
|
|
||||||
convertNodes(ast, code);
|
|
||||||
convertProgramNode(ast);
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
export default function convertComments(comments) {
|
module.exports = function convertComments(comments) {
|
||||||
for (const comment of comments) {
|
for (const comment of comments) {
|
||||||
if (comment.type === "CommentBlock") {
|
if (comment.type === "CommentBlock") {
|
||||||
comment.type = "Block";
|
comment.type = "Block";
|
||||||
@ -11,4 +11,4 @@ export default function convertComments(comments) {
|
|||||||
comment.range = [comment.start, comment.end];
|
comment.range = [comment.start, comment.end];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
@ -1,12 +1,4 @@
|
|||||||
import { tokTypes } from "@babel/core";
|
function convertTemplateType(tokens, tl) {
|
||||||
|
|
||||||
const tl = (
|
|
||||||
process.env.BABEL_8_BREAKING
|
|
||||||
? Object.fromEntries
|
|
||||||
: p => p.reduce((o, [k, v]) => ({ ...o, [k]: v }), {})
|
|
||||||
)(Object.keys(tokTypes).map(key => [key, tokTypes[key].label]));
|
|
||||||
|
|
||||||
function convertTemplateType(tokens) {
|
|
||||||
let curlyBrace = null;
|
let curlyBrace = null;
|
||||||
let templateTokens = [];
|
let templateTokens = [];
|
||||||
const result = [];
|
const result = [];
|
||||||
@ -97,7 +89,7 @@ function convertTemplateType(tokens) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertToken(token, source) {
|
function convertToken(token, source, tl) {
|
||||||
const { type } = token;
|
const { type } = token;
|
||||||
const { label } = type;
|
const { label } = type;
|
||||||
token.range = [token.start, token.end];
|
token.range = [token.start, token.end];
|
||||||
@ -192,8 +184,8 @@ function convertToken(token, source) {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function convertTokens(tokens, code) {
|
module.exports = function convertTokens(tokens, code, tl) {
|
||||||
return convertTemplateType(tokens)
|
return convertTemplateType(tokens, tl)
|
||||||
.filter(t => t.type !== "CommentLine" && t.type !== "CommentBlock")
|
.filter(t => t.type !== "CommentLine" && t.type !== "CommentBlock")
|
||||||
.map(t => convertToken(t, code));
|
.map(t => convertToken(t, code, tl));
|
||||||
}
|
};
|
||||||
18
eslint/babel-eslint-parser/src/convert/index.cjs
Normal file
18
eslint/babel-eslint-parser/src/convert/index.cjs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const convertTokens = require("./convertTokens.cjs");
|
||||||
|
const convertComments = require("./convertComments.cjs");
|
||||||
|
const convertAST = require("./convertAST.cjs");
|
||||||
|
|
||||||
|
exports.ast = function convert(ast, code, tokLabels, visitorKeys) {
|
||||||
|
ast.tokens = convertTokens(ast.tokens, code, tokLabels);
|
||||||
|
convertComments(ast.comments);
|
||||||
|
convertAST(ast, visitorKeys);
|
||||||
|
return ast;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.error = function convertError(err) {
|
||||||
|
if (err instanceof SyntaxError) {
|
||||||
|
err.lineNumber = err.loc.line;
|
||||||
|
err.column = err.loc.column;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
};
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import convertTokens from "./convertTokens";
|
|
||||||
import convertComments from "./convertComments";
|
|
||||||
import convertAST from "./convertAST";
|
|
||||||
|
|
||||||
export default function (ast, code) {
|
|
||||||
ast.tokens = convertTokens(ast.tokens, code);
|
|
||||||
convertComments(ast.comments);
|
|
||||||
convertAST(ast, code);
|
|
||||||
}
|
|
||||||
63
eslint/babel-eslint-parser/src/index.cjs
Normal file
63
eslint/babel-eslint-parser/src/index.cjs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
const semver = require("semver");
|
||||||
|
const { normalizeESLintConfig } = require("./configuration.cjs");
|
||||||
|
const analyzeScope = require("./analyze-scope.cjs");
|
||||||
|
const {
|
||||||
|
getVersion,
|
||||||
|
getVisitorKeys,
|
||||||
|
getTokLabels,
|
||||||
|
maybeParse,
|
||||||
|
} = require("./client.cjs");
|
||||||
|
const convert = require("./convert/index.cjs");
|
||||||
|
|
||||||
|
const babelParser = require(require.resolve("@babel/parser", {
|
||||||
|
paths: [require.resolve("@babel/core/package.json")],
|
||||||
|
}));
|
||||||
|
|
||||||
|
let isRunningMinSupportedCoreVersion = null;
|
||||||
|
|
||||||
|
function baseParse(code, options) {
|
||||||
|
// Ensure we're using a version of `@babel/core` that includes `parse()` and `tokTypes`.
|
||||||
|
const minSupportedCoreVersion = ">=7.2.0";
|
||||||
|
|
||||||
|
if (typeof isRunningMinSupportedCoreVersion !== "boolean") {
|
||||||
|
isRunningMinSupportedCoreVersion = semver.satisfies(
|
||||||
|
getVersion(),
|
||||||
|
minSupportedCoreVersion,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isRunningMinSupportedCoreVersion) {
|
||||||
|
throw new Error(
|
||||||
|
`@babel/eslint-parser@${
|
||||||
|
PACKAGE_JSON.version
|
||||||
|
} does not support @babel/core@${getVersion()}. Please upgrade to @babel/core@${minSupportedCoreVersion}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { ast, parserOptions } = maybeParse(code, options);
|
||||||
|
|
||||||
|
if (ast) return ast;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return convert.ast(
|
||||||
|
babelParser.parse(code, parserOptions),
|
||||||
|
code,
|
||||||
|
getTokLabels(),
|
||||||
|
getVisitorKeys(),
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
throw convert.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.parse = function (code, options = {}) {
|
||||||
|
return baseParse(code, normalizeESLintConfig(options));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.parseForESLint = function (code, options = {}) {
|
||||||
|
const normalizedOptions = normalizeESLintConfig(options);
|
||||||
|
const ast = baseParse(code, normalizedOptions);
|
||||||
|
const scopeManager = analyzeScope(ast, normalizedOptions);
|
||||||
|
|
||||||
|
return { ast, scopeManager, visitorKeys: getVisitorKeys() };
|
||||||
|
};
|
||||||
@ -1,61 +0,0 @@
|
|||||||
import semver from "semver";
|
|
||||||
import {
|
|
||||||
version as babelCoreVersion,
|
|
||||||
parseSync as babelParse,
|
|
||||||
} from "@babel/core";
|
|
||||||
import {
|
|
||||||
normalizeBabelParseConfig,
|
|
||||||
normalizeESLintConfig,
|
|
||||||
} from "./configuration";
|
|
||||||
import convert from "./convert";
|
|
||||||
import analyzeScope from "./analyze-scope";
|
|
||||||
import visitorKeys from "./visitor-keys";
|
|
||||||
|
|
||||||
let isRunningMinSupportedCoreVersion = null;
|
|
||||||
|
|
||||||
function baseParse(code, options) {
|
|
||||||
// Ensure we're using a version of `@babel/core` that includes `parse()` and `tokTypes`.
|
|
||||||
const minSupportedCoreVersion = ">=7.2.0";
|
|
||||||
|
|
||||||
if (typeof isRunningMinSupportedCoreVersion !== "boolean") {
|
|
||||||
isRunningMinSupportedCoreVersion = semver.satisfies(
|
|
||||||
babelCoreVersion,
|
|
||||||
minSupportedCoreVersion,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isRunningMinSupportedCoreVersion) {
|
|
||||||
throw new Error(
|
|
||||||
`@babel/eslint-parser@${PACKAGE_JSON.version} does not support @babel/core@${babelCoreVersion}. Please upgrade to @babel/core@${minSupportedCoreVersion}.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ast;
|
|
||||||
|
|
||||||
try {
|
|
||||||
ast = babelParse(code, normalizeBabelParseConfig(options));
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof SyntaxError) {
|
|
||||||
err.lineNumber = err.loc.line;
|
|
||||||
err.column = err.loc.column;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
convert(ast, code);
|
|
||||||
|
|
||||||
return ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parse(code, options = {}) {
|
|
||||||
return baseParse(code, normalizeESLintConfig(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseForESLint(code, options = {}) {
|
|
||||||
const normalizedOptions = normalizeESLintConfig(options);
|
|
||||||
const ast = baseParse(code, normalizedOptions);
|
|
||||||
const scopeManager = analyzeScope(ast, normalizedOptions);
|
|
||||||
|
|
||||||
return { ast, scopeManager, visitorKeys };
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
import { types as t } from "@babel/core";
|
|
||||||
import { KEYS as ESLINT_VISITOR_KEYS } from "eslint-visitor-keys";
|
|
||||||
|
|
||||||
// AST Types that are not presented in Babel AST
|
|
||||||
export const newTypes = {
|
|
||||||
ChainExpression: ESLINT_VISITOR_KEYS.ChainExpression,
|
|
||||||
ImportExpression: ESLINT_VISITOR_KEYS.ImportExpression,
|
|
||||||
Literal: ESLINT_VISITOR_KEYS.Literal,
|
|
||||||
MethodDefinition: ["decorators"].concat(ESLINT_VISITOR_KEYS.MethodDefinition),
|
|
||||||
Property: ["decorators"].concat(ESLINT_VISITOR_KEYS.Property),
|
|
||||||
PropertyDefinition: ["decorators"].concat(
|
|
||||||
ESLINT_VISITOR_KEYS.PropertyDefinition,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// AST Types that shares `"type"` property with Babel but have different shape
|
|
||||||
export const conflictTypes = {
|
|
||||||
// todo: remove this when we drop Babel 7 support
|
|
||||||
ClassPrivateMethod: ["decorators"].concat(
|
|
||||||
ESLINT_VISITOR_KEYS.MethodDefinition,
|
|
||||||
),
|
|
||||||
ExportAllDeclaration: ESLINT_VISITOR_KEYS.ExportAllDeclaration,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default { ...newTypes, ...t.VISITOR_KEYS, ...conflictTypes };
|
|
||||||
46
eslint/babel-eslint-parser/src/worker/ast-info.cjs
Normal file
46
eslint/babel-eslint-parser/src/worker/ast-info.cjs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
const ESLINT_VISITOR_KEYS = require("eslint-visitor-keys").KEYS;
|
||||||
|
const babel = require("./babel-core.cjs");
|
||||||
|
|
||||||
|
let visitorKeys;
|
||||||
|
exports.getVisitorKeys = function getVisitorKeys() {
|
||||||
|
if (!visitorKeys) {
|
||||||
|
// AST Types that are not presented in Babel AST
|
||||||
|
const newTypes = {
|
||||||
|
ChainExpression: ESLINT_VISITOR_KEYS.ChainExpression,
|
||||||
|
ImportExpression: ESLINT_VISITOR_KEYS.ImportExpression,
|
||||||
|
Literal: ESLINT_VISITOR_KEYS.Literal,
|
||||||
|
MethodDefinition: ["decorators"].concat(
|
||||||
|
ESLINT_VISITOR_KEYS.MethodDefinition,
|
||||||
|
),
|
||||||
|
Property: ["decorators"].concat(ESLINT_VISITOR_KEYS.Property),
|
||||||
|
PropertyDefinition: ["decorators"].concat(
|
||||||
|
ESLINT_VISITOR_KEYS.PropertyDefinition,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// AST Types that shares `"type"` property with Babel but have different shape
|
||||||
|
const conflictTypes = {
|
||||||
|
// todo: remove this when we drop Babel 7 support
|
||||||
|
ClassPrivateMethod: ["decorators"].concat(
|
||||||
|
ESLINT_VISITOR_KEYS.MethodDefinition,
|
||||||
|
),
|
||||||
|
ExportAllDeclaration: ESLINT_VISITOR_KEYS.ExportAllDeclaration,
|
||||||
|
};
|
||||||
|
|
||||||
|
visitorKeys = {
|
||||||
|
...newTypes,
|
||||||
|
...babel.types.VISITOR_KEYS,
|
||||||
|
...conflictTypes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return visitorKeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
let tokLabels;
|
||||||
|
exports.getTokLabels = function getTokLabels() {
|
||||||
|
return (tokLabels ||= (
|
||||||
|
process.env.BABEL_8_BREAKING
|
||||||
|
? Object.fromEntries
|
||||||
|
: p => p.reduce((o, [k, v]) => ({ ...o, [k]: v }), {})
|
||||||
|
)(Object.entries(babel.tokTypes).map(([key, tok]) => [key, tok.label])));
|
||||||
|
};
|
||||||
17
eslint/babel-eslint-parser/src/worker/babel-core.cjs
Normal file
17
eslint/babel-eslint-parser/src/worker/babel-core.cjs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
function initialize(babel) {
|
||||||
|
exports.init = null;
|
||||||
|
exports.version = babel.version;
|
||||||
|
exports.traverse = babel.traverse;
|
||||||
|
exports.types = babel.types;
|
||||||
|
exports.tokTypes = babel.tokTypes;
|
||||||
|
exports.parseSync = babel.parseSync;
|
||||||
|
exports.loadPartialConfigSync = babel.loadPartialConfigSync;
|
||||||
|
exports.loadPartialConfigAsync = babel.loadPartialConfigAsync;
|
||||||
|
exports.createConfigItem = babel.createConfigItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.BABEL_8_BREAKING) {
|
||||||
|
exports.init = import("@babel/core").then(ns => initialize(ns.default));
|
||||||
|
} else {
|
||||||
|
initialize(require("@babel/core"));
|
||||||
|
}
|
||||||
@ -1,25 +1,4 @@
|
|||||||
import { loadPartialConfig } from "@babel/core";
|
const babel = require("./babel-core.cjs");
|
||||||
|
|
||||||
export function normalizeESLintConfig(options) {
|
|
||||||
const {
|
|
||||||
babelOptions = {},
|
|
||||||
// ESLint sets ecmaVersion: undefined when ecmaVersion is not set in the config.
|
|
||||||
ecmaVersion = 2020,
|
|
||||||
sourceType = "module",
|
|
||||||
allowImportExportEverywhere = false,
|
|
||||||
requireConfigFile = true,
|
|
||||||
...otherOptions
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
return {
|
|
||||||
babelOptions,
|
|
||||||
ecmaVersion,
|
|
||||||
sourceType,
|
|
||||||
allowImportExportEverywhere,
|
|
||||||
requireConfigFile,
|
|
||||||
...otherOptions,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge user supplied estree plugin options to default estree plugin options
|
* Merge user supplied estree plugin options to default estree plugin options
|
||||||
@ -41,8 +20,8 @@ function getParserPlugins(babelOptions) {
|
|||||||
return [["estree", estreeOptions], ...babelParserPlugins];
|
return [["estree", estreeOptions], ...babelParserPlugins];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeBabelParseConfig(options) {
|
function normalizeParserOptions(options) {
|
||||||
const parseOptions = {
|
return {
|
||||||
sourceType: options.sourceType,
|
sourceType: options.sourceType,
|
||||||
filename: options.filePath,
|
filename: options.filePath,
|
||||||
...options.babelOptions,
|
...options.babelOptions,
|
||||||
@ -60,11 +39,11 @@ export function normalizeBabelParseConfig(options) {
|
|||||||
...options.babelOptions.caller,
|
...options.babelOptions.caller,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (options.requireConfigFile !== false) {
|
function validateResolvedConfig(config, options) {
|
||||||
const config = loadPartialConfig(parseOptions);
|
if (config !== null) {
|
||||||
|
if (options.requireConfigFile !== false) {
|
||||||
if (config !== null) {
|
|
||||||
if (!config.hasFilesystemConfig()) {
|
if (!config.hasFilesystemConfig()) {
|
||||||
let error = `No Babel config file detected for ${config.options.filename}. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.`;
|
let error = `No Babel config file detected for ${config.options.filename}. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.`;
|
||||||
|
|
||||||
@ -74,10 +53,20 @@ export function normalizeBabelParseConfig(options) {
|
|||||||
|
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return config.options;
|
|
||||||
}
|
}
|
||||||
|
return config.options;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseOptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = function normalizeBabelParseConfig(options) {
|
||||||
|
const parseOptions = normalizeParserOptions(options);
|
||||||
|
|
||||||
|
if (process.env.BABEL_8_BREAKING) {
|
||||||
|
return babel
|
||||||
|
.loadPartialConfigAsync(parseOptions)
|
||||||
|
.then(config => validateResolvedConfig(config, options) || parseOptions);
|
||||||
|
} else {
|
||||||
|
const config = babel.loadPartialConfigSync(parseOptions);
|
||||||
|
return validateResolvedConfig(config, options) || parseOptions;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = function extractParserOptionsPlugin() {
|
||||||
|
return {
|
||||||
|
parserOverride(code, opts) {
|
||||||
|
return opts;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
66
eslint/babel-eslint-parser/src/worker/index.cjs
Normal file
66
eslint/babel-eslint-parser/src/worker/index.cjs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
const babel = require("./babel-core.cjs");
|
||||||
|
const maybeParse = require("./maybeParse.cjs");
|
||||||
|
const { getVisitorKeys, getTokLabels } = require("./ast-info.cjs");
|
||||||
|
const normalizeBabelParseConfig = require("./configuration.cjs");
|
||||||
|
|
||||||
|
function handleMessage(action, payload) {
|
||||||
|
switch (action) {
|
||||||
|
case "GET_VERSION":
|
||||||
|
return babel.version;
|
||||||
|
case "GET_TYPES_INFO":
|
||||||
|
return {
|
||||||
|
FLOW_FLIPPED_ALIAS_KEYS: babel.types.FLIPPED_ALIAS_KEYS.Flow,
|
||||||
|
VISITOR_KEYS: babel.types.VISITOR_KEYS,
|
||||||
|
};
|
||||||
|
case "GET_TOKEN_LABELS":
|
||||||
|
return getTokLabels();
|
||||||
|
case "GET_VISITOR_KEYS":
|
||||||
|
return getVisitorKeys();
|
||||||
|
case "MAYBE_PARSE":
|
||||||
|
if (process.env.BABEL_8_BREAKING) {
|
||||||
|
return normalizeBabelParseConfig(payload.options).then(options =>
|
||||||
|
maybeParse(payload.code, options),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return maybeParse(
|
||||||
|
payload.code,
|
||||||
|
normalizeBabelParseConfig(payload.options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unknown internal parser worker action: ${action}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.BABEL_8_BREAKING) {
|
||||||
|
const { parentPort } = require("worker_threads");
|
||||||
|
|
||||||
|
parentPort.addListener(
|
||||||
|
"message",
|
||||||
|
async ({ signal, port, action, payload }) => {
|
||||||
|
let response;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (babel.init) await babel.init;
|
||||||
|
|
||||||
|
response = { result: await handleMessage(action, payload) };
|
||||||
|
} catch (error) {
|
||||||
|
response = { error, errorData: { ...error } };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
port.postMessage(response);
|
||||||
|
} catch {
|
||||||
|
port.postMessage({
|
||||||
|
error: new Error("Cannot serialize worker response"),
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
port.close();
|
||||||
|
Atomics.store(signal, 0, 1);
|
||||||
|
Atomics.notify(signal, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
module.exports = handleMessage;
|
||||||
|
}
|
||||||
43
eslint/babel-eslint-parser/src/worker/maybeParse.cjs
Normal file
43
eslint/babel-eslint-parser/src/worker/maybeParse.cjs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
const babel = require("./babel-core.cjs");
|
||||||
|
const convert = require("../convert/index.cjs");
|
||||||
|
const { getVisitorKeys, getTokLabels } = require("./ast-info.cjs");
|
||||||
|
const extractParserOptionsPlugin = require("./extract-parser-options-plugin.cjs");
|
||||||
|
|
||||||
|
const ref = {};
|
||||||
|
let extractParserOptionsConfigItem;
|
||||||
|
|
||||||
|
const MULTIPLE_OVERRIDES = /More than one plugin attempted to override parsing/;
|
||||||
|
|
||||||
|
module.exports = function maybeParse(code, options) {
|
||||||
|
if (!extractParserOptionsConfigItem) {
|
||||||
|
extractParserOptionsConfigItem = babel.createConfigItem(
|
||||||
|
[extractParserOptionsPlugin, ref],
|
||||||
|
{ dirname: __dirname, type: "plugin" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
options.plugins.push(extractParserOptionsConfigItem);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
parserOptions: babel.parseSync(code, options),
|
||||||
|
ast: null,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
if (!MULTIPLE_OVERRIDES.test(err.message)) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ast;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ast = babel.parseSync(code, options);
|
||||||
|
} catch (err) {
|
||||||
|
throw convert.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
ast: convert.ast(ast, code, getTokLabels(), getVisitorKeys()),
|
||||||
|
parserOptions: null,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -3,7 +3,7 @@ import escope from "eslint-scope";
|
|||||||
import unpad from "dedent";
|
import unpad from "dedent";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import { createRequire } from "module";
|
import { createRequire } from "module";
|
||||||
import { parseForESLint } from "../src";
|
import { parseForESLint } from "../lib/index.cjs";
|
||||||
|
|
||||||
const BABEL_OPTIONS = {
|
const BABEL_OPTIONS = {
|
||||||
configFile: path.resolve(
|
configFile: path.resolve(
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/eslint-parser": "workspace:^7.14.2",
|
"@babel/eslint-parser": "workspace:^7.14.2",
|
||||||
|
"@babel/preset-react": "workspace:^7.13.13",
|
||||||
"dedent": "^0.7.0",
|
"dedent": "^0.7.0",
|
||||||
"eslint": "^7.5.0",
|
"eslint": "^7.5.0",
|
||||||
"eslint-plugin-import": "^2.22.0",
|
"eslint-plugin-import": "^2.22.0",
|
||||||
|
|||||||
13
eslint/babel-eslint-tests/test/fixtures/mjs-config-file/.eslintrc.js
vendored
Normal file
13
eslint/babel-eslint-tests/test/fixtures/mjs-config-file/.eslintrc.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parser: "@babel/eslint-parser",
|
||||||
|
parserOptions: {
|
||||||
|
babelOptions: {
|
||||||
|
configFile: __dirname + "/babel.config.mjs",
|
||||||
|
sourceType: "module",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"template-curly-spacing": "error",
|
||||||
|
},
|
||||||
|
};
|
||||||
1
eslint/babel-eslint-tests/test/fixtures/mjs-config-file/a.js
vendored
Normal file
1
eslint/babel-eslint-tests/test/fixtures/mjs-config-file/a.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default () => <div />;
|
||||||
3
eslint/babel-eslint-tests/test/fixtures/mjs-config-file/babel.config.mjs
vendored
Normal file
3
eslint/babel-eslint-tests/test/fixtures/mjs-config-file/babel.config.mjs
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
presets: ["@babel/preset-react"],
|
||||||
|
};
|
||||||
@ -2,7 +2,7 @@ import eslint from "eslint";
|
|||||||
import unpad from "dedent";
|
import unpad from "dedent";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import * as parser from "../../../babel-eslint-parser";
|
import * as parser from "../../../babel-eslint-parser/lib/index.cjs";
|
||||||
|
|
||||||
export default function verifyAndAssertMessages(
|
export default function verifyAndAssertMessages(
|
||||||
code,
|
code,
|
||||||
|
|||||||
19
eslint/babel-eslint-tests/test/integration/config-files.js
Normal file
19
eslint/babel-eslint-tests/test/integration/config-files.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import eslint from "eslint";
|
||||||
|
import path from "path";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
|
describe("Babel config files", () => {
|
||||||
|
const babel8 = process.env.BABEL_8_BREAKING ? it : it.skip;
|
||||||
|
|
||||||
|
babel8("works with babel.config.mjs", () => {
|
||||||
|
const engine = new eslint.CLIEngine({ ignore: false });
|
||||||
|
expect(
|
||||||
|
engine.executeOnFiles([
|
||||||
|
path.resolve(
|
||||||
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
`../fixtures/mjs-config-file/a.js`,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
).toMatchObject({ errorCount: 0 });
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import eslint from "eslint";
|
import eslint from "eslint";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import * as parser from "../../../../../babel-eslint-parser";
|
import * as parser from "../../../../../babel-eslint-parser/lib/index.cjs";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
eslint.linter.defineParser("@babel/eslint-parser", parser);
|
eslint.linter.defineParser("@babel/eslint-parser", parser);
|
||||||
|
|||||||
@ -42,6 +42,7 @@ export default function* parser(
|
|||||||
}
|
}
|
||||||
return results[0];
|
return results[0];
|
||||||
}
|
}
|
||||||
|
// TODO: Add an error code
|
||||||
throw new Error("More than one plugin attempted to override parsing.");
|
throw new Error("More than one plugin attempted to override parsing.");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED") {
|
if (err.code === "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED") {
|
||||||
|
|||||||
@ -311,6 +311,7 @@ __metadata:
|
|||||||
resolution: "@babel/eslint-tests@workspace:eslint/babel-eslint-tests"
|
resolution: "@babel/eslint-tests@workspace:eslint/babel-eslint-tests"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/eslint-parser": "workspace:^7.14.2"
|
"@babel/eslint-parser": "workspace:^7.14.2"
|
||||||
|
"@babel/preset-react": "workspace:^7.13.13"
|
||||||
dedent: ^0.7.0
|
dedent: ^0.7.0
|
||||||
eslint: ^7.5.0
|
eslint: ^7.5.0
|
||||||
eslint-plugin-import: ^2.22.0
|
eslint-plugin-import: ^2.22.0
|
||||||
@ -3278,7 +3279,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/preset-react@workspace:*, @babel/preset-react@workspace:^7.12.13, @babel/preset-react@workspace:packages/babel-preset-react":
|
"@babel/preset-react@workspace:*, @babel/preset-react@workspace:^7.12.13, @babel/preset-react@workspace:^7.13.13, @babel/preset-react@workspace:packages/babel-preset-react":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@babel/preset-react@workspace:packages/babel-preset-react"
|
resolution: "@babel/preset-react@workspace:packages/babel-preset-react"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user