Skip to content

Commit

Permalink
parser node types improvements (#14791)
Browse files Browse the repository at this point in the history
* make node definitions mutable (because they are modified while parsing)

* babel-parser use interfaces instead of type aliases for node type definitions, fix issues found

* update error supporession comments related to node types update

* fix ObjectProperty.value to also allow pattern

* review fixes

* review fixes

* Remove a few `@ts-expect-error`s

Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
zxbodya and nicolo-ribaudo committed Jul 26, 2022
1 parent e7c3a5f commit b0114cc
Show file tree
Hide file tree
Showing 9 changed files with 615 additions and 560 deletions.
6 changes: 3 additions & 3 deletions packages/babel-parser/src/parse-error.ts
@@ -1,13 +1,13 @@
import { Position } from "./util/location";
import type { NodeBase } from "./types";
import {
instantiate,
ParseErrorCode,
type ParseErrorCredentials,
type ToMessage,
type SyntaxPlugin,
} from "./parse-error/credentials";
import type { Undone } from "../src/parser/node";
import type { Undone } from "./parser/node";
import type { Node } from "./types";

// Babel uses "normal" SyntaxErrors for it's errors, but adds some extra
// functionality. This functionality is defined in the
Expand Down Expand Up @@ -201,7 +201,7 @@ export function ParseErrorEnum(
}

export type RaiseProperties<ErrorDetails> = {
at: Position | Undone<NodeBase>;
at: Position | Undone<Node>;
} & ErrorDetails;

import ModuleErrors from "./parse-error/module-errors";
Expand Down
17 changes: 9 additions & 8 deletions packages/babel-parser/src/parser/comments.ts
Expand Up @@ -3,6 +3,7 @@
import BaseParser from "./base";
import type { Comment, Node } from "../types";
import * as charCodes from "charcodes";
import type { Undone } from "./node";

/**
* A whitespace token containing comments
Expand Down Expand Up @@ -30,10 +31,10 @@ export type CommentWhitespace = {
* trailingComments. New comments will be placed before old comments
* because the commentStack is enumerated reversely.
*
* @param {Node} node
* @param {Undone<Node>} node
* @param {Array<Comment>} comments
*/
function setTrailingComments(node: Node, comments: Array<Comment>) {
function setTrailingComments(node: Undone<Node>, comments: Array<Comment>) {
if (node.trailingComments === undefined) {
node.trailingComments = comments;
} else {
Expand All @@ -46,10 +47,10 @@ function setTrailingComments(node: Node, comments: Array<Comment>) {
* leadingComments. New comments will be placed before old comments
* because the commentStack is enumerated reversely.
*
* @param {Node} node
* @param {Undone<Node>} node
* @param {Array<Comment>} comments
*/
function setLeadingComments(node: Node, comments: Array<Comment>) {
function setLeadingComments(node: Undone<Node>, comments: Array<Comment>) {
if (node.leadingComments === undefined) {
node.leadingComments = comments;
} else {
Expand All @@ -62,10 +63,10 @@ function setLeadingComments(node: Node, comments: Array<Comment>) {
* innerComments. New comments will be placed before old comments
* because the commentStack is enumerated reversely.
*
* @param {Node} node
* @param {Undone<Node>} node
* @param {Array<Comment>} comments
*/
export function setInnerComments(node: Node, comments: Array<Comment>) {
export function setInnerComments(node: Undone<Node>, comments: Array<Comment>) {
if (node.innerComments === undefined) {
node.innerComments = comments;
} else {
Expand All @@ -78,12 +79,12 @@ export function setInnerComments(node: Node, comments: Array<Comment>) {
* merge comments to its trailingComments, otherwise merge comments
* to node's innerComments
*
* @param {Node} node
* @param {Undone<Node>} node
* @param {Array<Node>} elements
* @param {Array<Comment>} comments
*/
function adjustInnerComments(
node: Node,
node: Undone<Node>,
elements: Array<Node>,
commentWS: CommentWhitespace,
) {
Expand Down
59 changes: 43 additions & 16 deletions packages/babel-parser/src/parser/expression.ts
Expand Up @@ -343,6 +343,7 @@ export default class ExpressionParser extends LValParser {
this.checkLVal(left, {
in: this.finishNode(node, "AssignmentExpression"),
});
// @ts-expect-error todo(flow->ts) improve node types
return node;
} else if (ownExpressionErrors) {
this.checkExpressionErrors(refExpressionErrors, true);
Expand Down Expand Up @@ -589,13 +590,15 @@ export default class ExpressionParser extends LValParser {
const { startLoc } = this.state;
const body = this.parseMaybeAssign();
const requiredParentheses = UnparenthesizedPipeBodyDescriptions.has(
// @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type '"ArrowFunctionExpression" | "YieldExpression" | "AssignmentExpression" | "ConditionalExpression"'.
body.type,
);

// TODO: Check how to handle type casts in Flow and TS once they are supported
if (requiredParentheses && !body.extra?.parenthesized) {
this.raise(Errors.PipeUnparenthesizedBody, {
at: startLoc,
// @ts-expect-error TS2322: Type 'string' is not assignable to type '"AssignmentExpression" | "ArrowFunctionExpression" | "ConditionalExpression" | "YieldExpression"'.
type: body.type,
});
}
Expand Down Expand Up @@ -668,7 +671,12 @@ export default class ExpressionParser extends LValParser {
}
}

const expr = this.parseUpdate(node, update, refExpressionErrors);
const expr = this.parseUpdate(
// @ts-expect-error using "Undone" node as "done"
node,
update,
refExpressionErrors,
);

if (isAwait) {
const { type } = this.state;
Expand All @@ -692,11 +700,10 @@ export default class ExpressionParser extends LValParser {
refExpressionErrors?: ExpressionErrors | null,
): N.Expression {
if (update) {
this.checkLVal((node as Undone<N.UpdateExpression>).argument, {
in: this.finishNode(
node as Undone<N.UpdateExpression>,
"UpdateExpression",
),
// @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"),
});
return node;
}
Expand Down Expand Up @@ -922,6 +929,7 @@ export default class ExpressionParser extends LValParser {
tt.parenR,
base.type === "Import",
base.type !== "Super",
// @ts-expect-error todo(flow->ts)
node,
refExpressionErrors,
);
Expand Down Expand Up @@ -1452,7 +1460,7 @@ export default class ExpressionParser extends LValParser {
// but if the given `tokenType` does not match the plugin鈥檚 configuration,
// then this method will throw a `PipeTopicUnconfiguredToken` error.
finishTopicReference(
node: N.Node,
node: Undone<N.Node>,
startLoc: Position,
pipeProposal: string,
tokenType: TokenType,
Expand Down Expand Up @@ -1650,7 +1658,11 @@ export default class ExpressionParser extends LValParser {
// The code wasn't `function.sent` but just `function.`, so a simple error is less confusing.
this.unexpected();
}
return this.parseMetaProperty(node, meta, "sent");
return this.parseMetaProperty(
node as Undone<N.MetaProperty>,
meta,
"sent",
);
}
return this.parseFunction(node as Undone<N.FunctionExpression>);
}
Expand Down Expand Up @@ -1840,6 +1852,7 @@ export default class ExpressionParser extends LValParser {
this.expressionScope.validateAsPattern();
this.expressionScope.exit();
this.parseArrowExpression(arrowNode, exprList, false);
// @ts-expect-error todo(flow->ts) improve node types
return arrowNode;
}
this.expressionScope.exit();
Expand All @@ -1865,7 +1878,12 @@ export default class ExpressionParser extends LValParser {
val = exprList[0];
}

return this.wrapParenthesis(startPos, startLoc, val);
return this.wrapParenthesis(
startPos,
startLoc,
// @ts-expect-error todo(flow->ts)
val,
);
}

wrapParenthesis(
Expand Down Expand Up @@ -2080,7 +2098,10 @@ export default class ExpressionParser extends LValParser {
} else {
this.expect(tt.comma);
if (this.match(close)) {
this.addTrailingCommaExtraToNode(node);
this.addTrailingCommaExtraToNode(
// @ts-expect-error todo(flow->ts) improve node types
node,
);
break;
}
}
Expand Down Expand Up @@ -2396,9 +2417,9 @@ export default class ExpressionParser extends LValParser {
// and record the position of the first private name
parsePropertyName(
this: Parser,
prop: Undone<
N.ObjectOrClassMember | N.ClassMember | N.TsNamedTypeElementBase
>,
prop:
| Undone<N.ObjectOrClassMember | N.ClassMember>
| N.TsNamedTypeElementBase,
refExpressionErrors?: ExpressionErrors | null,
): N.Expression | N.Identifier {
if (this.eat(tt.bracketL)) {
Expand Down Expand Up @@ -2517,6 +2538,7 @@ export default class ExpressionParser extends LValParser {
close,
/* allowEmpty */ !isTuple,
refExpressionErrors,
// @ts-expect-error todo(flow->ts)
node,
);
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
Expand Down Expand Up @@ -2595,7 +2617,6 @@ export default class ExpressionParser extends LValParser {

if (isExpression) {
// https://tc39.es/ecma262/#prod-ExpressionBody
// @ts-expect-error Fixme: refine typings
(node as Undone<N.ArrowFunctionExpression>).body =
this.parseMaybeAssign();
this.checkParams(node, false, allowExpression, false);
Expand Down Expand Up @@ -2915,7 +2936,10 @@ export default class ExpressionParser extends LValParser {

this.expressionScope.recordParameterInitializerError(
Errors.AwaitExpressionFormalParameter,
{ at: node },
{
// @ts-expect-error todo(flow->ts)
at: node,
},
);

if (this.eat(tt.star)) {
Expand Down Expand Up @@ -2964,7 +2988,10 @@ export default class ExpressionParser extends LValParser {

this.expressionScope.recordParameterInitializerError(
Errors.YieldInParameter,
{ at: node },
{
// @ts-expect-error todo(flow->ts)
at: node,
},
);

this.next();
Expand Down
28 changes: 19 additions & 9 deletions packages/babel-parser/src/parser/statement.ts
Expand Up @@ -1160,7 +1160,6 @@ export default class StatementParser extends ExpressionParser {

if (
!hasStrictModeDirective &&
// @ts-expect-error migrate to Babel types
directive.value.value === "use strict"
) {
hasStrictModeDirective = true;
Expand Down Expand Up @@ -1381,7 +1380,6 @@ export default class StatementParser extends ExpressionParser {
// Parse the function body.
this.parseFunctionBodyAndFinish(
node,
// @ts-expect-error node must be one of types
isStatement ? "FunctionDeclaration" : "FunctionExpression",
);
});
Expand Down Expand Up @@ -2086,11 +2084,23 @@ export default class StatementParser extends ExpressionParser {
| N.ExportNamedDeclaration
>,
): N.AnyExport {
const hasDefault = this.maybeParseExportDefaultSpecifier(node);
const hasDefault = this.maybeParseExportDefaultSpecifier(
// @ts-expect-error todo(flow->ts)
node,
);
const parseAfterDefault = !hasDefault || this.eat(tt.comma);
const hasStar = parseAfterDefault && this.eatExportStar(node);
const hasStar =
parseAfterDefault &&
this.eatExportStar(
// @ts-expect-error todo(flow->ts)
node,
);
const hasNamespace =
hasStar && this.maybeParseExportNamespaceSpecifier(node);
hasStar &&
this.maybeParseExportNamespaceSpecifier(
// @ts-expect-error todo(flow->ts)
node,
);
const parseAfterNamespace =
parseAfterDefault && (!hasNamespace || this.eat(tt.comma));
const isFromRequired = hasDefault || hasStar;
Expand All @@ -2102,7 +2112,10 @@ export default class StatementParser extends ExpressionParser {
return this.finishNode(node, "ExportAllDeclaration");
}

const hasSpecifiers = this.maybeParseExportNamedSpecifiers(node);
const hasSpecifiers = this.maybeParseExportNamedSpecifiers(
// @ts-expect-error todo(flow->ts)
node,
);

if (
(hasDefault && parseAfterDefault && !hasStar && !hasSpecifiers) ||
Expand Down Expand Up @@ -2386,7 +2399,6 @@ export default class StatementParser extends ExpressionParser {
.declaration;
if (
declaration.type === "Identifier" &&
// @ts-expect-error migrate to Babel types
declaration.name === "from" &&
declaration.end - declaration.start === 4 && // does not contain escape
!declaration.extra?.parenthesized
Expand Down Expand Up @@ -2427,13 +2439,11 @@ export default class StatementParser extends ExpressionParser {
node.declaration.type === "FunctionDeclaration" ||
node.declaration.type === "ClassDeclaration"
) {
// @ts-expect-error migrate to Babel types
const id = node.declaration.id;
if (!id) throw new Error("Assertion failure");

this.checkDuplicateExports(node, id.name);
} else if (node.declaration.type === "VariableDeclaration") {
// @ts-expect-error migrate to Babel types
for (const declaration of node.declaration.declarations) {
this.checkDeclaration(declaration.id);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/util.ts
Expand Up @@ -46,7 +46,7 @@ export default class UtilParser extends Tokenizer {
// TODO

addExtra(
node: Node,
node: Partial<Node>,
key: string,
value: any,
enumerable: boolean = true,
Expand Down
7 changes: 2 additions & 5 deletions packages/babel-parser/src/plugins/estree.ts
Expand Up @@ -108,21 +108,17 @@ export default (superClass: {
directive.loc.start,
);
const expression = this.startNodeAt<N.EstreeLiteral>(
// @ts-expect-error N.Directive.value is not defined
directiveLiteral.start,
// @ts-expect-error N.Directive.value is not defined
directiveLiteral.loc.start,
);

// @ts-expect-error N.Directive.value is not defined
expression.value = directiveLiteral.extra.expressionValue;
// @ts-expect-error N.Directive.value is not defined
// @ts-expect-error TS2339: Property 'raw' does not exist on type 'Undone '.
expression.raw = directiveLiteral.extra.raw;

stmt.expression = this.finishNodeAt(
expression,
"Literal",
// @ts-expect-error N.Directive.value is not defined
directiveLiteral.loc.end,
);
// @ts-expect-error N.Directive.value is not defined
Expand Down Expand Up @@ -286,6 +282,7 @@ export default (superClass: {
let funcNode = this.startNode<N.MethodLike>();
funcNode.kind = node.kind; // provide kind, so super method correctly sets state
funcNode = super.parseMethod(
// @ts-expect-error todo(flow->ts)
funcNode,
isGenerator,
isAsync,
Expand Down

0 comments on commit b0114cc

Please sign in to comment.