Skip to content

Commit

Permalink
@babel/types builder improvements (#14519)
Browse files Browse the repository at this point in the history
* improve deprecated builders generation

* generate builders instead of dynamically doing it

* use default parameters in builder function arguments

* fix deprecated builders

* optimize: use shorthand if applicable

* Mark BaseNode properties as optional

They are generated by `@babel/parser` but not returned from types builder

* chore: improve types

* revert cloneNode changes

* fix: assign optional value when default is non-null

* optimize: skip validateNode when builder keys are empty

* fix: set default value of objectTypeAnnotation.indexers/callProperties/internalSlots to []

null has been excluded by validate: arrayOfType

* remove unused builder

* fix deprecated types builder typings

* simplify builders

* return validated in validateNode

* merge intermediate node declaration

* review comments

Co-authored-by: Bogdan Savluk <savluk.bogdan@gmail.com>
  • Loading branch information
JLHwung and zxbodya committed May 9, 2022
1 parent 871ed89 commit c6e68c7
Show file tree
Hide file tree
Showing 10 changed files with 1,452 additions and 483 deletions.
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} {`;

const nodeObjectExpression = `{\n${objectFields
.map(([k, v]) => (k === v ? ` ${k},` : ` ${k}: ${v},`))
.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.

0 comments on commit c6e68c7

Please sign in to comment.