Add espree parser (#9000)
Co-authored-by: Chris Brody <chris.brody+brodybits@gmail.com>
This commit is contained in:
1 parent
2bc68f11f3
commit
73e3976c34
73 files changed
+397
-116
No files matched your search
@@ -27,6 +27,8 @@ function clean(ast, newObj, parent) {
|
||||
if (newObj.value) {
|
||||
newObj.value = newObj.value.toLowerCase();
|
||||
}
|
||||
}
|
||||
if (ast.type === "BigIntLiteral" || ast.type === "Literal") {
|
||||
if (newObj.bigint) {
|
||||
newObj.bigint = newObj.bigint.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -991,7 +991,9 @@ function getCommentChildNodes(node, options) {
|
||||
// }
|
||||
// }
|
||||
if (
|
||||
(options.parser === "typescript" || options.parser === "flow") &&
|
||||
(options.parser === "typescript" ||
|
||||
options.parser === "flow" ||
|
||||
options.parser === "espree") &&
|
||||
node.type === "MethodDefinition" &&
|
||||
node.value &&
|
||||
node.value.type === "FunctionExpression" &&
|
||||
|
||||
@@ -10,7 +10,14 @@ const languages = [
|
||||
require("linguist-languages/data/JavaScript.json"),
|
||||
(data) => ({
|
||||
since: "0.0.0",
|
||||
parsers: ["babel", "babel-flow", "babel-ts", "flow", "typescript"],
|
||||
parsers: [
|
||||
"babel",
|
||||
"espree",
|
||||
"babel-flow",
|
||||
"babel-ts",
|
||||
"flow",
|
||||
"typescript",
|
||||
],
|
||||
vscodeLanguageIds: ["javascript", "mongo"],
|
||||
extensions: [
|
||||
...data.extensions,
|
||||
@@ -31,7 +38,14 @@ const languages = [
|
||||
})),
|
||||
createLanguage(require("linguist-languages/data/JSX.json"), () => ({
|
||||
since: "0.0.0",
|
||||
parsers: ["babel", "babel-flow", "babel-ts", "flow", "typescript"],
|
||||
parsers: [
|
||||
"babel",
|
||||
"babel-flow",
|
||||
"babel-ts",
|
||||
"flow",
|
||||
"typescript",
|
||||
"espree",
|
||||
],
|
||||
vscodeLanguageIds: ["javascriptreact"],
|
||||
})),
|
||||
createLanguage(require("linguist-languages/data/TypeScript.json"), () => ({
|
||||
@@ -132,6 +146,10 @@ const parsers = {
|
||||
get __ng_directive() {
|
||||
return require("./parser-angular").parsers.__ng_directive;
|
||||
},
|
||||
// JS - espree
|
||||
get espree() {
|
||||
return require("./parser-espree").parsers.espree;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"use strict";
|
||||
const { getShebang } = require("../common/util");
|
||||
const createError = require("../common/parser-create-error");
|
||||
const { hasPragma } = require("./pragma");
|
||||
const { locStart, locEnd } = require("./loc");
|
||||
const postprocess = require("./postprocess");
|
||||
|
||||
const espreeOptions = {
|
||||
range: true,
|
||||
loc: true,
|
||||
comment: true,
|
||||
tokens: true,
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
globalReturn: true,
|
||||
impliedStrict: false,
|
||||
},
|
||||
};
|
||||
|
||||
function parse(originalText, parsers, options) {
|
||||
const { parse, latestEcmaVersion } = require("espree");
|
||||
espreeOptions.ecmaVersion = latestEcmaVersion;
|
||||
|
||||
// Replace shebang with space
|
||||
const shebang = getShebang(originalText);
|
||||
const text = shebang
|
||||
? " ".repeat(shebang.length) + originalText.slice(shebang.length)
|
||||
: originalText;
|
||||
|
||||
let ast;
|
||||
|
||||
try {
|
||||
ast = parse(text, espreeOptions);
|
||||
} catch (moduleError) {
|
||||
try {
|
||||
ast = parse(text, { ...espreeOptions, sourceType: "script" });
|
||||
} catch (scriptError) {
|
||||
// throw the error for `module` parsing
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (typeof moduleError.lineNumber === "undefined") {
|
||||
throw moduleError;
|
||||
}
|
||||
|
||||
throw createError(moduleError.message, {
|
||||
start: { line: moduleError.lineNumber, column: moduleError.column },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return postprocess(ast, { ...options, originalText });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parsers: {
|
||||
espree: { parse, astFormat: "estree", hasPragma, locStart, locEnd },
|
||||
},
|
||||
};
|
||||
@@ -9,12 +9,20 @@ const { composeLoc, locStart, locEnd } = require("./loc");
|
||||
const { isTypeCastComment } = require("./comments");
|
||||
|
||||
function postprocess(ast, options) {
|
||||
if (options.parser === "typescript" || options.parser === "flow") {
|
||||
if (
|
||||
options.parser === "typescript" ||
|
||||
options.parser === "flow" ||
|
||||
options.parser === "espree"
|
||||
) {
|
||||
includeShebang(ast, options);
|
||||
}
|
||||
|
||||
// Keep Babel's non-standard ParenthesizedExpression nodes only if they have Closure-style type cast comments.
|
||||
if (options.parser !== "typescript" && options.parser !== "flow") {
|
||||
if (
|
||||
options.parser !== "typescript" &&
|
||||
options.parser !== "flow" &&
|
||||
options.parser !== "espree"
|
||||
) {
|
||||
const startOffsetsOfTypeCastedNodes = new Set();
|
||||
|
||||
// Comments might be attached not directly to ParenthesizedExpression but to its ancestor.
|
||||
@@ -48,6 +56,10 @@ function postprocess(ast, options) {
|
||||
|
||||
ast = visitNode(ast, (node) => {
|
||||
switch (node.type) {
|
||||
// Espree
|
||||
case "ChainExpression": {
|
||||
return transformChainExpression(node.expression);
|
||||
}
|
||||
case "LogicalExpression": {
|
||||
// We remove unneeded parens around same-operator LogicalExpressions
|
||||
if (isUnbalancedLogicalTree(node)) {
|
||||
@@ -126,6 +138,21 @@ function postprocess(ast, options) {
|
||||
}
|
||||
}
|
||||
|
||||
// This is a workaround to transform `ChainExpression` from `espree` into
|
||||
// `babel` shape AST, we should do the opposite, since `ChainExpression` is the
|
||||
// standard `estree` AST for `optional chaining`
|
||||
// https://github.com/estree/estree/blob/master/es2020.md
|
||||
function transformChainExpression(node) {
|
||||
if (node.type === "CallExpression") {
|
||||
node.type = "OptionalCallExpression";
|
||||
node.callee = transformChainExpression(node.callee);
|
||||
} else if (node.type === "MemberExpression") {
|
||||
node.type = "OptionalMemberExpression";
|
||||
node.object = transformChainExpression(node.object);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function visitNode(node, fn) {
|
||||
let entries;
|
||||
|
||||
|
||||
@@ -927,7 +927,7 @@ function returnArgumentHasLeadingComment(options, argument) {
|
||||
//
|
||||
// Angular does not support unquoted numbers in expressions.
|
||||
//
|
||||
// So we play it safe and only unquote numbers for the "babel" parser.
|
||||
// So we play it safe and only unquote numbers for the JavaScript parsers.
|
||||
// (Vue supports unquoted numbers in expressions, but let’s keep it simple.)
|
||||
//
|
||||
// Identifiers can be unquoted in more circumstances, though.
|
||||
@@ -945,7 +945,7 @@ function isStringPropSafeToUnquote(node, options) {
|
||||
)) ||
|
||||
(isSimpleNumber(node.key.value) &&
|
||||
String(Number(node.key.value)) === node.key.value &&
|
||||
options.parser === "babel"))
|
||||
(options.parser === "babel" || options.parser === "espree")))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ const options = {
|
||||
{ value: "babel-flow", since: "1.16.0", description: "Flow" },
|
||||
{ value: "babel-ts", since: "2.0.0", description: "TypeScript" },
|
||||
{ value: "typescript", since: "1.4.0", description: "TypeScript" },
|
||||
{ value: "espree", since: "2.2.0", description: "JavaScript" },
|
||||
{ value: "css", since: "1.7.1", description: "CSS" },
|
||||
{ value: "less", since: "1.7.1", description: "Less" },
|
||||
{ value: "scss", since: "1.7.1", description: "SCSS" },
|
||||
|
||||
@@ -119,6 +119,7 @@ function isSourceElement(opts, node) {
|
||||
case "babel-flow":
|
||||
case "babel-ts":
|
||||
case "typescript":
|
||||
case "espree":
|
||||
return isJsSourceElement(node.type);
|
||||
case "json":
|
||||
return jsonSourceElements.has(node.type);
|
||||
|
||||
Reference in new issue
Block a user