diff --git a/packages/babel-parser/src/index.ts b/packages/babel-parser/src/index.ts index 301dd1391e07..286d7ff04621 100644 --- a/packages/babel-parser/src/index.ts +++ b/packages/babel-parser/src/index.ts @@ -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; diff --git a/packages/babel-parser/src/parser/comments.ts b/packages/babel-parser/src/parser/comments.ts index 2d972e5b3998..04e7261c8961 100644 --- a/packages/babel-parser/src/parser/comments.ts +++ b/packages/babel-parser/src/parser/comments.ts @@ -66,7 +66,10 @@ function setLeadingComments(node: Undone, comments: Array) { * @param {Undone} node * @param {Array} comments */ -export function setInnerComments(node: Undone, comments: Array) { +export function setInnerComments( + node: Undone, + comments?: Array, +) { if (node.innerComments === undefined) { node.innerComments = comments; } else { diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts index 3fbf43f7a9bc..13ea7160dfa0 100644 --- a/packages/babel-parser/src/parser/expression.ts +++ b/packages/babel-parser/src/parser/expression.ts @@ -60,6 +60,7 @@ import { PARAM_RETURN, functionFlags, } from "../util/production-parameter"; +import type { ParamKind } from "../util/production-parameter"; import { newArrowHeadScope, newAsyncArrowScope, @@ -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: ( + ): N.Class; + abstract parseDecorators(allowExport?: boolean): void; + abstract parseFunction( 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 @@ -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, diff --git a/packages/babel-parser/src/parser/index.ts b/packages/babel-parser/src/parser/index.ts index 776449a899f5..45a32903fdc2 100644 --- a/packages/babel-parser/src/parser/index.ts +++ b/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"; @@ -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); @@ -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; + 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); diff --git a/packages/babel-parser/src/parser/lval.ts b/packages/babel-parser/src/parser/lval.ts index 0432891c0692..d030d6cc726b 100644 --- a/packages/babel-parser/src/parser/lval.ts +++ b/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 { @@ -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, @@ -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: ( + refNeedsArrowPos?: Pos | null, + ): Expression; + + abstract parseObjectLike( 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 diff --git a/packages/babel-parser/src/parser/node.ts b/packages/babel-parser/src/parser/node.ts index 360ed707f6e0..293b46675986 100644 --- a/packages/babel-parser/src/parser/node.ts +++ b/packages/babel-parser/src/parser/node.ts @@ -98,7 +98,7 @@ export function cloneStringLiteral(node: any): any { export type Undone = Omit; -export class NodeUtils extends UtilParser { +export abstract class NodeUtils extends UtilParser { startNode(): Undone { // @ts-expect-error return new Node(this, this.state.start, this.state.startLoc); diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index d73f064f12ca..552b634c77a6 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -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 @@ -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 = member; - // @ts-expect-error: Fixme: convert $FlowSubtype to TS - const privateMethod: $FlowSubtype = member; - // @ts-expect-error: Fixme: convert $FlowSubtype to TS - const publicProp: $FlowSubtype = member; - // @ts-expect-error: Fixme: convert $FlowSubtype to TS - const privateProp: $FlowSubtype = member; - // @ts-expect-error: Fixme: convert $FlowSubtype to TS - const accessorProp: $FlowSubtype = 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; diff --git a/packages/babel-parser/src/parser/util.ts b/packages/babel-parser/src/parser/util.ts index a7186f513ffe..b78ccacaf466 100644 --- a/packages/babel-parser/src/parser/util.ts +++ b/packages/babel-parser/src/parser/util.ts @@ -23,9 +23,7 @@ import { } from "../parse-error"; import type Parser from "."; -/*:: import type ScopeHandler from "../util/scope"; -*/ type TryParse = { node: Node; @@ -37,11 +35,9 @@ type TryParse = { // ## Parser utilities -export default class UtilParser extends Tokenizer { +export default abstract class UtilParser extends Tokenizer { // Forward-declaration: defined in parser/index.js - /*:: - +getScopeHandler: () => Class>; - */ + abstract getScopeHandler(): { new (...args: any): ScopeHandler }; // TODO diff --git a/packages/babel-parser/src/plugin-utils.ts b/packages/babel-parser/src/plugin-utils.ts index b2d1cc17bf9c..4421b24bba55 100644 --- a/packages/babel-parser/src/plugin-utils.ts +++ b/packages/babel-parser/src/plugin-utils.ts @@ -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, diff --git a/packages/babel-parser/src/plugins/estree.ts b/packages/babel-parser/src/plugins/estree.ts index 6712756457db..94ed4f143e31 100644 --- a/packages/babel-parser/src/plugins/estree.ts +++ b/packages/babel-parser/src/plugins/estree.ts @@ -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()); @@ -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; } // ================================== @@ -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), @@ -486,7 +488,7 @@ export default (superClass: { break; } - return node; + return node as N.AnyExport; } parseSubscript( diff --git a/packages/babel-parser/src/plugins/flow/index.ts b/packages/babel-parser/src/plugins/flow/index.ts index e46b2f3cb073..6114a7a0e1a3 100644 --- a/packages/babel-parser/src/plugins/flow/index.ts +++ b/packages/babel-parser/src/plugins/flow/index.ts @@ -304,12 +304,8 @@ type EnumMemberInit = loc: Position; }; -export default (superClass: { - new (...args: any): Parser; -}): { - new (...args: any): Parser; -} => - class extends superClass { +export default (superClass: typeof Parser) => + class FlowParserMixin extends superClass implements Parser { // The value of the @flow/@noflow pragma. Initially undefined, transitions // to "@flow" or "@noflow" if we see a pragma. Transitions to null if we are // past the initial comment. @@ -2492,8 +2488,11 @@ export default (superClass: { return node; } - isValidLVal(type: string, ...rest: [boolean, BindingTypes]) { - return type === "TypeCastExpression" || super.isValidLVal(type, ...rest); + isValidLVal(type: string, isParenthesized: boolean, binding: BindingTypes) { + return ( + type === "TypeCastExpression" || + super.isValidLVal(type, isParenthesized, binding) + ); } // parse class property type annotations @@ -3131,6 +3130,7 @@ export default (superClass: { node: N.Function, allowDuplicates: boolean, isArrowFunction?: boolean | null, + strictModeChanged: boolean = true, ): void { if ( isArrowFunction && @@ -3146,7 +3146,12 @@ export default (superClass: { } } - return super.checkParams(node, allowDuplicates, isArrowFunction); + return super.checkParams( + node, + allowDuplicates, + isArrowFunction, + strictModeChanged, + ); } parseParenAndDistinguishExpression(canBeArrow: boolean): N.Expression { @@ -3341,7 +3346,7 @@ export default (superClass: { return fileNode; } - skipBlockComment(): N.CommentBlock | void { + skipBlockComment(): N.CommentBlock | undefined { if (this.hasPlugin("flowComments") && this.skipFlowComment()) { if (this.state.hasFlowComment) { throw this.raise(FlowErrors.NestedFlowComment, { @@ -3522,8 +3527,7 @@ export default (superClass: { const id = this.parseIdentifier(true); const init = this.eat(tt.eq) ? this.flowEnumMemberInit() - : { type: "none", loc }; - // @ts-expect-error: fixme + : { type: "none" as const, loc }; return { id, init }; } diff --git a/packages/babel-parser/src/plugins/jsx/index.ts b/packages/babel-parser/src/plugins/jsx/index.ts index c4e42fecf9c4..60991e05c5ea 100644 --- a/packages/babel-parser/src/plugins/jsx/index.ts +++ b/packages/babel-parser/src/plugins/jsx/index.ts @@ -77,12 +77,14 @@ function getQualifiedJSXName( throw new Error("Node had unexpected type: " + object.type); } -export default (superClass: { - new (...args: any): Parser; -}): { - new (...args: any): Parser; -} => - class extends superClass { +export interface IJSXParserMixin { + jsxParseOpeningElementAfterName( + node: N.JSXOpeningElement, + ): N.JSXOpeningElement; +} + +export default (superClass: typeof Parser) => + class JSXParserMixin extends superClass implements Parser, IJSXParserMixin { // Reads inline JSX contents token. jsxReadToken(): void { diff --git a/packages/babel-parser/src/plugins/jsx/xhtml.ts b/packages/babel-parser/src/plugins/jsx/xhtml.ts index d5f80397204e..13205f0cfe79 100644 --- a/packages/babel-parser/src/plugins/jsx/xhtml.ts +++ b/packages/babel-parser/src/plugins/jsx/xhtml.ts @@ -256,5 +256,5 @@ const entities: { clubs: "\u2663", hearts: "\u2665", diams: "\u2666", -}; +} as const; export default entities; diff --git a/packages/babel-parser/src/plugins/placeholders.ts b/packages/babel-parser/src/plugins/placeholders.ts index bee82d3e16a0..dbe7cdca9660 100644 --- a/packages/babel-parser/src/plugins/placeholders.ts +++ b/packages/babel-parser/src/plugins/placeholders.ts @@ -5,50 +5,27 @@ import type Parser from "../parser"; import * as N from "../types"; import { ParseErrorEnum } from "../parse-error"; import type { Undone } from "../parser/node"; +import type { ExpressionErrors } from "../parser/util"; +import type { BindingTypes } from "../util/scopeflags"; import type { Position } from "../util/location"; -type $Call1 any, A> = F extends ( - a: A, - ...args: any -) => infer R - ? R - : never; - -export type PlaceholderTypes = - | "Identifier" - | "StringLiteral" - | "Expression" - | "Statement" - | "Declaration" - | "BlockStatement" - | "ClassBody" - | "Pattern"; - -// $PropertyType doesn't support enums. Use a fake "switch" (GetPlaceholderNode) -//type MaybePlaceholder = $PropertyType | N.Placeholder; - -type _Switch = $Call1< - // @ts-expect-error Fixme broken fake switch - (a: Cases[Index][0]) => Cases[Index][1], - Value ->; - -type $Switch = _Switch; -type NodeOf = $Switch< - T, - [ - ["Identifier", N.Identifier], - ["StringLiteral", N.StringLiteral], - ["Expression", N.Expression], - ["Statement", N.Statement], - ["Declaration", N.Declaration], - ["BlockStatement", N.BlockStatement], - ["ClassBody", N.ClassBody], - ["Pattern", N.Pattern], - ] ->; - -// Placeholder breaks everything, because its type is incompatible with +type PossiblePlaceholedrs = { + Identifier: N.Identifier; + StringLiteral: N.StringLiteral; + Expression: N.Expression; + Statement: N.Statement; + Declaration: N.Declaration; + BlockStatement: N.BlockStatement; + ClassBody: N.ClassBody; + Pattern: N.Pattern; +}; +export type PlaceholderTypes = keyof PossiblePlaceholedrs; + +type NodeOf = PossiblePlaceholedrs[T]; +// todo: when there is proper union type for Node +// type NodeOf = Extract; + +// todo: Placeholder breaks everything, because its type is incompatible with // the substituted nodes. type MaybePlaceholder = NodeOf; // | Placeholder @@ -60,13 +37,8 @@ const PlaceholderErrors = ParseErrorEnum`placeholders`({ /* eslint-disable sort-keys */ -export default (superClass: { - new (...args: any): Parser; -}): { - new (...args: any): Parser; -} => - // @ts-expect-error Plugin will override parser interface - class extends superClass { +export default (superClass: typeof Parser) => + class PlaceholdersParserMixin extends superClass implements Parser { parsePlaceholder( expectedNode: T, ): /*?N.Placeholder*/ MaybePlaceholder | undefined | null { @@ -93,6 +65,7 @@ export default (superClass: { const isFinished = !!(node.expectedNode && node.type === "Placeholder"); node.expectedNode = expectedNode; + // @ts-expect-error todo(flow->ts) return isFinished ? node : this.finishNode(node, "Placeholder"); } @@ -107,29 +80,30 @@ export default (superClass: { ) { return this.finishOp(tt.placeholder, 2); } - // @ts-expect-error placeholder typings - return super.getTokenFromCode(...arguments); + + return super.getTokenFromCode(code); } /* ============================================================ * * parser/expression.js * * ============================================================ */ - parseExprAtom(): MaybePlaceholder<"Expression"> { + parseExprAtom( + refExpressionErrors?: ExpressionErrors | null, + ): MaybePlaceholder<"Expression"> { return ( - this.parsePlaceholder("Expression") || super.parseExprAtom(...arguments) + this.parsePlaceholder("Expression") || + super.parseExprAtom(refExpressionErrors) ); } - // @ts-expect-error Plugin will override parser interface - parseIdentifier(): MaybePlaceholder<"Identifier"> { + parseIdentifier(liberal?: boolean): MaybePlaceholder<"Identifier"> { // NOTE: This function only handles identifiers outside of // expressions and binding patterns, since they are already // handled by the parseExprAtom and parseBindingAtom functions. // This is needed, for example, to parse "class %%NAME%% {}". return ( - this.parsePlaceholder("Identifier") || - super.parseIdentifier(...arguments) + this.parsePlaceholder("Identifier") || super.parseIdentifier(liberal) ); } @@ -138,7 +112,7 @@ export default (superClass: { startLoc: Position, checkKeywords: boolean, isBinding: boolean, - ): void { + ) { // Sometimes we call #checkReservedWord(node.name), expecting // that node is an Identifier. If it is a Placeholder, name // will be undefined. @@ -151,14 +125,15 @@ export default (superClass: { * parser/lval.js * * ============================================================ */ - // @ts-expect-error Plugin will override parser interface parseBindingAtom(): MaybePlaceholder<"Pattern"> { return this.parsePlaceholder("Pattern") || super.parseBindingAtom(); } - // @ts-expect-error Plugin will override parser interface - isValidLVal(type: string, ...rest: [boolean, BindingTypes]) { - return type === "Placeholder" || super.isValidLVal(type, ...rest); + isValidLVal(type: string, isParenthesized: boolean, binding: BindingTypes) { + return ( + type === "Placeholder" || + super.isValidLVal(type, isParenthesized, binding) + ); } toAssignable(node: N.Node, isLHS: boolean): void { @@ -224,7 +199,6 @@ export default (superClass: { if (this.match(tt.colon)) { // @ts-expect-error const stmt: N.LabeledStatement = node; - // @ts-expect-error: Fixme: placeholder typings stmt.label = this.finishPlaceholder(expr, "Identifier"); this.next(); stmt.body = super.parseStatement("label"); @@ -232,22 +206,30 @@ export default (superClass: { } this.semicolon(); - // @ts-expect-error: Fixme: placeholder typings node.name = expr.name; return this.finishPlaceholder(node, "Statement"); } - // @ts-expect-error Plugin will override parser interface - parseBlock(): MaybePlaceholder<"BlockStatement"> { + + parseBlock( + allowDirectives?: boolean, + createNewLexicalScope?: boolean, + afterBlockParse?: (hasStrictModeDirective: boolean) => void, + ): MaybePlaceholder<"BlockStatement"> { return ( this.parsePlaceholder("BlockStatement") || - super.parseBlock(...arguments) + super.parseBlock( + allowDirectives, + createNewLexicalScope, + afterBlockParse, + ) ); } - // @ts-expect-error Plugin will override parser interface - parseFunctionId(): MaybePlaceholder<"Identifier"> | undefined | null { + + parseFunctionId( + requireId?: boolean, + ): MaybePlaceholder<"Identifier"> | undefined | null { return ( - this.parsePlaceholder("Identifier") || - super.parseFunctionId(...arguments) + this.parsePlaceholder("Identifier") || super.parseFunctionId(requireId) ); } // @ts-expect-error Plugin will override parser interface @@ -269,11 +251,9 @@ export default (superClass: { this.match(tt.placeholder) || this.match(tt.braceL) ) { - // @ts-expect-error: placeholder typings node.id = placeholder; } else if (optionalId || !isStatement) { node.id = null; - // @ts-expect-error: placeholder typings node.body = this.finishPlaceholder(placeholder, "ClassBody"); return this.finishNode(node, type); } else { @@ -286,17 +266,15 @@ export default (superClass: { } super.parseClassSuper(node); - // @ts-expect-error placeholder typings node.body = this.parsePlaceholder("ClassBody") || super.parseClassBody(!!node.superClass, oldStrict); return this.finishNode(node, type); } - // @ts-expect-error Plugin will override parser interface - parseExport(node: N.Node): N.Node { + + parseExport(node: N.Node): N.AnyExport { const placeholder = this.parsePlaceholder("Identifier"); - // @ts-expect-error placeholder typings - if (!placeholder) return super.parseExport(...arguments); + if (!placeholder) return super.parseExport(node); if (!this.isContextual(tt._from) && !this.match(tt.comma)) { // export %%DECL%%; @@ -356,14 +334,12 @@ export default (superClass: { node: Undone, ): N.ImportDeclaration | N.TsImportEqualsDeclaration { const placeholder = this.parsePlaceholder("Identifier"); - // @ts-expect-error placeholder typings - if (!placeholder) return super.parseImport(...arguments); + if (!placeholder) return super.parseImport(node); node.specifiers = []; if (!this.isContextual(tt._from) && !this.match(tt.comma)) { // import %%STRING%%; - // @ts-expect-error placeholder typings node.source = this.finishPlaceholder(placeholder, "StringLiteral"); this.semicolon(); return this.finishNode(node, "ImportDeclaration"); @@ -372,7 +348,6 @@ export default (superClass: { // import %%DEFAULT%% ... const specifier = this.startNodeAtNode(placeholder); - // @ts-expect-error placeholder typings specifier.local = placeholder; node.specifiers.push( this.finishNode(specifier, "ImportDefaultSpecifier"), @@ -387,20 +362,16 @@ export default (superClass: { } this.expectContextual(tt._from); - // @ts-expect-error placeholder typings node.source = this.parseImportSource(); this.semicolon(); return this.finishNode(node, "ImportDeclaration"); } - // @ts-expect-error placeholder typings parseImportSource(): MaybePlaceholder<"StringLiteral"> { // import ... from %%STRING%%; return ( - this.parsePlaceholder("StringLiteral") || - // @ts-expect-error placeholder typings - super.parseImportSource(...arguments) + this.parsePlaceholder("StringLiteral") || super.parseImportSource() ); } diff --git a/packages/babel-parser/src/plugins/typescript/index.ts b/packages/babel-parser/src/plugins/typescript/index.ts index 168fa575ef02..d00d1a2204b6 100644 --- a/packages/babel-parser/src/plugins/typescript/index.ts +++ b/packages/babel-parser/src/plugins/typescript/index.ts @@ -36,6 +36,9 @@ import type { ExpressionErrors } from "../../parser/util"; import { PARAM } from "../../util/production-parameter"; import { Errors, ParseErrorEnum } from "../../parse-error"; import { cloneIdentifier, type Undone } from "../../parser/node"; +import type { Pattern } from "../../types"; +import type { Expression } from "../../types"; +import type { IJSXParserMixin } from "../jsx"; const getOwn = (object: T, key: keyof T) => Object.hasOwnProperty.call(object, key) && object[key]; @@ -269,13 +272,15 @@ function tsIsVarianceAnnotations( return modifier === "in" || modifier === "out"; } -export default (superClass: { - new (...args: any): Parser; -}): { - new (...args: any): Parser; -} => - // @ts-expect-error plugin may override interfaces - class extends superClass { +type ClassWithMixin< + T extends new (...args: any) => any, + M extends object, +> = T extends new (...args: infer P) => infer I + ? new (...args: P) => I & M + : never; + +export default (superClass: ClassWithMixin) => + class TypeScriptParserMixin extends superClass implements Parser { getScopeHandler(): { new (...args: any): TypeScriptScopeHandler; } { @@ -2385,9 +2390,17 @@ export default (superClass: { } parseArrayLike( - ...args: [TokenType, boolean, boolean, ExpressionErrors | null] + close: TokenType, + canBePattern: boolean, + isTuple: boolean, + refExpressionErrors?: ExpressionErrors | null, ): N.ArrayExpression | N.TupleExpression { - const node = super.parseArrayLike(...args); + const node = super.parseArrayLike( + close, + canBePattern, + isTuple, + refExpressionErrors, + ); if (node.type === "ArrayExpression") { this.tsCheckForInvalidTypeCasts(node.elements); @@ -3087,6 +3100,8 @@ export default (superClass: { node: N.Class, isStatement: boolean, optionalId?: boolean | null, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + bindingType?: BindingTypes, ): void { if ((!isStatement || optionalId) && this.isContextual(tt._implements)) { return; @@ -3229,21 +3244,28 @@ export default (superClass: { } parseObjPropValue( - prop: Undone, - ...args: [ - number | undefined | null, - Position | undefined | null, - boolean, - boolean, - boolean, - boolean, - ExpressionErrors | null, - ] - ): N.ObjectMethod | N.ObjectProperty { + prop: Undone, + startPos: number | undefined | null, + startLoc: Position | undefined | null, + isGenerator: boolean, + isAsync: boolean, + isPattern: boolean, + isAccessor: boolean, + refExpressionErrors?: ExpressionErrors | null, + ) { const typeParameters = this.tsTryParseTypeParameters(); if (typeParameters) prop.typeParameters = typeParameters; - return super.parseObjPropValue(prop, ...args); + return super.parseObjPropValue( + prop, + startPos, + startLoc, + isGenerator, + isAsync, + isPattern, + isAccessor, + refExpressionErrors, + ); } parseFunctionParams(node: N.Function, allowModifiers?: boolean): void { @@ -3285,7 +3307,8 @@ export default (superClass: { } parseMaybeAssign( - ...args: [ExpressionErrors | null, Function] + refExpressionErrors?: ExpressionErrors | null, + afterLeftParse?: Function, ): N.Expression { // Note: When the JSX plugin is on, type assertions (` x`) aren't valid syntax. @@ -3300,7 +3323,10 @@ export default (superClass: { // Prefer to parse JSX if possible. But may be an arrow fn. state = this.state.clone(); - jsx = this.tryParse(() => super.parseMaybeAssign(...args), state); + jsx = this.tryParse( + () => super.parseMaybeAssign(refExpressionErrors, afterLeftParse), + state, + ); /*:: invariant(!jsx.aborted) */ /*:: invariant(jsx.node != null) */ @@ -3317,7 +3343,7 @@ export default (superClass: { } if (!jsx?.error && !this.match(tt.lt)) { - return super.parseMaybeAssign(...args); + return super.parseMaybeAssign(refExpressionErrors, afterLeftParse); } // Either way, we're looking at a '<': tt.jsxTagStart or relational. @@ -3331,7 +3357,10 @@ export default (superClass: { const arrow = this.tryParse(abort => { // This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`. typeParameters = this.tsParseTypeParameters(); - const expr = super.parseMaybeAssign(...args); + const expr = super.parseMaybeAssign( + refExpressionErrors, + afterLeftParse, + ); if ( expr.type !== "ArrowFunctionExpression" || @@ -3386,7 +3415,10 @@ export default (superClass: { // This will start with a type assertion (via parseMaybeUnary). // But don't directly call `this.tsParseTypeAssertion` because we want to handle any binary after it. - typeCast = this.tryParse(() => super.parseMaybeAssign(...args), state); + typeCast = this.tryParse( + () => super.parseMaybeAssign(refExpressionErrors, afterLeftParse), + state, + ); /*:: invariant(!typeCast.aborted) */ /*:: invariant(typeCast.node != null) */ if (!typeCast.error) return typeCast.node; @@ -3432,11 +3464,12 @@ export default (superClass: { // Handle type assertions parseMaybeUnary( refExpressionErrors?: ExpressionErrors | null, + sawUnary?: boolean, ): N.Expression { if (!this.hasPlugin("jsx") && this.match(tt.lt)) { return this.tsParseTypeAssertion(); } else { - return super.parseMaybeUnary(refExpressionErrors); + return super.parseMaybeUnary(refExpressionErrors, sawUnary); } } @@ -3639,13 +3672,11 @@ export default (superClass: { } parseMaybeDefault( - ...args: [ - startPos?: number | null, - startLoc?: Position | null, - left?: N.Pattern | null, - ] + startPos?: number | null, + startLoc?: Position | null, + left?: Pattern | null, ): N.Pattern { - const node = super.parseMaybeDefault(...args); + const node = super.parseMaybeDefault(startPos, startLoc, left); if ( node.type === "AssignmentPattern" && @@ -3696,8 +3727,9 @@ export default (superClass: { } toAssignableList( - exprList: N.Expression[], - ...args: [Position | undefined | null, boolean] + exprList: Expression[], + trailingCommaLoc: Position | undefined | null, + isLHS: boolean, ): void { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; @@ -3707,7 +3739,7 @@ export default (superClass: { ); } } - super.toAssignableList(exprList, ...args); + super.toAssignableList(exprList, trailingCommaLoc, isLHS); } typeCastToParameter(node: N.TsTypeCastExpression): N.Node { @@ -3746,7 +3778,6 @@ export default (superClass: { // @ts-expect-error: refine typings if (typeArguments) node.typeParameters = typeArguments; } - // @ts-expect-error calling JSX methods return super.jsxParseOpeningElementAfterName(node); } @@ -3785,12 +3816,13 @@ export default (superClass: { parseClass( node: Undone, - ...args: [boolean, boolean] + isStatement: boolean, + optionalId?: boolean, ): T { const oldInAbstractClass = this.state.inAbstractClass; this.state.inAbstractClass = !!(node as any).abstract; try { - return super.parseClass(node, ...args); + return super.parseClass(node, isStatement, optionalId); } finally { this.state.inAbstractClass = oldInAbstractClass; } @@ -3829,18 +3861,24 @@ export default (superClass: { parseMethod< T extends N.ObjectMethod | N.ClassMethod | N.ClassPrivateMethod, >( - ...args: [ - Undone, - boolean, - boolean, - boolean, - boolean, - T["type"], - boolean, - ] + node: Undone, + isGenerator: boolean, + isAsync: boolean, + isConstructor: boolean, + allowDirectSuper: boolean, + type: T["type"], + inClassScope?: boolean, ) { - const method = super.parseMethod(...args); - // @ts-expect-error abstract is not in ObjectMethod + const method = super.parseMethod( + node, + isGenerator, + isAsync, + isConstructor, + allowDirectSuper, + type, + inClassScope, + ); + // @ts-expect-error todo(flow->ts) property not defined for all types in union if (method.abstract) { const hasBody = this.hasPlugin("estree") ? // @ts-expect-error estree typings diff --git a/packages/babel-parser/src/plugins/v8intrinsic.ts b/packages/babel-parser/src/plugins/v8intrinsic.ts index c47fd7e2bdfd..4722b0bd6eff 100644 --- a/packages/babel-parser/src/plugins/v8intrinsic.ts +++ b/packages/babel-parser/src/plugins/v8intrinsic.ts @@ -1,14 +1,11 @@ import type Parser from "../parser"; import { tokenIsIdentifier, tt } from "../tokenizer/types"; import * as N from "../types"; +import type { ExpressionErrors } from "../parser/util"; -export default (superClass: { - new (...args: any): Parser; -}): { - new (...args: any): Parser; -} => - class extends superClass { - parseV8Intrinsic(): N.Expression | void { +export default (superClass: typeof Parser) => + class V8IntrinsicMixin extends superClass implements Parser { + parseV8Intrinsic(): N.Expression { if (this.match(tt.modulo)) { const v8IntrinsicStartLoc = this.state.startLoc; // let the `loc` of Identifier starts from `%` @@ -31,7 +28,9 @@ export default (superClass: { * parser/expression.js * * ============================================================ */ - parseExprAtom(): N.Expression { - return this.parseV8Intrinsic() || super.parseExprAtom(...arguments); + parseExprAtom(refExpressionErrors?: ExpressionErrors | null): N.Expression { + return ( + this.parseV8Intrinsic() || super.parseExprAtom(refExpressionErrors) + ); } }; diff --git a/packages/babel-parser/src/tokenizer/index.ts b/packages/babel-parser/src/tokenizer/index.ts index 22a0ab5246d0..fadbc99e2b22 100644 --- a/packages/babel-parser/src/tokenizer/index.ts +++ b/packages/babel-parser/src/tokenizer/index.ts @@ -82,7 +82,7 @@ export class Token { // ## Tokenizer -export default class Tokenizer extends CommentsParser { +export default abstract class Tokenizer extends CommentsParser { isLookahead: boolean; // Token store. @@ -260,7 +260,7 @@ export default class Tokenizer extends CommentsParser { this.getTokenFromCode(this.codePointAtPos(this.state.pos)); } - skipBlockComment(): N.CommentBlock | void { + skipBlockComment(): N.CommentBlock | undefined { let startLoc; if (!this.isLookahead) startLoc = this.state.curPosition(); const start = this.state.pos; @@ -297,7 +297,7 @@ export default class Tokenizer extends CommentsParser { return comment; } - skipLineComment(startSkip: number): N.CommentLine | void { + skipLineComment(startSkip: number): N.CommentLine | undefined { const start = this.state.pos; let startLoc; if (!this.isLookahead) startLoc = this.state.curPosition(); @@ -361,7 +361,6 @@ export default class Tokenizer extends CommentsParser { case charCodes.asterisk: { const comment = this.skipBlockComment(); if (comment !== undefined) { - // @ts-expect-error strictNullCheck is not enabled this.addComment(comment); if (this.options.attachComment) comments.push(comment); } @@ -371,7 +370,6 @@ export default class Tokenizer extends CommentsParser { case charCodes.slash: { const comment = this.skipLineComment(2); if (comment !== undefined) { - // @ts-expect-error strictNullCheck is not enabled this.addComment(comment); if (this.options.attachComment) comments.push(comment); } @@ -396,7 +394,6 @@ export default class Tokenizer extends CommentsParser { // A `-->` line comment const comment = this.skipLineComment(3); if (comment !== undefined) { - // @ts-expect-error strictNullCheck is not enabled this.addComment(comment); if (this.options.attachComment) comments.push(comment); } @@ -413,7 +410,6 @@ export default class Tokenizer extends CommentsParser { // `