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

@babel/types builder improvements #14519

Merged
merged 17 commits into from May 9, 2022
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
Expand Up @@ -4,7 +4,7 @@ import syntaxDecorators from "@babel/plugin-syntax-decorators";
import ReplaceSupers from "@babel/helper-replace-supers";
import splitExportDeclaration from "@babel/helper-split-export-declaration";
import * as charCodes from "charcodes";
import type { PluginAPI, PluginObject } from "@babel/core";
import type { PluginAPI, PluginObject, PluginPass } from "@babel/core";
import type { Options } from "..";

type ClassDecoratableElement =
Expand Down Expand Up @@ -482,7 +482,7 @@ function maybeSequenceExpression(exprs: t.Expression[]) {

function transformClass(
path: NodePath<t.ClassExpression | t.ClassDeclaration>,
state: any,
state: PluginPass,
constantSuper: boolean,
): NodePath {
const body = path.get("body.body");
Expand Down
12 changes: 6 additions & 6 deletions packages/babel-types/scripts/generators/ast-types.js
Expand Up @@ -36,13 +36,13 @@ export interface SourceLocation {
}

interface BaseNode {
leadingComments: ReadonlyArray<Comment> | null;
innerComments: ReadonlyArray<Comment> | null;
trailingComments: ReadonlyArray<Comment> | null;
start: number | null;
end: number | null;
loc: SourceLocation | null;
type: Node["type"];
leadingComments?: ReadonlyArray<Comment> | null;
innerComments?: ReadonlyArray<Comment> | null;
trailingComments?: ReadonlyArray<Comment> | null;
start?: number | null;
end?: number | null;
loc?: SourceLocation | null;
range?: [number, number];
extra?: Record<string, unknown>;
}
Expand Down
67 changes: 48 additions & 19 deletions packages/babel-types/scripts/generators/builders.js
Expand Up @@ -51,20 +51,23 @@ function generateBuilderArgs(type) {
}

if (builderNames.includes(fieldName)) {
const field = definitions.NODE_FIELDS[type][fieldName];
const def = JSON.stringify(field.default);
const bindingIdentifierName = t.toBindingIdentifierName(fieldName);
let arg;
if (areAllRemainingFieldsNullable(fieldName, builderNames, fields)) {
args.push(
`${bindingIdentifierName}${
isNullable(field) ? "?:" : ":"
} ${typeAnnotation}`
);
arg = `${bindingIdentifierName}${
isNullable(field) && !def ? "?:" : ":"
} ${typeAnnotation}`;
} else {
args.push(
`${bindingIdentifierName}: ${typeAnnotation}${
isNullable(field) ? " | undefined" : ""
}`
);
arg = `${bindingIdentifierName}: ${typeAnnotation}${
isNullable(field) ? " | undefined" : ""
}`;
}
if (def !== "null" || isNullable(field)) {
arg += `= ${def}`;
}
args.push(arg);
}
});

Expand All @@ -82,11 +85,8 @@ function generateLowercaseBuilders() {
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import builder from "../builder";
import validateNode from "../validateNode";
import type * as t from "../..";

/* eslint-disable @typescript-eslint/no-unused-vars */

`;

const reservedNames = new Set(["super", "import"]);
Expand All @@ -96,11 +96,39 @@ import type * as t from "../..";
const formatedBuilderNameLocal = reservedNames.has(formatedBuilderName)
? `_${formatedBuilderName}`
: formatedBuilderName;

const fieldNames = sortFieldNames(
Object.keys(definitions.NODE_FIELDS[type]),
type
);
const builderNames = definitions.BUILDER_KEYS[type];
const objectFields = [["type", JSON.stringify(type)]];
fieldNames.forEach(fieldName => {
const field = definitions.NODE_FIELDS[type][fieldName];
if (builderNames.includes(fieldName)) {
const bindingIdentifierName = t.toBindingIdentifierName(fieldName);
objectFields.push([fieldName, bindingIdentifierName]);
} else if (!field.optional) {
const def = JSON.stringify(field.default);
objectFields.push([fieldName, def]);
}
});

output += `${
formatedBuilderNameLocal === formatedBuilderName ? "export " : ""
}function ${formatedBuilderNameLocal}(${defArgs.join(
", "
)}): t.${type} { return builder.apply("${type}", arguments); }\n`;
}function ${formatedBuilderNameLocal}(${defArgs.join(", ")}): t.${type} {`;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type annotation is preserved because we skip validateNode for nodes with empty builder keys.


const nodeObjectExpression = `{\n${objectFields
.map(([k, v]) => (k === v ? ` ${k},` : ` ${k}: ${v},`))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: since these just come from local param names, can't we make it always match?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the argument name match the AST field name. The exceptions are non-valid binding identifier names, such as CallExpression's arguments and ClassMethod's static.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh

.join("\n")}\n }`;

if (builderNames.length > 0) {
output += `\n return validateNode<t.${type}>(${nodeObjectExpression});`;
} else {
output += `\n return ${nodeObjectExpression};`;
}
output += `\n}\n`;

if (formatedBuilderNameLocal !== formatedBuilderName) {
output += `export { ${formatedBuilderNameLocal} as ${formatedBuilderName} };\n`;
}
Expand All @@ -118,10 +146,11 @@ import type * as t from "../..";
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const newType = definitions.DEPRECATED_KEYS[type];
const formatedBuilderName = formatBuilderName(type);
const formatedNewBuilderName = formatBuilderName(newType);
output += `/** @deprecated */
function ${type}(${generateBuilderArgs(newType).join(", ")}): t.${type} {
function ${type}(${generateBuilderArgs(newType).join(", ")}) {
console.trace("The node type ${type} has been renamed to ${newType}");
return builder.apply("${type}", arguments);
return ${formatedNewBuilderName}(${t.BUILDER_KEYS[newType].join(", ")});
}
export { ${type} as ${formatedBuilderName} };\n`;
// This is needed for backwards compatibility.
Expand Down
18 changes: 9 additions & 9 deletions packages/babel-types/src/ast-types/generated/index.ts
Expand Up @@ -32,13 +32,13 @@ export interface SourceLocation {
}

interface BaseNode {
leadingComments: ReadonlyArray<Comment> | null;
innerComments: ReadonlyArray<Comment> | null;
trailingComments: ReadonlyArray<Comment> | null;
start: number | null;
end: number | null;
loc: SourceLocation | null;
type: Node["type"];
leadingComments?: ReadonlyArray<Comment> | null;
innerComments?: ReadonlyArray<Comment> | null;
trailingComments?: ReadonlyArray<Comment> | null;
start?: number | null;
end?: number | null;
loc?: SourceLocation | null;
range?: [number, number];
extra?: Record<string, unknown>;
}
Expand Down Expand Up @@ -1253,9 +1253,9 @@ export interface NumberTypeAnnotation extends BaseNode {
export interface ObjectTypeAnnotation extends BaseNode {
type: "ObjectTypeAnnotation";
properties: Array<ObjectTypeProperty | ObjectTypeSpreadProperty>;
indexers?: Array<ObjectTypeIndexer> | null;
callProperties?: Array<ObjectTypeCallProperty> | null;
internalSlots?: Array<ObjectTypeInternalSlot> | null;
indexers?: Array<ObjectTypeIndexer>;
callProperties?: Array<ObjectTypeCallProperty>;
internalSlots?: Array<ObjectTypeInternalSlot>;
exact: boolean;
inexact?: boolean | null;
}
Expand Down
37 changes: 0 additions & 37 deletions packages/babel-types/src/builders/builder.ts

This file was deleted.