Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve @babel/parser AST types #16425

Merged
merged 5 commits into from Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
109 changes: 64 additions & 45 deletions packages/babel-parser/src/parser/expression.ts
Expand Up @@ -117,13 +117,16 @@ export default abstract class ExpressionParser extends LValParser {
prop.type === "SpreadElement" ||
this.isObjectMethod(prop) ||
prop.computed ||
// @ts-expect-error prop must be an ObjectProperty
prop.shorthand
) {
return;
}

const key = prop.key;
const key = prop.key as
| N.Identifier
| N.StringLiteral
| N.NumericLiteral
| N.BigIntLiteral;
// It is either an Identifier or a String/NumericLiteral
const name = key.type === "Identifier" ? key.name : key.value;

Expand All @@ -148,7 +151,10 @@ export default abstract class ExpressionParser extends LValParser {
}
}

shouldExitDescending(expr: N.Expression, potentialArrowAt: number): boolean {
shouldExitDescending(
expr: N.Expression | N.PrivateName,
potentialArrowAt: number,
): expr is N.ArrowFunctionExpression {
return (
expr.type === "ArrowFunctionExpression" && expr.start === potentialArrowAt
);
Expand All @@ -158,7 +164,7 @@ export default abstract class ExpressionParser extends LValParser {
getExpression(this: Parser): N.Expression & N.ParserOutput {
this.enterInitialScopes();
this.nextToken();
const expr = this.parseExpression();
const expr = this.parseExpression() as N.Expression & N.ParserOutput;
if (!this.match(tt.eof)) {
this.unexpected();
}
Expand All @@ -170,7 +176,6 @@ export default abstract class ExpressionParser extends LValParser {
if (this.options.tokens) {
expr.tokens = this.tokens;
}
// @ts-expect-error fixme: refine types
return expr;
}

Expand Down Expand Up @@ -323,7 +328,7 @@ export default abstract class ExpressionParser extends LValParser {
refExpressionErrors.privateKeyLoc = null; // reset because `({ #x: x })` is an assignable pattern
}
} else {
node.left = left;
node.left = left as unknown as N.Assignable; // checked a few lines further down
}

this.next();
Expand Down Expand Up @@ -442,9 +447,10 @@ export default abstract class ExpressionParser extends LValParser {
if (op === tt.pipeline) {
this.expectPlugin("pipelineOperator");
if (this.state.inFSharpPipelineDirectBody) {
return left;
// PrivateName must be followed by `in`, but we have `|>`
return left as N.Expression;
}
this.checkPipelineAtInfixOperator(left, leftStartLoc);
this.checkPipelineAtInfixOperator(left as N.Expression, leftStartLoc);
}
const node = this.startNodeAt<N.LogicalExpression | N.BinaryExpression>(
leftStartLoc,
Expand Down Expand Up @@ -499,7 +505,8 @@ export default abstract class ExpressionParser extends LValParser {
return this.parseExprOp(finishedNode, leftStartLoc, minPrec);
}
}
return left;
// PrivateName is followed by `in` and handled by the previous if statement
return left as N.Expression;
}

// Helper function for `parseExprOp`. Parse the right-hand side of binary-
Expand Down Expand Up @@ -668,7 +675,6 @@ export default abstract class ExpressionParser extends LValParser {
refExpressionErrors?: ExpressionErrors | null,
): N.Expression {
if (update) {
// @ts-expect-error Type 'Node' is missing the following properties from type 'Undone<UpdateExpression>': prefix, operator, argument
const updateExpressionNode = node as Undone<N.UpdateExpression>;
this.checkLVal(updateExpressionNode.argument, {
in: this.finishNode(updateExpressionNode, "UpdateExpression"),
Expand Down Expand Up @@ -1199,7 +1205,10 @@ export default abstract class ExpressionParser extends LValParser {
// fall through
case tt._class:
return this.parseClass(
this.maybeTakeDecorators(decorators, this.startNode()),
this.maybeTakeDecorators(
decorators,
this.startNode<N.ClassExpression>(),
),
false,
);

Expand Down Expand Up @@ -1234,7 +1243,7 @@ export default abstract class ExpressionParser extends LValParser {
this.raise(Errors.PrivateInExpectedIn, this.state.startLoc, {
identifierName: this.state.value,
});
return this.parsePrivateName();
return this.parsePrivateName() as unknown as N.Expression;
}

case tt.moduloAssign: {
Expand Down Expand Up @@ -1414,12 +1423,14 @@ export default abstract class ExpressionParser extends LValParser {
// If the `pipelineOperator` plugin is active,
// but if the given `tokenType` does not match the plugin’s configuration,
// then this method will throw a `PipeTopicUnconfiguredToken` error.
finishTopicReference(
node: Undone<N.Node>,
finishTopicReference<
T extends N.PipelinePrimaryTopicReference | N.TopicReference,
>(
node: Undone<T>,
startLoc: Position,
pipeProposal: string,
tokenType: TokenType,
): N.Expression {
): T {
if (
this.testTopicReferenceConfiguration(pipeProposal, startLoc, tokenType)
) {
Expand Down Expand Up @@ -1758,7 +1769,7 @@ export default abstract class ExpressionParser extends LValParser {
this.state.inFSharpPipelineDirectBody = false;

const innerStartLoc = this.state.startLoc;
const exprList: N.Expression[] = [];
const exprList: (N.Expression | N.RestElement)[] = [];
const refExpressionErrors = new ExpressionErrors();
let first = true;
let spreadStartLoc;
Expand Down Expand Up @@ -1831,7 +1842,7 @@ export default abstract class ExpressionParser extends LValParser {
this.toReferencedListDeep(exprList, /* isParenthesizedExpr */ true);
if (exprList.length > 1) {
val = this.startNodeAt<N.SequenceExpression>(innerStartLoc);
val.expressions = exprList;
val.expressions = exprList as N.Expression[];
// finish node at current location so it can pick up comments after `)`
this.finishNode(val, "SequenceExpression");
this.resetEndLocation(val, innerEndLoc);
Expand Down Expand Up @@ -1879,11 +1890,11 @@ export default abstract class ExpressionParser extends LValParser {
}
}

parseParenItem(
node: N.Expression,
parseParenItem<T extends N.Expression | N.RestElement | N.SpreadElement>(
node: T,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
startLoc: Position,
): N.Expression {
): T | N.TypeCastExpression | N.TsTypeCastExpression {
return node;
}

Expand Down Expand Up @@ -1991,19 +2002,23 @@ export default abstract class ExpressionParser extends LValParser {
// https://tc39.es/ecma262/#prod-TemplateLiteral
parseTemplate(this: Parser, isTagged: boolean): N.TemplateLiteral {
const node = this.startNode<N.TemplateLiteral>();
node.expressions = [];
let curElt = this.parseTemplateElement(isTagged);
node.quasis = [curElt];
const quasis = [curElt];
const substitutions = [];
while (!curElt.tail) {
node.expressions.push(this.parseTemplateSubstitution());
substitutions.push(this.parseTemplateSubstitution());
this.readTemplateContinuation();
node.quasis.push((curElt = this.parseTemplateElement(isTagged)));
quasis.push((curElt = this.parseTemplateElement(isTagged)));
}
// Type cast from (N.Expression[] | N.TsType[]). parseTemplateSubstitution
// returns consistent results.
node.expressions = substitutions as N.Expression[] | N.TsType[];
node.quasis = quasis;
return this.finishNode(node, "TemplateLiteral");
}

// This is overwritten by the TypeScript plugin to parse template types
parseTemplateSubstitution(this: Parser): N.Expression {
parseTemplateSubstitution(this: Parser): N.Expression | N.TsType {
return this.parseExpression();
}

Expand Down Expand Up @@ -2108,7 +2123,9 @@ export default abstract class ExpressionParser extends LValParser {
// Check grammar production:
// IdentifierName *_opt PropertyName
// It is used in `parsePropertyDefinition` to detect AsyncMethod and Accessors
maybeAsyncOrAccessorProp(prop: Undone<N.ObjectProperty>): boolean {
maybeAsyncOrAccessorProp(
prop: Undone<N.ObjectProperty>,
): prop is typeof prop & { key: N.Identifier } {
return (
!prop.computed &&
prop.key.type === "Identifier" &&
Expand Down Expand Up @@ -2160,9 +2177,10 @@ export default abstract class ExpressionParser extends LValParser {
let isGenerator = this.eat(tt.star);
this.parsePropertyNamePrefixOperator(prop);
const containsEsc = this.state.containsEsc;
const key = this.parsePropertyName(prop, refExpressionErrors);
this.parsePropertyName(prop, refExpressionErrors);

if (!isGenerator && !containsEsc && this.maybeAsyncOrAccessorProp(prop)) {
const { key } = prop;
const keyName = key.name;
// https://tc39.es/ecma262/#prod-AsyncMethod
// https://tc39.es/ecma262/#prod-AsyncGeneratorMethod
Expand Down Expand Up @@ -2325,30 +2343,29 @@ export default abstract class ExpressionParser extends LValParser {
}
}

parseObjPropValue(
parseObjPropValue<T extends N.ObjectMember>(
this: Parser,
prop: Undone<N.ObjectMethod | N.ObjectProperty>,
prop: Undone<T>,
startLoc: Position | undefined | null,
isGenerator: boolean,
isAsync: boolean,
isPattern: boolean,
isAccessor: boolean,
refExpressionErrors?: ExpressionErrors | null,
): N.ObjectMethod | N.ObjectProperty {
const node =
this.parseObjectMethod(
prop as Undone<N.ObjectMethod>,
isGenerator,
isAsync,
isPattern,
isAccessor,
) ||
): T {
const node = (this.parseObjectMethod(
prop as Undone<N.ObjectMethod>,
isGenerator,
isAsync,
isPattern,
isAccessor,
) ||
this.parseObjectProperty(
prop as Undone<N.ObjectProperty>,
startLoc,
isPattern,
refExpressionErrors,
);
)) as T;

if (!node) this.unexpected();

Expand All @@ -2364,7 +2381,7 @@ export default abstract class ExpressionParser extends LValParser {
| Undone<N.ObjectOrClassMember | N.ClassMember>
| N.TsNamedTypeElementBase,
refExpressionErrors?: ExpressionErrors | null,
): N.Expression | N.Identifier {
): void {
if (this.eat(tt.bracketL)) {
(prop as Undone<N.ObjectOrClassMember>).computed = true;
prop.key = this.parseMaybeAssignAllowIn();
Expand Down Expand Up @@ -2413,8 +2430,6 @@ export default abstract class ExpressionParser extends LValParser {
prop.computed = false;
}
}

return prop.key;
}

// Initialize empty function node.
Expand Down Expand Up @@ -2491,7 +2506,9 @@ export default abstract class ExpressionParser extends LValParser {
parseArrowExpression(
this: Parser,
node: Undone<N.ArrowFunctionExpression>,
params: N.Expression[] | undefined | null,
params:
| Array<N.Expression | N.SpreadElement>
| Array<N.Expression | N.RestElement>,
isAsync: boolean,
trailingCommaLoc?: Position | null,
): N.ArrowFunctionExpression {
Expand Down Expand Up @@ -2523,7 +2540,9 @@ export default abstract class ExpressionParser extends LValParser {

setArrowFunctionParameters(
node: Undone<N.ArrowFunctionExpression>,
params: N.Expression[],
params:
| Array<N.Expression | N.SpreadElement>
| Array<N.Expression | N.RestElement>,
trailingCommaLoc?: Position | null,
): void {
this.toAssignableList(params, trailingCommaLoc, false);
Expand Down Expand Up @@ -2707,7 +2726,7 @@ export default abstract class ExpressionParser extends LValParser {
allowEmpty?: boolean | null,
refExpressionErrors?: ExpressionErrors | null,
allowPlaceholder?: boolean | null,
): N.Expression | null {
): N.Expression | N.SpreadElement | N.ArgumentPlaceholder | null {
let elt;
if (this.match(tt.comma)) {
if (!allowEmpty) {
Expand Down