Skip to content

Commit

Permalink
Use bit flags
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Feb 9, 2023
1 parent 071c854 commit e521f13
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 77 deletions.
8 changes: 2 additions & 6 deletions packages/babel-parser/src/parser/expression.ts
Expand Up @@ -95,10 +95,7 @@ export default abstract class ExpressionParser extends LValParser {
allowExpressionBody?: boolean,
isAsync?: boolean,
): T;
abstract parseFunctionParams(
node: N.Function,
allowModifiers?: boolean,
): void;
abstract parseFunctionParams(node: N.Function, isConstructor?: boolean): void;
abstract parseBlockOrModuleBlockBody(
body: N.Statement[],
directives: N.Directive[] | null | undefined,
Expand Down Expand Up @@ -2427,15 +2424,14 @@ export default abstract class ExpressionParser extends LValParser {
): T {
this.initFunction(node, isAsync);
node.generator = isGenerator;
const allowModifiers = isConstructor; // For TypeScript parameter properties
this.scope.enter(
SCOPE_FUNCTION |
SCOPE_SUPER |
(inClassScope ? SCOPE_CLASS : 0) |
(allowDirectSuper ? SCOPE_DIRECT_SUPER : 0),
);
this.prodParam.enter(functionFlags(isAsync, node.generator));
this.parseFunctionParams(node, allowModifiers);
this.parseFunctionParams(node, isConstructor);
const finishedNode = this.parseFunctionBodyAndFinish(node, type, true);
this.prodParam.exit();
this.scope.exit();
Expand Down
40 changes: 15 additions & 25 deletions packages/babel-parser/src/parser/lval.ts
Expand Up @@ -44,6 +44,12 @@ const unwrapParenthesizedExpression = (node: Node): Node => {
: node;
};

export const enum ParseBindingListFlags {
ALLOW_EMPTY = 1 << 0,
IS_FUNCTION_PARAMS = 1 << 1,
IS_CONSTRUCTOR_PARAMS = 1 << 2,
}

export default abstract class LValParser extends NodeUtils {
// Forward-declaration: defined in expression.js
abstract parseIdentifier(liberal?: boolean): Identifier;
Expand Down Expand Up @@ -366,7 +372,7 @@ export default abstract class LValParser extends NodeUtils {
node.elements = this.parseBindingList(
tt.bracketR,
charCodes.rightSquareBracket,
{ allowEmpty: true },
ParseBindingListFlags.ALLOW_EMPTY,
);
return this.finishNode(node, "ArrayPattern");
}
Expand All @@ -384,16 +390,10 @@ export default abstract class LValParser extends NodeUtils {
this: Parser,
close: TokenType,
closeCharCode: typeof charCodes[keyof typeof charCodes],
{
allowEmpty = false,
allowModifiers = false,
isFunctionParams = false,
}: {
allowEmpty?: boolean;
allowModifiers?: boolean;
isFunctionParams?: boolean;
} = {},
flags: ParseBindingListFlags,
): Array<Pattern | TSParameterProperty> {
const allowEmpty = flags & ParseBindingListFlags.ALLOW_EMPTY;

const elts: Array<Pattern | TSParameterProperty> = [];
let first = true;
while (!this.eat(close)) {
Expand All @@ -408,10 +408,7 @@ export default abstract class LValParser extends NodeUtils {
break;
} else if (this.match(tt.ellipsis)) {
elts.push(
this.parseAssignableListItemTypes(
this.parseRestBinding(),
isFunctionParams,
),
this.parseAssignableListItemTypes(this.parseRestBinding(), flags),
);
if (!this.checkCommaAfterRest(closeCharCode)) {
this.expect(close);
Expand All @@ -428,13 +425,7 @@ export default abstract class LValParser extends NodeUtils {
while (this.match(tt.at)) {
decorators.push(this.parseDecorator());
}
elts.push(
this.parseAssignableListItem(
allowModifiers,
decorators,
isFunctionParams,
),
);
elts.push(this.parseAssignableListItem(flags, decorators));
}
}
return elts;
Expand Down Expand Up @@ -478,12 +469,11 @@ export default abstract class LValParser extends NodeUtils {

parseAssignableListItem(
this: Parser,
allowModifiers: boolean | undefined | null,
flags: ParseBindingListFlags,
decorators: Decorator[],
isFunctionParam: boolean = false,
): Pattern | TSParameterProperty {
const left = this.parseMaybeDefault();
this.parseAssignableListItemTypes(left, isFunctionParam);
this.parseAssignableListItemTypes(left, flags);
const elt = this.parseMaybeDefault(left.loc.start, left);
if (decorators.length) {
left.decorators = decorators;
Expand All @@ -495,7 +485,7 @@ export default abstract class LValParser extends NodeUtils {
parseAssignableListItemTypes(
param: Pattern,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isFunctionParam: boolean,
flags: ParseBindingListFlags,
): Pattern {
return param;
}
Expand Down
15 changes: 9 additions & 6 deletions packages/babel-parser/src/parser/statement.ts
Expand Up @@ -43,6 +43,7 @@ import type { Position } from "../util/location";
import { createPositionWithColumnOffset } from "../util/location";
import { cloneStringLiteral, cloneIdentifier, type Undone } from "./node";
import type Parser from "./index";
import { ParseBindingListFlags } from "./lval";

const loopLabel = { kind: "loop" } as const,
switchLabel = { kind: "switch" } as const;
Expand Down Expand Up @@ -1566,7 +1567,7 @@ export default abstract class StatementParser extends ExpressionParser {
node.id = this.parseFunctionId();
}

this.parseFunctionParams(node, /* allowModifiers */ false);
this.parseFunctionParams(node, /* isConstructor */ false);

// For the smartPipelines plugin: Disable topic references from outer
// contexts within the function body. They are permitted in function
Expand Down Expand Up @@ -1602,14 +1603,16 @@ export default abstract class StatementParser extends ExpressionParser {
parseFunctionParams(
this: Parser,
node: Undone<N.Function>,
allowModifiers?: boolean,
isConstructor?: boolean,
): void {
this.expect(tt.parenL);
this.expressionScope.enter(newParameterDeclarationScope());
node.params = this.parseBindingList(tt.parenR, charCodes.rightParenthesis, {
allowModifiers,
isFunctionParams: true,
});
node.params = this.parseBindingList(
tt.parenR,
charCodes.rightParenthesis,
ParseBindingListFlags.IS_FUNCTION_PARAMS |
(isConstructor ? ParseBindingListFlags.IS_CONSTRUCTOR_PARAMS : 0),
);

this.expressionScope.exit();
}
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-parser/src/plugins/flow/index.ts
Expand Up @@ -2887,14 +2887,14 @@ export default (superClass: typeof Parser) =>
// parse function type parameters - function foo<T>() {}
parseFunctionParams(
node: Undone<N.Function>,
allowModifiers?: boolean,
isConstructor: boolean,
): void {
// @ts-expect-error kind may not index node
const kind = node.kind;
if (kind !== "get" && kind !== "set" && this.match(tt.lt)) {
node.typeParameters = this.flowParseTypeParameterDeclaration();
}
super.parseFunctionParams(node, allowModifiers);
super.parseFunctionParams(node, isConstructor);
}

// parse flow type annotations on variable declarator heads - let foo: string = bar
Expand Down Expand Up @@ -3291,7 +3291,7 @@ export default (superClass: typeof Parser) =>
startLoc: Position,
): N.ArrowFunctionExpression | undefined | null {
const node = this.startNodeAt<N.ArrowFunctionExpression>(startLoc);
this.parseFunctionParams(node);
this.parseFunctionParams(node, false);
if (!this.parseArrow(node)) return;
return super.parseArrowExpression(
node,
Expand Down
76 changes: 39 additions & 37 deletions packages/babel-parser/src/plugins/typescript/index.ts
Expand Up @@ -42,6 +42,7 @@ import { cloneIdentifier, type Undone } from "../../parser/node";
import type { Pattern } from "../../types";
import type { Expression } from "../../types";
import type { IJSXParserMixin } from "../jsx";
import { ParseBindingListFlags } from "../../parser/lval";

const getOwn = <T extends {}>(object: T, key: keyof T) =>
Object.hasOwnProperty.call(object, key) && object[key];
Expand Down Expand Up @@ -755,9 +756,11 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
N.Identifier | N.RestElement | N.ObjectPattern | N.ArrayPattern
> {
return super
.parseBindingList(tt.parenR, charCodes.rightParenthesis, {
isFunctionParams: true,
})
.parseBindingList(
tt.parenR,
charCodes.rightParenthesis,
ParseBindingListFlags.IS_FUNCTION_PARAMS,
)
.map(pattern => {
if (
pattern.type !== "Identifier" &&
Expand Down Expand Up @@ -1421,9 +1424,11 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
const { errors } = this.state;
const previousErrorCount = errors.length;
try {
super.parseBindingList(tt.bracketR, charCodes.rightSquareBracket, {
allowEmpty: true,
});
super.parseBindingList(
tt.bracketR,
charCodes.rightSquareBracket,
ParseBindingListFlags.ALLOW_EMPTY,
);
return errors.length === previousErrorCount;
} catch {
return false;
Expand Down Expand Up @@ -2249,41 +2254,35 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
}

parseAssignableListItem(
allowModifiers: boolean | undefined | null,
flags: ParseBindingListFlags,
decorators: N.Decorator[],
isFunctionParam: boolean,
): N.Pattern | N.TSParameterProperty {
// Store original location to include modifiers in range
const startLoc = this.state.startLoc;

let accessibility: N.Accessibility | undefined | null;
let readonly = false;
let override = false;
if (allowModifiers !== undefined) {
const modified: ModifierBase = {};
this.tsParseModifiers({
modified,
allowedModifiers: [
"public",
"private",
"protected",
"override",
"readonly",
],
});
accessibility = modified.accessibility;
override = modified.override;
readonly = modified.readonly;
if (
allowModifiers === false &&
(accessibility || readonly || override)
) {
this.raise(TSErrors.UnexpectedParameterModifier, { at: startLoc });
}
const modified: ModifierBase = {};
this.tsParseModifiers({
modified,
allowedModifiers: [
"public",
"private",
"protected",
"override",
"readonly",
],
});
const accessibility = modified.accessibility;
const override = modified.override;
const readonly = modified.readonly;
if (
!(flags & ParseBindingListFlags.IS_CONSTRUCTOR_PARAMS) &&
(accessibility || readonly || override)
) {
this.raise(TSErrors.UnexpectedParameterModifier, { at: startLoc });
}

const left = this.parseMaybeDefault();
this.parseAssignableListItemTypes(left, isFunctionParam);
this.parseAssignableListItemTypes(left, flags);
const elt = this.parseMaybeDefault(left.loc.start, left);
if (accessibility || readonly || override) {
const pp = this.startNodeAt<N.TSParameterProperty>(startLoc);
Expand Down Expand Up @@ -3294,10 +3293,10 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
);
}

parseFunctionParams(node: N.Function, allowModifiers?: boolean): void {
parseFunctionParams(node: N.Function, isConstructor: boolean): void {
const typeParameters = this.tsTryParseTypeParameters();
if (typeParameters) node.typeParameters = typeParameters;
super.parseFunctionParams(node, allowModifiers);
super.parseFunctionParams(node, isConstructor);
}

// `let x: number;`
Expand Down Expand Up @@ -3527,8 +3526,11 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
}

// Allow type annotations inside of a parameter list.
parseAssignableListItemTypes(param: N.Pattern, isFunctionParam: boolean) {
if (!isFunctionParam) return param;
parseAssignableListItemTypes(
param: N.Pattern,
flags: ParseBindingListFlags,
) {
if (!(flags & ParseBindingListFlags.IS_FUNCTION_PARAMS)) return param;

if (this.eat(tt.question)) {
(param as any as N.Identifier).optional = true;
Expand Down

0 comments on commit e521f13

Please sign in to comment.