Skip to content

Commit

Permalink
Improve @babel/parser AST types (#16425)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Apr 22, 2024
1 parent ca50141 commit 941cee2
Show file tree
Hide file tree
Showing 12 changed files with 902 additions and 393 deletions.
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鈥檚 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

0 comments on commit 941cee2

Please sign in to comment.