Skip to content

Commit

Permalink
[babel 8] Use @babel/types for parser's return type
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Feb 7, 2025
1 parent 48d915c commit 17d82a2
Show file tree
Hide file tree
Showing 13 changed files with 307 additions and 373 deletions.
1 change: 1 addition & 0 deletions Gulpfile.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ function buildRollupDts(packages) {
"packages/babel-parser/typings/babel-parser.source.d.ts",
"packages/babel-parser/typings/babel-parser.d.ts",
"// This file is auto-generated! Do not modify it directly.\n" +
"// Run `yarn gulp bundle-dts` to re-generate it.\n" +
// @typescript-eslint/no-redundant-type-constituents can be removed once we drop the IF_BABEL_7 type
"/* eslint-disable @typescript-eslint/consistent-type-imports, @typescript-eslint/no-redundant-type-constituents */",
"packages/babel-parser"
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/src/parser/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Handler } from "gensync";
import { parse, type File as ParseResult } from "@babel/parser";
import { parse, type ParseResult } from "@babel/parser";
import { codeFrameColumns } from "@babel/code-frame";
import generateMissingPluginMessage from "./util/missing-plugin-helper.ts";
import type { PluginPasses } from "../config/index.ts";
Expand Down
3 changes: 1 addition & 2 deletions packages/babel-core/src/transformation/normalize-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export default function* normalizeFile(
ast = cloneDeep(ast);
}
} else {
// @ts-expect-error todo: use babel-types ast typings in Babel parser
ast = yield* parser(pluginPasses, options, code);
}

Expand Down Expand Up @@ -101,7 +100,7 @@ export default function* normalizeFile(

return new File(options, {
code,
ast: ast as t.File,
ast: ast,
inputMap,
});
}
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"conditions": {
"BABEL_8_BREAKING": [
{
"types": null,
"engines": {
"node": "^18.20.0 || ^20.17.0 || >=22.8.0"
}
Expand Down
59 changes: 40 additions & 19 deletions packages/babel-parser/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import {
mixinPluginNames,
mixinPlugins,
} from "./plugin-utils.ts";
import type {
export type {
PluginConfig as ParserPlugin,
DecoratorsPluginOptions,
FlowPluginOptions,
RecordAndTuplePluginOptions,
PipelineOperatorPluginOptions,
RecordAndTuplePluginOptions,
TypeScriptPluginOptions,
} from "./typings.ts";
import Parser, { type PluginsMap } from "./parser/index.ts";

Expand All @@ -20,10 +22,28 @@ import {
} from "./tokenizer/types.ts";
export type { Token } from "./tokenizer/index.ts";

import type { Expression, File } from "./types.ts";
// TODO: Rather than type-casting the internal AST definitions to the
// @babel/types one, we should actually unify them.
import type { Expression, File } from "@babel/types";
export type { Expression, File };

export function parse(input: string, options?: Options): File {
export type ParserOptions = Partial<Options>;

export interface ParseError {
code: string;
reasonCode: string;
}
export type ParseResult<Result extends File | Expression = File> = Result & {
errors: null | ParseError[];
};

/**
* Parse the provided code as an entire ECMAScript program.
*/
export function parse(
input: string,
options?: ParserOptions,
): ParseResult<File> {
if (options?.sourceType === "unambiguous") {
options = {
...options,
Expand All @@ -34,7 +54,7 @@ export function parse(input: string, options?: Options): File {
const ast = parser.parse();

if (parser.sawUnambiguousESM) {
return ast;
return ast as unknown as ParseResult<File>;
}

if (parser.ambiguousScriptDifferentAst) {
Expand All @@ -45,34 +65,43 @@ export function parse(input: string, options?: Options): File {
// can be parsed either as an AwaitExpression, or as two ExpressionStatements.
try {
options.sourceType = "script";
return getParser(options, input).parse();
return getParser(
options,
input,
).parse() as unknown as ParseResult<File>;
} catch {}
} else {
// This is both a valid module and a valid script, but
// we parse it as a script by default
ast.program.sourceType = "script";
}

return ast;
return ast as unknown as ParseResult<File>;
} catch (moduleError) {
try {
options.sourceType = "script";
return getParser(options, input).parse();
return getParser(
options,
input,
).parse() as unknown as ParseResult<File>;
} catch {}

throw moduleError;
}
} else {
return getParser(options, input).parse();
return getParser(options, input).parse() as unknown as ParseResult<File>;
}
}

export function parseExpression(input: string, options?: Options): Expression {
export function parseExpression(
input: string,
options?: ParserOptions,
): ParseResult<Expression> {
const parser = getParser(options, input);
if (parser.options.strictMode) {
parser.state.strict = true;
}
return parser.getExpression();
return parser.getExpression() as unknown as ParseResult<Expression>;
}

function generateExportedTokenTypes(
Expand Down Expand Up @@ -135,11 +164,3 @@ function getParserClass(
}
return cls;
}

export type {
FlowPluginOptions,
ParserPlugin,
PipelineOperatorPluginOptions,
RecordAndTuplePluginOptions,
};
export type ParserOptions = Partial<Options>;
133 changes: 120 additions & 13 deletions packages/babel-parser/src/options.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,138 @@
import type { PluginList } from "./plugin-utils.ts";
import type { Plugin } from "./plugin-utils.ts";

// A second optional argument can be given to further configure
// the parser process. These options are recognized:

export type SourceType = "script" | "module" | "unambiguous";

export interface Options {
sourceType?: SourceType;
sourceFilename?: string;
startIndex?: number;
startColumn?: number;
startLine?: number;
/**
* By default, import and export declarations can only appear at a program's top level.
* Setting this option to true allows them anywhere where a statement is allowed.
*/
allowImportExportEverywhere?: boolean;

/**
* By default, await use is not allowed outside of an async function.
* Set this to true to accept such code.
*/
allowAwaitOutsideFunction?: boolean;

/**
* By default, a return statement at the top level raises an error.
* Set this to true to accept such code.
*/
allowReturnOutsideFunction?: boolean;

/**
* By default, new.target use is not allowed outside of a function or class.
* Set this to true to accept such code.
*/
allowNewTargetOutsideFunction?: boolean;
allowImportExportEverywhere?: boolean;

allowSuperOutsideMethod?: boolean;

/**
* By default, exported identifiers must refer to a declared variable.
* Set this to true to allow export statements to reference undeclared variables.
*/
allowUndeclaredExports?: boolean;
plugins?: PluginList;
strictMode?: boolean | undefined | null;

/**
* By default, Babel parser JavaScript code according to Annex B syntax.
* Set this to `false` to disable such behavior.
*/
annexB?: boolean;

/**
* By default, Babel attaches comments to adjacent AST nodes.
* When this option is set to false, comments are not attached.
* It can provide up to 30% performance improvement when the input code has many comments.
* @babel/eslint-parser will set it for you.
* It is not recommended to use attachComment: false with Babel transform,
* as doing so removes all the comments in output code, and renders annotations such as
* /* istanbul ignore next *\/ nonfunctional.
*/
attachComment?: boolean;

/**
* By default, Babel always throws an error when it finds some invalid code.
* When this option is set to true, it will store the parsing error and
* try to continue parsing the invalid input file.
*/
errorRecovery?: boolean;

/**
* Indicate the mode the code should be parsed in.
* Can be one of "script", "module", or "unambiguous". Defaults to "script".
* "unambiguous" will make @babel/parser attempt to guess, based on the presence
* of ES6 import or export statements.
* Files with ES6 imports and exports are considered "module" and are otherwise "script".
*/
sourceType?: "script" | "module" | "unambiguous";

/**
* Correlate output AST nodes with their source filename.
* Useful when generating code and source maps from the ASTs of multiple input files.
*/
sourceFilename?: string;

/**
* By default, all source indexes start from 0.
* You can provide a start index to alternatively start with.
* Useful for integration with other source tools.
*/
startIndex?: number;

/**
* By default, the first line of code parsed is treated as line 1.
* You can provide a line number to alternatively start with.
* Useful for integration with other source tools.
*/
startLine?: number;

/**
* By default, the parsed code is treated as if it starts from line 1, column 0.
* You can provide a column number to alternatively start with.
* Useful for integration with other source tools.
*/
startColumn?: number;

/**
* Array containing the plugins that you want to enable.
*/
plugins?: Plugin[];

/**
* Should the parser work in strict mode.
* Defaults to true if sourceType === 'module'. Otherwise, false.
*/
strictMode?: boolean;

/**
* Adds a ranges property to each node: [node.start, node.end]
*/
ranges?: boolean;

/**
* Adds all parsed tokens to a tokens property on the File node.
*/
tokens?: boolean;
createImportExpressions?: boolean;

/**
* By default, the parser adds information about parentheses by setting
* `extra.parenthesized` to `true` as needed.
* When this option is `true` the parser creates `ParenthesizedExpression`
* AST nodes instead of using the `extra` property.
*/
createParenthesizedExpressions?: boolean;
errorRecovery?: boolean;
attachComment?: boolean;
annexB?: boolean;

/**
* The default is false in Babel 7 and true in Babel 8
* Set this to true to parse it as an `ImportExpression` node.
* Otherwise `import(foo)` is parsed as `CallExpression(Import, [Identifier(foo)])`.
*/
createImportExpressions?: boolean;
}

export const enum OptionFlags {
Expand Down
2 changes: 0 additions & 2 deletions packages/babel-parser/src/plugin-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import type { PluginConfig } from "./typings.ts";

export type Plugin = PluginConfig;

export type PluginList = PluginConfig[];

export type MixinPlugin = (
superClass: new (...args: any) => Parser,
) => new (...args: any) => Parser;
Expand Down
3 changes: 1 addition & 2 deletions packages/babel-parser/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"./src/**/*.ts",
"./src/**/*.cts",
"../../lib/globals.d.ts",
"../../scripts/repo-utils/*.d.ts",
"../../packages/babel-parser/typings/*.d.ts"
"../../scripts/repo-utils/*.d.ts"
],
"references": [
{
Expand Down
Loading

0 comments on commit 17d82a2

Please sign in to comment.