Skip to content

Commit

Permalink
babel parser type improvements (#14801)
Browse files Browse the repository at this point in the history
  • Loading branch information
zxbodya committed Aug 3, 2022
1 parent 2a7a216 commit 8d17ae6
Show file tree
Hide file tree
Showing 19 changed files with 297 additions and 284 deletions.
1 change: 1 addition & 0 deletions packages/babel-parser/src/index.ts
Expand Up @@ -113,6 +113,7 @@ function getParserClass(pluginsFromOptions: PluginList): {
if (!cls) {
cls = Parser;
for (const plugin of pluginList) {
// @ts-expect-error todo(flow->ts)
cls = mixinPlugins[plugin](cls);
}
parserClassCache[key] = cls;
Expand Down
5 changes: 4 additions & 1 deletion packages/babel-parser/src/parser/comments.ts
Expand Up @@ -66,7 +66,10 @@ function setLeadingComments(node: Undone<Node>, comments: Array<Comment>) {
* @param {Undone<Node>} node
* @param {Array<Comment>} comments
*/
export function setInnerComments(node: Undone<Node>, comments: Array<Comment>) {
export function setInnerComments(
node: Undone<Node>,
comments?: Array<Comment>,
) {
if (node.innerComments === undefined) {
node.innerComments = comments;
} else {
Expand Down
49 changes: 26 additions & 23 deletions packages/babel-parser/src/parser/expression.ts
Expand Up @@ -60,6 +60,7 @@ import {
PARAM_RETURN,
functionFlags,
} from "../util/production-parameter";
import type { ParamKind } from "../util/production-parameter";
import {
newArrowHeadScope,
newAsyncArrowScope,
Expand All @@ -71,44 +72,44 @@ import { setInnerComments } from "./comments";
import { cloneIdentifier, type Undone } from "./node";
import type Parser from ".";

/*::
import type { SourceType } from "../options";
declare var invariant;
*/

export default class ExpressionParser extends LValParser {
export default abstract class ExpressionParser extends LValParser {
// Forward-declaration: defined in statement.js
/*::
+parseBlock: (
abstract parseBlock(
allowDirectives?: boolean,
createNewLexicalScope?: boolean,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
) => N.BlockStatement;
+parseClass: (
): N.BlockStatement;
abstract parseClass(
node: N.Class,
isStatement: boolean,
optionalId?: boolean,
) => N.Class;
+parseDecorators: (allowExport?: boolean) => void;
+parseFunction: <T: N.NormalFunction>(
): N.Class;
abstract parseDecorators(allowExport?: boolean): void;
abstract parseFunction<T extends N.NormalFunction>(
node: T,
statement?: number,
allowExpressionBody?: boolean,
isAsync?: boolean,
) => T;
+parseFunctionParams: (node: N.Function, allowModifiers?: boolean) => void;
+takeDecorators: (node: N.HasDecorators) => void;
+parseBlockOrModuleBlockBody: (
): T;
abstract parseFunctionParams(
node: N.Function,
allowModifiers?: boolean,
): void;
abstract takeDecorators(node: N.HasDecorators): void;
abstract parseBlockOrModuleBlockBody(
body: N.Statement[],
directives: ?(N.Directive[]),
directives: N.Directive[] | null | undefined,
topLevel: boolean,
end: TokenType,
afterBlockParse?: (hasStrictModeDirective: boolean) => void
) => void
+parseProgram: (
program: N.Program, end: TokenType, sourceType?: SourceType
) => N.Program
*/
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
): void;
abstract parseProgram(
program: N.Program,
end: TokenType,
sourceType?: SourceType,
): N.Program;

// For object literal, check if property __proto__ has been used more than once.
// If the expression is a destructuring assignment, then __proto__ may appear
Expand Down Expand Up @@ -2629,7 +2630,9 @@ export default class ExpressionParser extends LValParser {

// FunctionBody[Yield, Await]:
// StatementList[?Yield, ?Await, +Return] opt
this.prodParam.enter(this.prodParam.currentFlags() | PARAM_RETURN);
this.prodParam.enter(
(this.prodParam.currentFlags() | PARAM_RETURN) as ParamKind,
);
node.body = this.parseBlock(
true,
false,
Expand Down
19 changes: 9 additions & 10 deletions packages/babel-parser/src/parser/index.ts
@@ -1,5 +1,5 @@
import type { Options } from "../options";
import type { File, Program /*::, JSXOpeningElement */ } from "../types";
import type * as N from "../types";
import type { PluginList } from "../plugin-utils";
import { getOptions } from "../options";
import StatementParser from "./statement";
Expand All @@ -14,11 +14,10 @@ export type PluginsMap = Map<

export default class Parser extends StatementParser {
// Forward-declaration so typescript plugin can override jsx plugin
/*::
+jsxParseOpeningElementAfterName: (
node: JSXOpeningElement,
) => JSXOpeningElement;
*/
// todo(flow->ts) - this probably can be removed
// abstract jsxParseOpeningElementAfterName(
// node: N.JSXOpeningElement,
// ): N.JSXOpeningElement;

constructor(options: Options | undefined | null, input: string) {
options = getOptions(options);
Expand All @@ -32,15 +31,15 @@ export default class Parser extends StatementParser {

// This can be overwritten, for example, by the TypeScript plugin.
getScopeHandler(): {
new (...args: any): ScopeHandler<any>;
new (...args: any): ScopeHandler;
} {
return ScopeHandler;
}

parse(): File {
parse(): N.File {
this.enterInitialScopes();
const file = this.startNode() as File;
const program = this.startNode() as Program;
const file = this.startNode() as N.File;
const program = this.startNode() as N.Program;
this.nextToken();
file.errors = null;
this.parseTopLevel(file, program);
Expand Down
62 changes: 32 additions & 30 deletions packages/babel-parser/src/parser/lval.ts
@@ -1,4 +1,3 @@
/*:: declare var invariant; */
import * as charCodes from "charcodes";
import { tt, type TokenType } from "../tokenizer/types";
import type {
Expand All @@ -11,18 +10,17 @@ import type {
Pattern,
RestElement,
SpreadElement,
/*:: ObjectOrClassMember, */
/*:: ClassMember, */
ObjectOrClassMember,
ClassMember,
ObjectMember,
TsNamedTypeElementBase,
PrivateName,
ObjectExpression,
ObjectPattern,
ArrayExpression,
ArrayPattern,
/*:: TsNamedTypeElementBase, */
/*:: PrivateName, */
/*:: ObjectExpression, */
/*:: ObjectPattern, */
} from "../types";
import type { Position } from "../util/location";
import type { Pos, Position } from "../util/location";
import {
isStrictBindOnlyReservedWord,
isStrictBindReservedWord,
Expand All @@ -46,39 +44,43 @@ const unwrapParenthesizedExpression = (node: Node): Node => {
: node;
};

export default class LValParser extends NodeUtils {
export default abstract class LValParser extends NodeUtils {
// Forward-declaration: defined in expression.js
/*::
+parseIdentifier: (liberal?: boolean) => Identifier;
+parseMaybeAssignAllowIn: (
refExpressionErrors?: ?ExpressionErrors,
abstract parseIdentifier(liberal?: boolean): Identifier;
abstract parseMaybeAssign(
refExpressionErrors?: ExpressionErrors | null,
afterLeftParse?: Function,
refNeedsArrowPos?: Pos | null,
): Expression;

abstract parseMaybeAssignAllowIn(
refExpressionErrors?: ExpressionErrors | null,
afterLeftParse?: Function,
) => Expression;
+parseObjectLike: <T: ObjectPattern | ObjectExpression>(
refNeedsArrowPos?: Pos | null,
): Expression;

abstract parseObjectLike<T extends ObjectPattern | ObjectExpression>(
close: TokenType,
isPattern: boolean,
isRecord?: ?boolean,
refExpressionErrors?: ?ExpressionErrors,
) => T;
+parseObjPropValue: (
isRecord?: boolean,
refExpressionErrors?: ExpressionErrors,
): T;
abstract parseObjPropValue(
prop: any,
startPos: ?number,
startLoc: ?Position,
startPos: number | null,
startLoc: Position | null,
isGenerator: boolean,
isAsync: boolean,
isPattern: boolean,
isAccessor: boolean,
refExpressionErrors?: ?ExpressionErrors,
) => void;
+parsePropertyName: (
refExpressionErrors?: ExpressionErrors | null,
): void;
abstract parsePropertyName(
prop: ObjectOrClassMember | ClassMember | TsNamedTypeElementBase,
) => Expression | Identifier;
+parsePrivateName: () => PrivateName
*/
): Expression | Identifier;
abstract parsePrivateName(): PrivateName;
// Forward-declaration: defined in statement.js
/*::
+parseDecorator: () => Decorator;
*/
abstract parseDecorator(): Decorator;

/**
* Convert existing expression atom to assignable pattern
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/node.ts
Expand Up @@ -98,7 +98,7 @@ export function cloneStringLiteral(node: any): any {

export type Undone<T extends NodeType> = Omit<T, "type">;

export class NodeUtils extends UtilParser {
export abstract class NodeUtils extends UtilParser {
startNode<T extends NodeType>(): Undone<T> {
// @ts-expect-error
return new Node(this, this.state.start, this.state.startLoc);
Expand Down
17 changes: 6 additions & 11 deletions packages/babel-parser/src/parser/statement.ts
Expand Up @@ -184,7 +184,7 @@ function babel7CompatTokens(tokens: (Token | N.Comment)[], input: string) {
}
return tokens;
}
export default class StatementParser extends ExpressionParser {
export default abstract class StatementParser extends ExpressionParser {
// ### Statement parsing

// Parse a program. Initializes the parser, reads any number of
Expand Down Expand Up @@ -1627,16 +1627,11 @@ export default class StatementParser extends ExpressionParser {
state: N.ParseClassMemberState,
isStatic: boolean,
) {
// @ts-expect-error: Fixme: convert $FlowSubtype to TS
const publicMethod: $FlowSubtype<N.ClassMethod> = member;
// @ts-expect-error: Fixme: convert $FlowSubtype to TS
const privateMethod: $FlowSubtype<N.ClassPrivateMethod> = member;
// @ts-expect-error: Fixme: convert $FlowSubtype to TS
const publicProp: $FlowSubtype<N.ClassProperty> = member;
// @ts-expect-error: Fixme: convert $FlowSubtype to TS
const privateProp: $FlowSubtype<N.ClassPrivateProperty> = member;
// @ts-expect-error: Fixme: convert $FlowSubtype to TS
const accessorProp: $FlowSubtype<N.ClassAccessorProperty> = member;
const publicMethod = member as N.ClassMethod;
const privateMethod = member as N.ClassPrivateMethod;
const publicProp = member as N.ClassProperty;
const privateProp = member as N.ClassPrivateProperty;
const accessorProp = member as N.ClassAccessorProperty;

const method: typeof publicMethod | typeof privateMethod = publicMethod;
const publicMember: typeof publicMethod | typeof publicProp = publicMethod;
Expand Down
8 changes: 2 additions & 6 deletions packages/babel-parser/src/parser/util.ts
Expand Up @@ -23,9 +23,7 @@ import {
} from "../parse-error";
import type Parser from ".";

/*::
import type ScopeHandler from "../util/scope";
*/

type TryParse<Node, Error, Thrown, Aborted, FailState> = {
node: Node;
Expand All @@ -37,11 +35,9 @@ type TryParse<Node, Error, Thrown, Aborted, FailState> = {

// ## Parser utilities

export default class UtilParser extends Tokenizer {
export default abstract class UtilParser extends Tokenizer {
// Forward-declaration: defined in parser/index.js
/*::
+getScopeHandler: () => Class<ScopeHandler<*>>;
*/
abstract getScopeHandler(): { new (...args: any): ScopeHandler };

// TODO

Expand Down
4 changes: 1 addition & 3 deletions packages/babel-parser/src/plugin-utils.ts
Expand Up @@ -220,9 +220,7 @@ import placeholders from "./plugins/placeholders";
import v8intrinsic from "./plugins/v8intrinsic";

// NOTE: order is important. estree must come first; placeholders must come last.
export const mixinPlugins: {
[name: string]: MixinPlugin;
} = {
export const mixinPlugins = {
estree,
jsx,
flow,
Expand Down
36 changes: 19 additions & 17 deletions packages/babel-parser/src/plugins/estree.ts
Expand Up @@ -19,13 +19,8 @@ function toESTreeLocation(node: any) {
return node;
}

export default (superClass: {
new (...args: any): Parser;
}): {
new (...args: any): Parser;
} =>
// @ts-expect-error plugin may override interfaces
class extends superClass {
export default (superClass: typeof Parser) =>
class ESTreeParserMixin extends superClass implements Parser {
parse(): File {
const file = toESTreeLocation(super.parse());

Expand Down Expand Up @@ -124,7 +119,11 @@ export default (superClass: {
// @ts-expect-error N.Directive.value is not defined
stmt.directive = directiveLiteral.extra.raw.slice(1, -1);

return this.finishNodeAt(stmt, "ExpressionStatement", directive.loc.end);
return this.finishNodeAt(
stmt,
"ExpressionStatement",
directive.loc.end,
) as N.ExpressionStatement;
}

// ==================================
Expand Down Expand Up @@ -164,15 +163,18 @@ export default (superClass: {

parseBlockBody(
node: N.BlockStatementLike,
...args: [
boolean | undefined | null,
boolean,
TokenType,
void | ((a: boolean) => void),
]
allowDirectives: boolean | undefined | null,
topLevel: boolean,
end: TokenType,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
): void {
// @ts-expect-error figure out args typings
super.parseBlockBody(node, ...args);
super.parseBlockBody(
node,
allowDirectives,
topLevel,
end,
afterBlockParse,
);

const directiveStatements = node.directives.map(d =>
this.directiveToStmt(d),
Expand Down Expand Up @@ -486,7 +488,7 @@ export default (superClass: {
break;
}

return node;
return node as N.AnyExport;
}

parseSubscript(
Expand Down

0 comments on commit 8d17ae6

Please sign in to comment.