Skip to content

Commit

Permalink
Simplify JS parser handling Hashbang (#10407)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed Mar 22, 2021
1 parent be0bbd1 commit 199be1a
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 33 deletions.
21 changes: 0 additions & 21 deletions src/language-js/parse-postprocess.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,12 @@
const {
getLast,
getNextNonSpaceNonCommentCharacter,
getShebang,
} = require("../common/util");
const createError = require("../common/parser-create-error");
const { locStart, locEnd } = require("./loc");
const { isTypeCastComment } = require("./comments");

function postprocess(ast, options) {
if (
options.parser === "typescript" ||
options.parser === "flow" ||
options.parser === "espree"
) {
includeShebang(ast, options);
}

// Invalid decorators are removed since `@typescript-eslint/typescript-estree` v4
// https://github.com/typescript-eslint/typescript-eslint/pull/2375
if (options.parser === "typescript" && options.originalText.includes("@")) {
Expand Down Expand Up @@ -256,16 +247,4 @@ function rebalanceLogicalTree(node) {
});
}

function includeShebang(ast, options) {
const shebang = getShebang(options.originalText);

if (shebang) {
ast.comments.unshift({
type: "Line",
value: shebang.slice(2),
range: [0, shebang.length],
});
}
}

module.exports = postprocess;
13 changes: 4 additions & 9 deletions src/language-js/parser-espree.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use strict";
const { getShebang } = require("../common/util");
const createError = require("../common/parser-create-error");
const tryCombinations = require("../utils/try-combinations");
const postprocess = require("./parse-postprocess");
const createParser = require("./parser/create-parser");
const replaceHashbang = require("./parser/replace-hashbang");

const parseOptions = {
range: true,
Expand Down Expand Up @@ -33,15 +33,10 @@ function parse(originalText, parsers, options) {
const { parse, latestEcmaVersion } = require("espree");
parseOptions.ecmaVersion = latestEcmaVersion;

// Replace shebang with space
const shebang = getShebang(originalText);
const text = shebang
? " ".repeat(shebang.length) + originalText.slice(shebang.length)
: originalText;

const textToParse = replaceHashbang(originalText);
const { result: ast, error: moduleParseError } = tryCombinations(
() => parse(text, { ...parseOptions, sourceType: "module" }),
() => parse(text, { ...parseOptions, sourceType: "script" })
() => parse(textToParse, { ...parseOptions, sourceType: "module" }),
() => parse(textToParse, { ...parseOptions, sourceType: "script" })
);

if (!ast) {
Expand Down
3 changes: 2 additions & 1 deletion src/language-js/parser-flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const createError = require("../common/parser-create-error");
const postprocess = require("./parse-postprocess");
const createParser = require("./parser/create-parser");
const replaceHashbang = require("./parser/replace-hashbang");

// https://github.com/facebook/flow/tree/master/packages/flow-parser#options
const parseOptions = {
Expand Down Expand Up @@ -47,7 +48,7 @@ function createParseError(error) {
function parse(text, parsers, opts) {
// Inline the require to avoid loading all the JS if we don't use it
const { parse } = require("flow-parser");
const ast = parse(text, parseOptions);
const ast = parse(replaceHashbang(text), parseOptions);
const [error] = ast.errors;
if (error) {
throw createParseError(error);
Expand Down
6 changes: 4 additions & 2 deletions src/language-js/parser-typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const createError = require("../common/parser-create-error");
const tryCombinations = require("../utils/try-combinations");
const postprocess = require("./parse-postprocess");
const createParser = require("./parser/create-parser");
const replaceHashbang = require("./parser/replace-hashbang");

/** @type {import("@typescript-eslint/typescript-estree").TSESTreeOptions} */
const parseOptions = {
Expand Down Expand Up @@ -33,14 +34,15 @@ function createParseError(error) {
}

function parse(text, parsers, opts) {
const textToParse = replaceHashbang(text);
const jsx = isProbablyJsx(text);

const { parseWithNodeMaps } = require("@typescript-eslint/typescript-estree");
const { result, error: firstError } = tryCombinations(
// Try passing with our best guess first.
() => parseWithNodeMaps(text, { ...parseOptions, jsx }),
() => parseWithNodeMaps(textToParse, { ...parseOptions, jsx }),
// But if we get it wrong, try the opposite.
() => parseWithNodeMaps(text, { ...parseOptions, jsx: !jsx })
() => parseWithNodeMaps(textToParse, { ...parseOptions, jsx: !jsx })
);

if (!result) {
Expand Down
13 changes: 13 additions & 0 deletions src/language-js/parser/replace-hashbang.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use strict";

// Replace `#!` with `//` so `typescript`, `flow`, and `espree` can parse it as line comment
// Inspired by ESLint parse function https://github.com/eslint/eslint/blob/9d6063add931f0803cae1676d5df307baf114360/lib/linter/linter.js#L635
function replaceHashbang(text) {
if (text.charAt(0) === "#" && text.charAt(1) === "!") {
return "//" + text.slice(2);
}

return text;
}

module.exports = replaceHashbang;

0 comments on commit 199be1a

Please sign in to comment.