Skip to content

Commit

Permalink
Convert @babel/traverse to TypeScript (#12488)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
zxbodya and nicolo-ribaudo committed Jan 24, 2021
1 parent cd090e9 commit d98418e
Show file tree
Hide file tree
Showing 37 changed files with 2,024 additions and 369 deletions.
52 changes: 39 additions & 13 deletions Gulpfile.js
Expand Up @@ -86,13 +86,12 @@ function rename(fn) {
}

/**
*
* @typedef {("asserts" | "builders" | "constants" | "validators")} HelperKind
* @param {HelperKind} helperKind
* @param {string} generator
* @param {string} pkg
* @param {string} filename
* @param {string} message
*/
function generateTypeHelpers(helperKind, filename = "index.ts") {
const dest = `./packages/babel-types/src/${helperKind}/generated/`;
function generateHelpers(generator, dest, filename, message) {
const formatCode = require("./scripts/utils/formatCode");
const stream = gulp
.src(".", { base: __dirname })
Expand All @@ -101,14 +100,9 @@ function generateTypeHelpers(helperKind, filename = "index.ts") {
through.obj(function (file, enc, callback) {
file.path = filename;
file.contents = Buffer.from(
formatCode(
require(`./packages/babel-types/scripts/generators/${helperKind}`)(
filename
),
dest + file.path
)
formatCode(require(generator)(filename), dest + file.path)
);
fancyLog(`${chalk.green("✔")} Generated ${helperKind}`);
fancyLog(`${chalk.green("✔")} Generated ${message}`);
callback(null, file);
})
)
Expand All @@ -117,6 +111,35 @@ function generateTypeHelpers(helperKind, filename = "index.ts") {
return finish(stream);
}

/**
*
* @typedef {("asserts" | "builders" | "constants" | "validators")} TypesHelperKind
* @param {TypesHelperKind} helperKind
* @param {string} filename
*/
async function generateTypeHelpers(helperKind, filename = "index.ts") {
return generateHelpers(
`./packages/babel-types/scripts/generators/${helperKind}`,
`./packages/babel-types/src/${helperKind}/generated/`,
filename,
`@babel/types -> ${helperKind}`
);
}

/**
*
* @typedef {("asserts" | "validators" | "virtual-types")} TraverseHelperKind
* @param {TraverseHelperKind} helperKind
*/
async function generateTraverseHelpers(helperKind) {
return generateHelpers(
`./packages/babel-traverse/scripts/generators/${helperKind}`,
`./packages/babel-traverse/src/path/generated/`,
`${helperKind}.ts`,
`@babel/traverse -> ${helperKind}`
);
}

function generateStandalone() {
const dest = "./packages/babel-standalone/src/generated/";
const formatCode = require("./scripts/utils/formatCode");
Expand Down Expand Up @@ -383,7 +406,7 @@ const standaloneBundle = [
];

gulp.task("generate-type-helpers", () => {
fancyLog("Generating @babel/types dynamic functions");
fancyLog("Generating @babel/types and @babel/traverse dynamic functions");

return Promise.all([
generateTypeHelpers("asserts"),
Expand All @@ -392,6 +415,9 @@ gulp.task("generate-type-helpers", () => {
generateTypeHelpers("constants"),
generateTypeHelpers("validators"),
generateTypeHelpers("ast-types"),
generateTraverseHelpers("asserts"),
generateTraverseHelpers("validators"),
generateTraverseHelpers("virtual-types"),
]);
});

Expand Down
4 changes: 4 additions & 0 deletions lib/babel-packages.js.flow
Expand Up @@ -168,3 +168,7 @@ declare module "@babel/helper-function-name" {
declare module "@babel/helper-split-export-declaration" {
declare export default function splitExportDeclaration(exportDeclaration: any): any;
}

declare module "@babel/traverse" {
declare module.exports: any;
}
26 changes: 26 additions & 0 deletions packages/babel-traverse/scripts/generators/asserts.js
@@ -0,0 +1,26 @@
"use strict";
const t = require("@babel/types");

module.exports = function generateAsserts() {
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import * as t from "@babel/types";
import NodePath from "../index";
export interface NodePathAssetions {`;

for (const type of t.TYPES) {
output += `
assert${type}(
opts?: object,
): asserts this is NodePath<t.${type}>;`;
}

output += `
}`;

return output;
};
37 changes: 37 additions & 0 deletions packages/babel-traverse/scripts/generators/validators.js
@@ -0,0 +1,37 @@
"use strict";

const t = require("@babel/types");
const virtualTypes = require("../../lib/path/lib/virtual-types");

const definitions = require("@babel/types/lib/definitions");

module.exports = function generateValidators() {
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import * as t from "@babel/types";
import NodePath from "../index";
export interface NodePathValidators {
`;

for (const type of t.TYPES) {
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
}

for (const type of Object.keys(virtualTypes)) {
if (type[0] === "_") continue;
if (definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]) {
output += `is${type}(opts?: object): this is NodePath<t.${type}>;`;
} else {
output += `is${type}(opts?: object): boolean;`;
}
}

output += `
}
`;

return output;
};
26 changes: 26 additions & 0 deletions packages/babel-traverse/scripts/generators/virtual-types.js
@@ -0,0 +1,26 @@
"use strict";

const virtualTypes = require("../../lib/path/lib/virtual-types");

module.exports = function generateValidators() {
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import * as t from "@babel/types";
export interface VirtualTypeAliases {
`;

for (const type of Object.keys(virtualTypes)) {
output += ` ${type}: ${(virtualTypes[type].types || ["Node"])
.map(t => `t.${t}`)
.join(" | ")};`;
}

output += `
}
`;

return output;
};
File renamed without changes.
@@ -1,5 +1,6 @@
import NodePath from "./path";
import * as t from "@babel/types";
import type Scope from "./scope";

const testing = process.env.NODE_ENV === "test";

Expand All @@ -12,10 +13,12 @@ export default class TraversalContext {
}

declare parentPath: NodePath;
declare scope;
declare scope: Scope;
declare state;
declare opts;
queue: ?Array<NodePath> = null;
queue: Array<NodePath> | null = null;
priorityQueue: Array<NodePath> | null = null;
declare trap?: boolean;

/**
* This method does a simple check to determine whether or not we really need to attempt
Expand All @@ -30,7 +33,7 @@ export default class TraversalContext {
if (opts[node.type]) return true;

// check if we're going to traverse into this node
const keys: ?Array<string> = t.VISITOR_KEYS[node.type];
const keys: Array<string> | undefined = t.VISITOR_KEYS[node.type];
if (!keys?.length) return false;

// we need to traverse into this node so ensure that it has children to traverse into!
Expand All @@ -41,7 +44,7 @@ export default class TraversalContext {
return false;
}

create(node, obj, key, listKey): NodePath {
create(node, obj, key, listKey?): NodePath {
// We don't need to `.setContext()` here, since `.visitQueue()` already
// calls `.pushContext`.
return NodePath.get({
Expand Down
@@ -1,10 +1,10 @@
import type Scope from "./scope";

export interface HubInterface {
getCode(): ?string;
getScope(): ?Scope;
addHelper(name: string): Object;
buildError(node: Object, msg: string, Error: Class<Error>): Error;
getCode(): string | void;
getScope(): Scope | void;
addHelper(name: string): any;
buildError(node: any, msg: string, Error: new () => Error): Error;
}

export default class Hub implements HubInterface {
Expand Down
Expand Up @@ -2,23 +2,50 @@ import TraversalContext from "./context";
import * as visitors from "./visitors";
import * as t from "@babel/types";
import * as cache from "./cache";
import type NodePath from "./path";
import type Scope from "./scope";
import type { Visitor } from "./types";

export type { Visitor };
export { default as NodePath } from "./path";
export { default as Scope } from "./scope";
export { default as Hub } from "./hub";
export type { HubInterface } from "./hub";

export { visitors };

export default function traverse(
parent: Object | Array<Object>,
opts?: Object,
scope?: Object,
state: Object,
parentPath: Object,
export type TraverseOptions<S = t.Node> =
| {
scope?: Scope;
noScope?: boolean;
denylist?: string[];
}
| Visitor<S>;

function traverse<S>(
parent: t.Node,
opts: TraverseOptions<S>,
scope: Scope | undefined,
state: S,
parentPath?: NodePath,
): void;

function traverse(
parent: t.Node,
opts: TraverseOptions,
scope?: Scope,
state?: any,
parentPath?: NodePath,
): void;

function traverse(
parent: t.Node,
opts: TraverseOptions = {},
scope?: Scope,
state?: any,
parentPath?: NodePath,
) {
if (!parent) return;
if (!opts) opts = {};

if (!opts.noScope && !scope) {
if (parent.type !== "Program" && parent.type !== "File") {
Expand All @@ -39,6 +66,8 @@ export default function traverse(
traverse.node(parent, opts, scope, state, parentPath);
}

export default traverse;

traverse.visitors = visitors;
traverse.verify = visitors.verify;
traverse.explode = visitors.explode;
Expand All @@ -48,14 +77,14 @@ traverse.cheap = function (node, enter) {
};

traverse.node = function (
node: Object,
opts: Object,
scope: Object,
state: Object,
parentPath: Object,
node: t.Node,
opts: TraverseOptions,
scope?: Scope,
state?: any,
parentPath?: NodePath,
skipKeys?,
) {
const keys: Array = t.VISITOR_KEYS[node.type];
const keys = t.VISITOR_KEYS[node.type];
if (!keys) return;

const context = new TraversalContext(scope, opts, state, parentPath);
Expand All @@ -65,27 +94,27 @@ traverse.node = function (
}
};

traverse.clearNode = function (node, opts) {
traverse.clearNode = function (node: t.Node, opts?) {
t.removeProperties(node, opts);

cache.path.delete(node);
};

traverse.removeProperties = function (tree, opts) {
traverse.removeProperties = function (tree, opts?) {
t.traverseFast(tree, traverse.clearNode, opts);
return tree;
};

function hasDenylistedType(path, state) {
function hasDenylistedType(path: NodePath, state) {
if (path.node.type === state.type) {
state.has = true;
path.stop();
}
}

traverse.hasType = function (
tree: Object,
type: Object,
tree: any,
type: any,
denylistTypes?: Array<string>,
): boolean {
// the node we're searching in is denylisted
Expand Down

0 comments on commit d98418e

Please sign in to comment.