Skip to content

Commit

Permalink
Provide better parentPath typings (#14739)
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed Jul 9, 2022
1 parent b4646fe commit 41582ee
Show file tree
Hide file tree
Showing 22 changed files with 7,167 additions and 510 deletions.
Expand Up @@ -94,13 +94,17 @@ function extractElementDescriptor(

const { node, scope } = path as NodePath<SupportedElement>;

new ReplaceSupers({
methodPath: path,
objectRef: classRef,
superRef,
file,
refToPreserve: classRef,
}).replace();
if (!path.isTSDeclareMethod()) {
new ReplaceSupers({
methodPath: path as NodePath<
Exclude<SupportedElement, t.TSDeclareMethod>
>,
objectRef: classRef,
superRef,
file,
refToPreserve: classRef,
}).replace();
}

const properties: t.ObjectExpression["properties"] = [
prop("kind", t.stringLiteral(t.isClassMethod(node) ? node.kind : "field")),
Expand Down
Expand Up @@ -215,9 +215,12 @@ const handle = {
);
}

// @ts-expect-error isOptionalMemberExpression does not work with NodePath union
const startingNode = startingOptional.isOptionalMemberExpression()
? startingOptional.node.object
: startingOptional.node.callee;
? // @ts-expect-error isOptionalMemberExpression does not work with NodePath union
startingOptional.node.object
: // @ts-expect-error isOptionalMemberExpression does not work with NodePath union
startingOptional.node.callee;
const baseNeedsMemoised = scope.maybeGenerateMemoised(startingNode);
const baseRef = baseNeedsMemoised ?? startingNode;

Expand Down
Expand Up @@ -36,7 +36,7 @@ const awaitVisitor = traverse.visitors.merge<{ wrapAwait: t.Expression }>([
]);

export default function (
path: NodePath<any>,
path: NodePath<t.Function>,
helpers: {
wrapAsync: t.Expression;
wrapAwait?: t.Expression;
Expand Down
22 changes: 16 additions & 6 deletions packages/babel-helper-replace-supers/src/index.ts
@@ -1,4 +1,4 @@
import type { HubInterface, NodePath, Scope } from "@babel/traverse";
import type { NodePath, Scope } from "@babel/traverse";
import traverse from "@babel/traverse";
import memberExpressionToFunctions from "@babel/helper-member-expression-to-functions";
import type { HandlerState } from "@babel/helper-member-expression-to-functions";
Expand Down Expand Up @@ -317,9 +317,16 @@ const looseHandlers = {
};

type ReplaceSupersOptionsBase = {
methodPath: NodePath<any>;
methodPath: NodePath<
| t.ClassMethod
| t.ClassProperty
| t.ObjectMethod
| t.ClassPrivateMethod
| t.ClassPrivateProperty
| t.StaticBlock
>;
constantSuper?: boolean;
file: any;
file: File;
// objectRef might have been shadowed in child scopes,
// in that case, we need to rename related variables.
refToPreserve?: t.Identifier;
Expand All @@ -336,7 +343,7 @@ type ReplaceSupersOptions = ReplaceSupersOptionsBase &
);

interface ReplaceState {
file: unknown;
file: File;
scope: Scope;
isDerivedConstructor: boolean;
isStatic: boolean;
Expand All @@ -353,7 +360,10 @@ export default class ReplaceSupers {
this.isDerivedConstructor =
path.isClassMethod({ kind: "constructor" }) && !!opts.superRef;
this.isStatic =
path.isObjectMethod() || path.node.static || path.isStaticBlock?.();
path.isObjectMethod() ||
// @ts-expect-error static is not in ClassPrivateMethod
path.node.static ||
path.isStaticBlock?.();
this.isPrivateMethod = path.isPrivate() && path.isMethod();

this.file = opts.file;
Expand All @@ -364,7 +374,7 @@ export default class ReplaceSupers {
this.opts = opts;
}

declare file: HubInterface;
declare file: File;
declare isDerivedConstructor: boolean;
declare constantSuper: boolean;
declare isPrivateMethod: boolean;
Expand Down
24 changes: 16 additions & 8 deletions packages/babel-helper-wrap-function/src/index.ts
Expand Up @@ -40,7 +40,7 @@ const buildDeclarationWrapper = template.statements(`

function classOrObjectMethod(
path: NodePath<t.ClassMethod | t.ClassPrivateMethod | t.ObjectMethod>,
callId: any,
callId: t.Expression,
) {
const node = path.node;
const body = node.body;
Expand All @@ -67,13 +67,14 @@ function classOrObjectMethod(
}

function plainFunction(
path: NodePath<any>,
callId: any,
path: NodePath<Exclude<t.Function, t.Method>>,
callId: t.Expression,
noNewArrows: boolean,
ignoreFunctionLength: boolean,
) {
const node = path.node;
const isDeclaration = path.isFunctionDeclaration();
// @ts-expect-error id is not in ArrowFunctionExpression
const functionId = node.id;
const wrapper = isDeclaration
? buildDeclarationWrapper
Expand All @@ -84,14 +85,16 @@ function plainFunction(
if (path.isArrowFunctionExpression()) {
path.arrowFunctionToExpression({ noNewArrows });
}

// @ts-expect-error node is FunctionDeclaration|FunctionExpression
node.id = null;

if (isDeclaration) {
node.type = "FunctionExpression";
}

const built = callExpression(callId, [node]);
const built = callExpression(callId, [
node as Exclude<t.Function, t.Method | t.FunctionDeclaration>,
]);

const params: t.Identifier[] = [];
for (const param of node.params) {
Expand Down Expand Up @@ -138,15 +141,20 @@ function plainFunction(
}

export default function wrapFunction(
path: NodePath,
callId: any,
path: NodePath<t.Function>,
callId: t.Expression,
// TODO(Babel 8): Consider defaulting to false for spec compliancy
noNewArrows: boolean = true,
ignoreFunctionLength: boolean = false,
) {
if (path.isMethod()) {
classOrObjectMethod(path, callId);
} else {
plainFunction(path, callId, noNewArrows, ignoreFunctionLength);
plainFunction(
path as NodePath<Exclude<t.Function, t.Method>>,
callId,
noNewArrows,
ignoreFunctionLength,
);
}
}
1 change: 1 addition & 0 deletions packages/babel-helpers/src/index.ts
Expand Up @@ -59,6 +59,7 @@ function getHelperMetadata(file: File): HelperMetadata {
}
if (
child.get("specifiers").length !== 1 ||
// @ts-expect-error isImportDefaultSpecifier does not work with NodePath union
!child.get("specifiers.0").isImportDefaultSpecifier()
) {
throw child.buildCodeFrameError(
Expand Down
Expand Up @@ -23,18 +23,16 @@ export function shouldTransform(
path: NodePath<t.OptionalMemberExpression | t.OptionalCallExpression>,
): boolean {
let optionalPath: NodePath<t.Expression> = path;
const chains = [];
while (
optionalPath.isOptionalMemberExpression() ||
optionalPath.isOptionalCallExpression()
) {
const { node } = optionalPath;
chains.push(node);

const chains: (t.OptionalCallExpression | t.OptionalMemberExpression)[] = [];
for (;;) {
if (optionalPath.isOptionalMemberExpression()) {
chains.push(optionalPath.node);
optionalPath = skipTransparentExprWrappers(optionalPath.get("object"));
} else if (optionalPath.isOptionalCallExpression()) {
chains.push(optionalPath.node);
optionalPath = skipTransparentExprWrappers(optionalPath.get("callee"));
} else {
break;
}
}
for (let i = 0; i < chains.length; i++) {
Expand Down
Expand Up @@ -685,10 +685,10 @@ function transformClass(

const replaceSupers = new ReplaceSupers({
constantSuper,
methodPath: element,
methodPath: element as NodePath<t.ClassPrivateMethod>,
objectRef: classLocal,
superRef: path.node.superClass,
file: state,
file: state.file,
refToPreserve: classLocal,
});

Expand Down
11 changes: 4 additions & 7 deletions packages/babel-plugin-proposal-object-rest-spread/src/index.ts
Expand Up @@ -243,7 +243,9 @@ export default declare((api, opts: Options) => {

function replaceRestElement(
parentPath: NodePath<t.Function | t.CatchClause>,
paramPath: Param | NodePath<t.AssignmentPattern["left"]>,
paramPath: NodePath<
t.Function["params"][number] | t.AssignmentPattern["left"]
>,
container?: t.VariableDeclaration[],
): void {
if (paramPath.isAssignmentPattern()) {
Expand All @@ -255,12 +257,7 @@ export default declare((api, opts: Options) => {
const elements = paramPath.get("elements");

for (let i = 0; i < elements.length; i++) {
replaceRestElement(
parentPath,
// @ts-expect-error Fixme: handle TSAsExpression
elements[i],
container,
);
replaceRestElement(parentPath, elements[i], container);
}
}

Expand Down
Expand Up @@ -37,6 +37,7 @@ function needsMemoize(
) {
const { node } = optionalPath;
const childPath = skipTransparentExprWrappers(
// @ts-expect-error isOptionalMemberExpression does not work with NodePath union
optionalPath.isOptionalMemberExpression()
? optionalPath.get("object")
: optionalPath.get("callee"),
Expand Down Expand Up @@ -87,7 +88,7 @@ export function transform(
if (node.optional) {
optionals.push(node);
}

// @ts-expect-error isOptionalMemberExpression does not work with NodePath union
if (optionalPath.isOptionalMemberExpression()) {
// @ts-expect-error todo(flow->ts) avoid changing more type
optionalPath.node.type = "MemberExpression";
Expand Down
4 changes: 3 additions & 1 deletion packages/babel-plugin-transform-block-scoping/src/index.ts
Expand Up @@ -113,7 +113,9 @@ export default declare((api, opts: Options) => {
};
});

function ignoreBlock(path: NodePath) {
function ignoreBlock(
path: NodePath<t.BlockStatement | t.SwitchStatement | t.Program>,
) {
return t.isLoop(path.parent) || t.isCatchClause(path.parent);
}

Expand Down
12 changes: 5 additions & 7 deletions packages/babel-plugin-transform-classes/src/index.ts
Expand Up @@ -5,7 +5,6 @@ import splitExportDeclaration from "@babel/helper-split-export-declaration";
import { types as t } from "@babel/core";
import globals from "globals";
import transformClass from "./transformClass";
import type { Visitor, NodePath } from "@babel/traverse";

const getBuiltinClasses = (category: keyof typeof globals) =>
Object.keys(globals[category]).filter(name => /^[A-Z]/.test(name));
Expand Down Expand Up @@ -68,7 +67,7 @@ export default declare((api, options: Options) => {

VISITED.add(node);

path.replaceWith(
const [replacedPath] = path.replaceWith(
transformClass(path, state.file, builtinClasses, loose, {
setClassMethods,
constantSuper,
Expand All @@ -77,16 +76,15 @@ export default declare((api, options: Options) => {
}),
);

if (path.isCallExpression()) {
annotateAsPure(path);
// todo: improve babel types
const callee = path.get("callee") as unknown as NodePath;
if (replacedPath.isCallExpression()) {
annotateAsPure(replacedPath);
const callee = replacedPath.get("callee");
if (callee.isArrowFunctionExpression()) {
// This is an IIFE, so we don't need to worry about the noNewArrows assumption
callee.arrowFunctionToExpression();
}
}
},
} as Visitor<any>,
},
};
});
6 changes: 3 additions & 3 deletions packages/babel-traverse/scripts/generators/validators.js
Expand Up @@ -14,7 +14,7 @@ export interface NodePathValidators {
`;

for (const type of [...t.TYPES].sort()) {
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
output += `is${type}<T extends t.Node>(this: NodePath<T>, opts?: object): this is NodePath<T & t.${type}>;`;
}

for (const type of Object.keys(virtualTypes)) {
Expand All @@ -24,9 +24,9 @@ export interface NodePathValidators {
const { types } = virtualTypes[type];
if (type[0] === "_") continue;
if (t.NODE_FIELDS[type] || t.FLIPPED_ALIAS_KEYS[type]) {
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
output += `is${type}<T extends t.Node>(this: NodePath<T>, opts?: object): this is NodePath<T & t.${type}>;`;
} else if (types /* in VirtualTypeAliases */) {
output += `is${type}(opts?: object): this is NodePath<VirtualTypeAliases["${type}"]>;`;
output += `is${type}<T extends t.Node>(this: NodePath<T>, opts?: object): this is NodePath<T & VirtualTypeAliases["${type}"]>;`;
} else if (type === "Pure") {
output += `isPure(constantsOnly?: boolean): boolean;`;
} else {
Expand Down

0 comments on commit 41582ee

Please sign in to comment.