Convert @babel/traverse to TypeScript (#12488)

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Bogdan Savluk 2021-01-24 01:33:09 +01:00 committed by GitHub
parent cd090e9842
commit d98418efbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 2023 additions and 368 deletions

View File

@ -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 })
@ -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);
})
)
@ -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");
@ -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"),
@ -392,6 +415,9 @@ gulp.task("generate-type-helpers", () => {
generateTypeHelpers("constants"),
generateTypeHelpers("validators"),
generateTypeHelpers("ast-types"),
generateTraverseHelpers("asserts"),
generateTraverseHelpers("validators"),
generateTraverseHelpers("virtual-types"),
]);
});

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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";
@ -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
@ -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!
@ -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({

View File

@ -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 {

View File

@ -2,7 +2,11 @@ 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";
@ -10,15 +14,38 @@ 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") {
@ -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;
@ -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);
@ -65,18 +94,18 @@ 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();
@ -84,8 +113,8 @@ function hasDenylistedType(path, state) {
}
traverse.hasType = function (
tree: Object,
type: Object,
tree: any,
type: any,
denylistTypes?: Array<string>,
): boolean {
// the node we're searching in is denylisted

View File

@ -10,7 +10,9 @@ import NodePath from "./index";
* truthy value.
*/
export function findParent(callback): ?NodePath {
export function findParent(
callback: (path: NodePath) => boolean,
): NodePath | null {
let path = this;
while ((path = path.parentPath)) {
if (callback(path)) return path;
@ -24,7 +26,10 @@ export function findParent(callback): ?NodePath {
* or `null` if the `callback` never returns a truthy value.
*/
export function find(callback): ?NodePath {
export function find(
this: NodePath,
callback: (path: NodePath) => boolean,
): NodePath | null {
let path = this;
do {
if (callback(path)) return path;
@ -36,15 +41,15 @@ export function find(callback): ?NodePath {
* Get the parent function of the current path.
*/
export function getFunctionParent(): ?NodePath {
return this.findParent(p => p.isFunction());
export function getFunctionParent(this: NodePath): NodePath<t.Function> | null {
return this.findParent(p => p.isFunction()) as NodePath<t.Function> | null;
}
/**
* Walk up the tree until we hit a parent node path in a list.
*/
export function getStatementParent(): NodePath {
export function getStatementParent(this: NodePath): NodePath<t.Statement> {
let path = this;
do {
@ -64,7 +69,7 @@ export function getStatementParent(): NodePath {
);
}
return path;
return path as NodePath<t.Statement>;
}
/**
@ -76,6 +81,7 @@ export function getStatementParent(): NodePath {
*/
export function getEarliestCommonAncestorFrom(
this: NodePath,
paths: Array<NodePath>,
): NodePath {
return this.getDeepestCommonAncestorFrom(
@ -84,7 +90,7 @@ export function getEarliestCommonAncestorFrom(
let earliest;
const keys = t.VISITOR_KEYS[deepest.type];
for (const ancestry of (ancestries: Array)) {
for (const ancestry of ancestries) {
const path = ancestry[i + 1];
// first path
@ -104,7 +110,7 @@ export function getEarliestCommonAncestorFrom(
// handle keys
const earliestKeyIndex = keys.indexOf(earliest.parentKey);
const currentKeyIndex = keys.indexOf(path.parentKey);
const currentKeyIndex = keys.indexOf(path.parentKey as string);
if (earliestKeyIndex > currentKeyIndex) {
// key appears before so it's earlier
earliest = path;
@ -123,8 +129,9 @@ export function getEarliestCommonAncestorFrom(
*/
export function getDeepestCommonAncestorFrom(
this: NodePath,
paths: Array<NodePath>,
filter?: Function,
filter?: (deepest: t.Node, i: number, ancestries: NodePath[][]) => NodePath,
): NodePath {
if (!paths.length) {
return this;
@ -142,7 +149,7 @@ export function getDeepestCommonAncestorFrom(
// get the ancestors of the path, breaking when the parent exceeds ourselves
const ancestries = paths.map(path => {
const ancestry = [];
const ancestry: NodePath[] = [];
do {
ancestry.unshift(path);
@ -163,7 +170,7 @@ export function getDeepestCommonAncestorFrom(
depthLoop: for (let i = 0; i < minDepth; i++) {
const shouldMatch = first[i];
for (const ancestry of (ancestries: Array)) {
for (const ancestry of ancestries) {
if (ancestry[i] !== shouldMatch) {
// we've hit a snag
break depthLoop;
@ -192,7 +199,7 @@ export function getDeepestCommonAncestorFrom(
* NOTE: The current node path is included in this.
*/
export function getAncestry(): Array<NodePath> {
export function getAncestry(this: NodePath): Array<NodePath> {
let path = this;
const paths = [];
do {
@ -204,21 +211,21 @@ export function getAncestry(): Array<NodePath> {
/**
* A helper to find if `this` path is an ancestor of @param maybeDescendant
*/
export function isAncestor(maybeDescendant: NodePath): boolean {
export function isAncestor(this: NodePath, maybeDescendant: NodePath): boolean {
return maybeDescendant.isDescendant(this);
}
/**
* A helper to find if `this` path is a descendant of @param maybeAncestor
*/
export function isDescendant(maybeAncestor: NodePath): boolean {
export function isDescendant(this: NodePath, maybeAncestor: NodePath): boolean {
return !!this.findParent(parent => parent === maybeAncestor);
}
export function inType(): boolean {
export function inType(this: NodePath, ...candidateTypes: string[]): boolean {
let path = this;
while (path) {
for (const type of (arguments: Array)) {
for (const type of candidateTypes) {
if (path.node.type === type) return true;
}
path = path.parentPath;

View File

@ -1,11 +1,12 @@
// This file contains methods responsible for dealing with comments.
import * as t from "@babel/types";
import type NodePath from "./index";
/**
* Share comments amongst siblings.
*/
export function shareCommentsWithSiblings() {
export function shareCommentsWithSiblings(this: NodePath) {
// NOTE: this assumes numbered keys
if (typeof this.key === "string") return;
@ -27,7 +28,12 @@ export function shareCommentsWithSiblings() {
}
}
export function addComment(type: string, content: string, line?: boolean) {
export function addComment(
this: NodePath,
type: t.CommentTypeShorthand,
content: string,
line?: boolean,
) {
t.addComment(this.node, type, content, line);
}
@ -35,6 +41,10 @@ export function addComment(type: string, content: string, line?: boolean) {
* Give node `comments` of the specified `type`.
*/
export function addComments(type: string, comments: Array) {
export function addComments(
this: NodePath,
type: t.CommentTypeShorthand,
comments: readonly t.Comment[],
) {
t.addComments(this.node, type, comments);
}

View File

@ -2,8 +2,10 @@
import traverse from "../index";
import { SHOULD_SKIP, SHOULD_STOP } from "./index";
import type TraversalContext from "../context";
import type NodePath from "./index";
export function call(key): boolean {
export function call(this: NodePath, key: string): boolean {
const opts = this.opts;
this.debug(key);
@ -19,7 +21,7 @@ export function call(key): boolean {
return false;
}
export function _call(fns?: Array<Function>): boolean {
export function _call(this: NodePath, fns?: Array<Function>): boolean {
if (!fns) return false;
for (const fn of fns) {
@ -51,7 +53,7 @@ export function _call(fns?: Array<Function>): boolean {
return false;
}
export function isDenylisted(): boolean {
export function isDenylisted(this: NodePath): boolean {
const denylist = this.opts.denylist ?? this.opts.blacklist;
return denylist && denylist.indexOf(this.node.type) > -1;
}
@ -59,7 +61,7 @@ export function isDenylisted(): boolean {
// TODO: Remove in Babel 8
export { isDenylisted as isBlacklisted };
export function visit(): boolean {
export function visit(this: NodePath): boolean {
if (!this.node) {
return false;
}
@ -97,23 +99,23 @@ export function visit(): boolean {
return this.shouldStop;
}
export function skip() {
export function skip(this: NodePath) {
this.shouldSkip = true;
}
export function skipKey(key) {
export function skipKey(this: NodePath, key: string) {
if (this.skipKeys == null) {
this.skipKeys = {};
}
this.skipKeys[key] = true;
}
export function stop() {
export function stop(this: NodePath) {
// this.shouldSkip = true; this.shouldStop = true;
this._traverseFlags |= SHOULD_SKIP | SHOULD_STOP;
}
export function setScope() {
export function setScope(this: NodePath) {
if (this.opts && this.opts.noScope) return;
let path = this.parentPath;
@ -129,7 +131,7 @@ export function setScope() {
if (this.scope) this.scope.init();
}
export function setContext(context) {
export function setContext(this: NodePath, context?: TraversalContext) {
if (this.skipKeys != null) {
this.skipKeys = {};
}
@ -153,7 +155,7 @@ export function setContext(context) {
* for the new values.
*/
export function resync() {
export function resync(this: NodePath) {
if (this.removed) return;
this._resyncParent();
@ -162,13 +164,13 @@ export function resync() {
//this._resyncRemoved();
}
export function _resyncParent() {
export function _resyncParent(this: NodePath) {
if (this.parentPath) {
this.parent = this.parentPath.node;
}
}
export function _resyncKey() {
export function _resyncKey(this: NodePath) {
if (!this.container) return;
if (this.node === this.container[this.key]) return;
@ -194,7 +196,7 @@ export function _resyncKey() {
this.key = null;
}
export function _resyncList() {
export function _resyncList(this: NodePath) {
if (!this.parent || !this.inList) return;
const newContainer = this.parent[this.listKey];
@ -204,7 +206,7 @@ export function _resyncList() {
this.container = newContainer || null;
}
export function _resyncRemoved() {
export function _resyncRemoved(this: NodePath) {
if (
this.key == null ||
!this.container ||
@ -214,7 +216,7 @@ export function _resyncRemoved() {
}
}
export function popContext() {
export function popContext(this: NodePath) {
this.contexts.pop();
if (this.contexts.length > 0) {
this.setContext(this.contexts[this.contexts.length - 1]);
@ -223,12 +225,12 @@ export function popContext() {
}
}
export function pushContext(context) {
export function pushContext(this: NodePath, context: TraversalContext) {
this.contexts.push(context);
this.setContext(context);
}
export function setup(parentPath, container, listKey, key) {
export function setup(this: NodePath, parentPath, container, listKey, key) {
this.listKey = listKey;
this.container = container;
@ -236,13 +238,13 @@ export function setup(parentPath, container, listKey, key) {
this.setKey(key);
}
export function setKey(key) {
export function setKey(this: NodePath, key) {
this.key = key;
this.node = this.container[this.key];
this.type = this.node?.type;
}
export function requeue(pathToQueue = this) {
export function requeue(this: NodePath, pathToQueue = this) {
if (pathToQueue.removed) return;
// TODO: Uncomment in Babel 8. If a path is skipped, and then replaced with a
@ -263,7 +265,7 @@ export function requeue(pathToQueue = this) {
}
}
export function _getQueueContexts() {
export function _getQueueContexts(this: NodePath) {
let path = this;
let contexts = this.contexts;
while (!contexts.length) {

View File

@ -2,27 +2,31 @@
import * as t from "@babel/types";
import nameFunction from "@babel/helper-function-name";
import type NodePath from "./index";
export function toComputedKey(): Object {
const node = this.node;
export function toComputedKey(this: NodePath) {
let key;
if (this.isMemberExpression()) {
key = node.property;
key = this.node.property;
} else if (this.isProperty() || this.isMethod()) {
key = node.key;
key = this.node.key;
} else {
throw new ReferenceError("todo");
}
if (!node.computed) {
// @ts-expect-error todo(flow->ts) computed does not exist in ClassPrivateProperty
if (!this.node.computed) {
if (t.isIdentifier(key)) key = t.stringLiteral(key.name);
}
return key;
}
export function ensureBlock() {
export function ensureBlock(
this: NodePath<
t.Loop | t.WithStatement | t.Function | t.LabeledStatement | t.CatchClause
>,
) {
const body = this.get("body");
const bodyNode = body.node;
@ -37,7 +41,7 @@ export function ensureBlock() {
return bodyNode;
}
const statements = [];
const statements: Array<t.Statement> = [];
let stringPath = "body";
let key;
@ -50,15 +54,15 @@ export function ensureBlock() {
stringPath += ".body.0";
if (this.isFunction()) {
key = "argument";
statements.push(t.returnStatement(body.node));
statements.push(t.returnStatement(body.node as t.Expression));
} else {
key = "expression";
statements.push(t.expressionStatement(body.node));
statements.push(t.expressionStatement(body.node as t.Expression));
}
}
this.node.body = t.blockStatement(statements);
const parentPath = this.get(stringPath);
const parentPath = this.get(stringPath) as NodePath;
body.setup(
parentPath,
listKey ? parentPath.node[listKey] : parentPath.node,
@ -72,7 +76,7 @@ export function ensureBlock() {
/**
* Keeping this for backward-compatibility. You should use arrowFunctionToExpression() for >=7.x.
*/
export function arrowFunctionToShadowed() {
export function arrowFunctionToShadowed(this: NodePath) {
if (!this.isArrowFunctionExpression()) return;
this.arrowFunctionToExpression();
@ -84,7 +88,7 @@ export function arrowFunctionToShadowed() {
* you have wrapped some set of items in an IIFE or other function, but want "this", "arguments", and super"
* to continue behaving as expected.
*/
export function unwrapFunctionEnvironment() {
export function unwrapFunctionEnvironment(this: NodePath) {
if (
!this.isArrowFunctionExpression() &&
!this.isFunctionExpression() &&
@ -101,10 +105,10 @@ export function unwrapFunctionEnvironment() {
/**
* Convert a given arrow function into a normal ES5 function expression.
*/
export function arrowFunctionToExpression({
allowInsertArrow = true,
specCompliant = false,
} = {}) {
export function arrowFunctionToExpression(
this: NodePath,
{ allowInsertArrow = true, specCompliant = false } = {},
) {
if (!this.isArrowFunctionExpression()) {
throw this.buildCodeFrameError(
"Cannot convert non-arrow function to a function expression.",
@ -118,6 +122,7 @@ export function arrowFunctionToExpression({
);
this.ensureBlock();
// @ts-expect-error todo(flow->ts): avoid mutating nodes
this.node.type = "FunctionExpression";
if (specCompliant) {
const checkBinding = thisBinding
@ -392,7 +397,7 @@ function standardizeSuperProperty(superProp) {
? superProp.scope.generateDeclaredUidIdentifier("prop")
: null;
const parts = [
const parts: t.Expression[] = [
t.assignmentExpression(
"=",
tmp,

View File

@ -23,7 +23,7 @@ const INVALID_METHODS = ["random"];
*
*/
export function evaluateTruthy(): boolean {
export function evaluateTruthy(this: NodePath): boolean {
const res = this.evaluate();
if (res.confident) return !!res.value;
}
@ -45,7 +45,7 @@ function deopt(path, state) {
* var g = a ? 1 : 2,
* a = g * this.foo
*/
function evaluateCached(path, state) {
function evaluateCached(path: NodePath, state) {
const { node } = path;
const { seen } = state;
@ -58,7 +58,8 @@ function evaluateCached(path, state) {
return;
}
} else {
const item = { resolved: false };
// todo: create type annotation for state instead
const item: { resolved: boolean; value?: any } = { resolved: false };
seen.set(node, item);
const val = _evaluate(path, state);
@ -70,11 +71,9 @@ function evaluateCached(path, state) {
}
}
function _evaluate(path, state) {
function _evaluate(path: NodePath, state) {
if (!state.confident) return;
const { node } = path;
if (path.isSequenceExpression()) {
const exprs = path.get("expressions");
return evaluateCached(exprs[exprs.length - 1], state);
@ -85,7 +84,7 @@ function _evaluate(path, state) {
path.isNumericLiteral() ||
path.isBooleanLiteral()
) {
return node.value;
return path.node.value;
}
if (path.isNullLiteral()) {
@ -93,27 +92,30 @@ function _evaluate(path, state) {
}
if (path.isTemplateLiteral()) {
return evaluateQuasis(path, node.quasis, state);
return evaluateQuasis(path, path.node.quasis, state);
}
if (
path.isTaggedTemplateExpression() &&
path.get("tag").isMemberExpression()
) {
const object = path.get("tag.object");
const object = path.get("tag.object") as NodePath;
const {
// @ts-expect-error todo(flow->ts): possible bug, object is can be any expression and so name might be undefined
node: { name },
} = object;
const property = path.get("tag.property");
const property = path.get("tag.property") as NodePath;
if (
object.isIdentifier() &&
name === "String" &&
!path.scope.getBinding(name, true) &&
property.isIdentifier &&
// todo(flow->ts): was changed from getBinding(name, true)
// should this be hasBinding(name, true) as the binding is never used later?
!path.scope.getBinding(name) &&
property.isIdentifier() &&
property.node.name === "raw"
) {
return evaluateQuasis(path, node.quasi.quasis, state, true);
return evaluateQuasis(path, path.node.quasi.quasis, state, true);
}
}
@ -135,12 +137,13 @@ function _evaluate(path, state) {
// "foo".length
if (
path.isMemberExpression() &&
!path.parentPath.isCallExpression({ callee: node })
!path.parentPath.isCallExpression({ callee: path.node })
) {
const property = path.get("property");
const object = path.get("object");
const property = path.get("property") as NodePath;
const object = path.get("object") as NodePath;
if (object.isLiteral() && property.isIdentifier()) {
// @ts-expect-error todo(flow->ts): instead of typeof - would it be better to check type of ast node?
const value = object.node.value;
const type = typeof value;
if (type === "number" || type === "string") {
@ -150,7 +153,8 @@ function _evaluate(path, state) {
}
if (path.isReferencedIdentifier()) {
const binding = path.scope.getBinding(node.name);
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
const binding = path.scope.getBinding(path.node.name);
if (binding && binding.constantViolations.length > 0) {
return deopt(binding.path, state);
@ -163,11 +167,14 @@ function _evaluate(path, state) {
if (binding?.hasValue) {
return binding.value;
} else {
if (node.name === "undefined") {
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
if (path.node.name === "undefined") {
return binding ? deopt(binding.path, state) : undefined;
} else if (node.name === "Infinity") {
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
} else if (path.node.name === "Infinity") {
return binding ? deopt(binding.path, state) : Infinity;
} else if (node.name === "NaN") {
// @ts-expect-error todo(flow->ts): consider separating type refinement and check for reference
} else if (path.node.name === "NaN") {
return binding ? deopt(binding.path, state) : NaN;
}
@ -181,14 +188,14 @@ function _evaluate(path, state) {
}
if (path.isUnaryExpression({ prefix: true })) {
if (node.operator === "void") {
if (path.node.operator === "void") {
// we don't need to evaluate the argument to know what this will return
return undefined;
}
const argument = path.get("argument");
if (
node.operator === "typeof" &&
path.node.operator === "typeof" &&
(argument.isFunction() || argument.isClass())
) {
return "function";
@ -196,7 +203,7 @@ function _evaluate(path, state) {
const arg = evaluateCached(argument, state);
if (!state.confident) return;
switch (node.operator) {
switch (path.node.operator) {
case "!":
return !arg;
case "+":
@ -227,13 +234,14 @@ function _evaluate(path, state) {
if (path.isObjectExpression()) {
const obj = {};
const props: Array<NodePath> = path.get("properties");
const props = path.get("properties");
for (const prop of props) {
if (prop.isObjectMethod() || prop.isSpreadElement()) {
return deopt(prop, state);
}
const keyPath = prop.get("key");
const keyPath: any = prop.get("key");
let key = keyPath;
// @ts-expect-error todo(flow->ts): type refinement issues ObjectMethod and SpreadElement somehow not excluded
if (prop.node.computed) {
key = key.evaluate();
if (!key.confident) {
@ -245,7 +253,8 @@ function _evaluate(path, state) {
} else {
key = key.node.value;
}
const valuePath = prop.get("value");
// todo(flow->ts): remove typecast
const valuePath = prop.get("value") as NodePath;
let value = valuePath.evaluate();
if (!value.confident) {
return deopt(value.deopt, state);
@ -266,7 +275,7 @@ function _evaluate(path, state) {
const right = evaluateCached(path.get("right"), state);
const rightConfident = state.confident;
switch (node.operator) {
switch (path.node.operator) {
case "||":
// TODO consider having a "truthy type" that doesn't bail on
// left uncertainty but can still evaluate to truthy.
@ -288,7 +297,7 @@ function _evaluate(path, state) {
const right = evaluateCached(path.get("right"), state);
if (!state.confident) return;
switch (node.operator) {
switch (path.node.operator) {
case "-":
return left - right;
case "+":
@ -340,15 +349,16 @@ function _evaluate(path, state) {
// Number(1);
if (
callee.isIdentifier() &&
!path.scope.getBinding(callee.node.name, true) &&
!path.scope.getBinding(callee.node.name) &&
VALID_CALLEES.indexOf(callee.node.name) >= 0
) {
func = global[node.callee.name];
func = global[callee.node.name];
}
if (callee.isMemberExpression()) {
const object = callee.get("object");
const property = callee.get("property");
// todo: improve babel-types
const property = callee.get("property") as NodePath;
// Math.min(1, 2)
if (
@ -363,8 +373,10 @@ function _evaluate(path, state) {
// "abc".charCodeAt(4)
if (object.isLiteral() && property.isIdentifier()) {
// @ts-expect-error todo(flow->ts): consider checking ast node type instead of value type (StringLiteral and NumberLiteral)
const type = typeof object.node.value;
if (type === "string" || type === "number") {
// @ts-expect-error todo(flow->ts): consider checking ast node type instead of value type
context = object.node.value;
func = context[property.node.name];
}
@ -382,7 +394,7 @@ function _evaluate(path, state) {
deopt(path, state);
}
function evaluateQuasis(path, quasis: Array<Object>, state, raw = false) {
function evaluateQuasis(path, quasis: Array<any>, state, raw = false) {
let str = "";
let i = 0;
@ -420,10 +432,12 @@ function evaluateQuasis(path, quasis: Array<Object>, state, raw = false) {
*
*/
export function evaluate(): {
confident: boolean,
value: any,
deopt?: NodePath,
export function evaluate(
this: NodePath,
): {
confident: boolean;
value: any;
deopt?: NodePath;
} {
const state = {
confident: true,

View File

@ -1,24 +1,27 @@
// @flow
// This file contains methods responsible for dealing with/retrieving children or siblings.
import type TraversalContext from "../index";
import type TraversalContext from "../context";
import NodePath from "./index";
import * as t from "@babel/types";
export function getOpposite(): ?NodePath {
export function getOpposite(this: NodePath): NodePath | null {
if (this.key === "left") {
return this.getSibling("right");
} else if (this.key === "right") {
return this.getSibling("left");
}
return null;
}
function addCompletionRecords(path, paths) {
function addCompletionRecords(
path: NodePath | null | undefined,
paths: NodePath[],
): NodePath[] {
if (path) return paths.concat(path.getCompletionRecords());
return paths;
}
function findBreak(statements): ?NodePath {
function findBreak(statements): NodePath | null {
let breakStatement;
if (!Array.isArray(statements)) {
statements = [statements];
@ -94,15 +97,17 @@ function completionRecordForSwitch(cases, paths) {
return paths;
}
export function getCompletionRecords(): NodePath[] {
export function getCompletionRecords(this: NodePath): NodePath[] {
let paths = [];
if (this.isIfStatement()) {
paths = addCompletionRecords(this.get("consequent"), paths);
paths = addCompletionRecords(this.get("alternate"), paths);
} else if (this.isDoExpression() || this.isFor() || this.isWhile()) {
// @ts-expect-error(flow->ts): todo
paths = addCompletionRecords(this.get("body"), paths);
} else if (this.isProgram() || this.isBlockStatement()) {
// @ts-expect-error(flow->ts): todo
paths = addCompletionRecords(this.get("body").pop(), paths);
} else if (this.isFunction()) {
return this.get("body").getCompletionRecords();
@ -120,7 +125,7 @@ export function getCompletionRecords(): NodePath[] {
return paths;
}
export function getSibling(key: string): NodePath {
export function getSibling(this: NodePath, key: string | number): NodePath {
return NodePath.get({
parentPath: this.parentPath,
parent: this.parent,
@ -130,16 +135,19 @@ export function getSibling(key: string): NodePath {
}).setContext(this.context);
}
export function getPrevSibling(): NodePath {
export function getPrevSibling(this: NodePath): NodePath {
// @ts-expect-error todo(flow->ts) this.key could be a string
return this.getSibling(this.key - 1);
}
export function getNextSibling(): NodePath {
export function getNextSibling(this: NodePath): NodePath {
// @ts-expect-error todo(flow->ts) this.key could be a string
return this.getSibling(this.key + 1);
}
export function getAllNextSiblings(): NodePath[] {
let _key = this.key;
export function getAllNextSiblings(this: NodePath): NodePath[] {
// @ts-expect-error todo(flow->ts) this.key could be a string
let _key: number = this.key;
let sibling = this.getSibling(++_key);
const siblings = [];
while (sibling.node) {
@ -149,8 +157,9 @@ export function getAllNextSiblings(): NodePath[] {
return siblings;
}
export function getAllPrevSiblings(): NodePath[] {
let _key = this.key;
export function getAllPrevSiblings(this: NodePath): NodePath[] {
// @ts-expect-error todo(flow->ts) this.key could be a string
let _key: number = this.key;
let sibling = this.getSibling(--_key);
const siblings = [];
while (sibling.node) {
@ -160,9 +169,26 @@ export function getAllPrevSiblings(): NodePath[] {
return siblings;
}
export function get(
function get<T extends t.Node, K extends keyof T>(
this: NodePath<T>,
key: K,
context?: boolean | TraversalContext,
): T[K] extends Array<t.Node | null | undefined>
? Array<NodePath<T[K][number]>>
: T[K] extends t.Node | null | undefined
? NodePath<T[K]>
: never;
function get<T extends t.Node>(
this: NodePath<T>,
key: string,
context?: boolean | TraversalContext = true,
context?: true | TraversalContext,
): NodePath | NodePath[];
function get<T extends t.Node>(
this: NodePath<T>,
key: string,
context: true | TraversalContext = true,
): NodePath | NodePath[] {
if (context === true) context = this.context;
const parts = key.split(".");
@ -175,7 +201,10 @@ export function get(
}
}
export function _getKey(
export { get };
export function _getKey<T extends t.Node>(
this: NodePath<T>,
key: string,
context?: TraversalContext,
): NodePath | NodePath[] {
@ -204,12 +233,14 @@ export function _getKey(
}
export function _getPattern(
this: NodePath,
parts: string[],
context?: TraversalContext,
): NodePath | NodePath[] {
let path = this;
let path: NodePath | NodePath[] = this;
for (const part of parts) {
if (part === ".") {
// @ts-expect-error todo(flow-ts): Can path be an array here?
path = path.parentPath;
} else {
if (Array.isArray(path)) {
@ -222,21 +253,52 @@ export function _getPattern(
return path;
}
export function getBindingIdentifiers(duplicates?: boolean): Object {
function getBindingIdentifiers(
duplicates: true,
): Record<string, t.Identifier[]>;
function getBindingIdentifiers(
duplicates?: false,
): Record<string, t.Identifier>;
function getBindingIdentifiers(
duplicates: boolean,
): Record<string, t.Identifier[] | t.Identifier>;
function getBindingIdentifiers(
duplicates?: boolean,
): Record<string, t.Identifier[] | t.Identifier> {
return t.getBindingIdentifiers(this.node, duplicates);
}
export function getOuterBindingIdentifiers(duplicates?: boolean): Object {
export { getBindingIdentifiers };
function getOuterBindingIdentifiers(
duplicates: true,
): Record<string, t.Identifier[]>;
function getOuterBindingIdentifiers(
duplicates?: false,
): Record<string, t.Identifier>;
function getOuterBindingIdentifiers(
duplicates: boolean,
): Record<string, t.Identifier[] | t.Identifier>;
function getOuterBindingIdentifiers(
duplicates?: boolean,
): Record<string, t.Identifier[] | t.Identifier> {
return t.getOuterBindingIdentifiers(this.node, duplicates);
}
export { getOuterBindingIdentifiers };
// original source - https://github.com/babel/babel/blob/main/packages/babel-types/src/retrievers/getBindingIdentifiers.js
// path.getBindingIdentifiers returns nodes where the following re-implementation
// returns paths
export function getBindingIdentifierPaths(
duplicates?: boolean = false,
outerOnly?: boolean = false,
): { [string]: NodePath } {
this: NodePath,
duplicates: boolean = false,
outerOnly: boolean = false,
): {
[x: string]: NodePath;
} {
const path = this;
let search = [].concat(path);
const ids = Object.create(null);
@ -292,7 +354,10 @@ export function getBindingIdentifierPaths(
}
export function getOuterBindingIdentifierPaths(
this: NodePath,
duplicates?: boolean,
): { [string]: NodePath } {
): {
[x: string]: NodePath;
} {
return this.getBindingIdentifierPaths(duplicates, true);
}

View File

@ -0,0 +1,688 @@
/*
* 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 {
assertAnyTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.AnyTypeAnnotation>;
assertArgumentPlaceholder(
opts?: object,
): asserts this is NodePath<t.ArgumentPlaceholder>;
assertArrayExpression(
opts?: object,
): asserts this is NodePath<t.ArrayExpression>;
assertArrayPattern(opts?: object): asserts this is NodePath<t.ArrayPattern>;
assertArrayTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.ArrayTypeAnnotation>;
assertArrowFunctionExpression(
opts?: object,
): asserts this is NodePath<t.ArrowFunctionExpression>;
assertAssignmentExpression(
opts?: object,
): asserts this is NodePath<t.AssignmentExpression>;
assertAssignmentPattern(
opts?: object,
): asserts this is NodePath<t.AssignmentPattern>;
assertAwaitExpression(
opts?: object,
): asserts this is NodePath<t.AwaitExpression>;
assertBigIntLiteral(opts?: object): asserts this is NodePath<t.BigIntLiteral>;
assertBinary(opts?: object): asserts this is NodePath<t.Binary>;
assertBinaryExpression(
opts?: object,
): asserts this is NodePath<t.BinaryExpression>;
assertBindExpression(
opts?: object,
): asserts this is NodePath<t.BindExpression>;
assertBlock(opts?: object): asserts this is NodePath<t.Block>;
assertBlockParent(opts?: object): asserts this is NodePath<t.BlockParent>;
assertBlockStatement(
opts?: object,
): asserts this is NodePath<t.BlockStatement>;
assertBooleanLiteral(
opts?: object,
): asserts this is NodePath<t.BooleanLiteral>;
assertBooleanLiteralTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.BooleanLiteralTypeAnnotation>;
assertBooleanTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.BooleanTypeAnnotation>;
assertBreakStatement(
opts?: object,
): asserts this is NodePath<t.BreakStatement>;
assertCallExpression(
opts?: object,
): asserts this is NodePath<t.CallExpression>;
assertCatchClause(opts?: object): asserts this is NodePath<t.CatchClause>;
assertClass(opts?: object): asserts this is NodePath<t.Class>;
assertClassBody(opts?: object): asserts this is NodePath<t.ClassBody>;
assertClassDeclaration(
opts?: object,
): asserts this is NodePath<t.ClassDeclaration>;
assertClassExpression(
opts?: object,
): asserts this is NodePath<t.ClassExpression>;
assertClassImplements(
opts?: object,
): asserts this is NodePath<t.ClassImplements>;
assertClassMethod(opts?: object): asserts this is NodePath<t.ClassMethod>;
assertClassPrivateMethod(
opts?: object,
): asserts this is NodePath<t.ClassPrivateMethod>;
assertClassPrivateProperty(
opts?: object,
): asserts this is NodePath<t.ClassPrivateProperty>;
assertClassProperty(opts?: object): asserts this is NodePath<t.ClassProperty>;
assertCompletionStatement(
opts?: object,
): asserts this is NodePath<t.CompletionStatement>;
assertConditional(opts?: object): asserts this is NodePath<t.Conditional>;
assertConditionalExpression(
opts?: object,
): asserts this is NodePath<t.ConditionalExpression>;
assertContinueStatement(
opts?: object,
): asserts this is NodePath<t.ContinueStatement>;
assertDebuggerStatement(
opts?: object,
): asserts this is NodePath<t.DebuggerStatement>;
assertDecimalLiteral(
opts?: object,
): asserts this is NodePath<t.DecimalLiteral>;
assertDeclaration(opts?: object): asserts this is NodePath<t.Declaration>;
assertDeclareClass(opts?: object): asserts this is NodePath<t.DeclareClass>;
assertDeclareExportAllDeclaration(
opts?: object,
): asserts this is NodePath<t.DeclareExportAllDeclaration>;
assertDeclareExportDeclaration(
opts?: object,
): asserts this is NodePath<t.DeclareExportDeclaration>;
assertDeclareFunction(
opts?: object,
): asserts this is NodePath<t.DeclareFunction>;
assertDeclareInterface(
opts?: object,
): asserts this is NodePath<t.DeclareInterface>;
assertDeclareModule(opts?: object): asserts this is NodePath<t.DeclareModule>;
assertDeclareModuleExports(
opts?: object,
): asserts this is NodePath<t.DeclareModuleExports>;
assertDeclareOpaqueType(
opts?: object,
): asserts this is NodePath<t.DeclareOpaqueType>;
assertDeclareTypeAlias(
opts?: object,
): asserts this is NodePath<t.DeclareTypeAlias>;
assertDeclareVariable(
opts?: object,
): asserts this is NodePath<t.DeclareVariable>;
assertDeclaredPredicate(
opts?: object,
): asserts this is NodePath<t.DeclaredPredicate>;
assertDecorator(opts?: object): asserts this is NodePath<t.Decorator>;
assertDirective(opts?: object): asserts this is NodePath<t.Directive>;
assertDirectiveLiteral(
opts?: object,
): asserts this is NodePath<t.DirectiveLiteral>;
assertDoExpression(opts?: object): asserts this is NodePath<t.DoExpression>;
assertDoWhileStatement(
opts?: object,
): asserts this is NodePath<t.DoWhileStatement>;
assertEmptyStatement(
opts?: object,
): asserts this is NodePath<t.EmptyStatement>;
assertEmptyTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.EmptyTypeAnnotation>;
assertEnumBody(opts?: object): asserts this is NodePath<t.EnumBody>;
assertEnumBooleanBody(
opts?: object,
): asserts this is NodePath<t.EnumBooleanBody>;
assertEnumBooleanMember(
opts?: object,
): asserts this is NodePath<t.EnumBooleanMember>;
assertEnumDeclaration(
opts?: object,
): asserts this is NodePath<t.EnumDeclaration>;
assertEnumDefaultedMember(
opts?: object,
): asserts this is NodePath<t.EnumDefaultedMember>;
assertEnumMember(opts?: object): asserts this is NodePath<t.EnumMember>;
assertEnumNumberBody(
opts?: object,
): asserts this is NodePath<t.EnumNumberBody>;
assertEnumNumberMember(
opts?: object,
): asserts this is NodePath<t.EnumNumberMember>;
assertEnumStringBody(
opts?: object,
): asserts this is NodePath<t.EnumStringBody>;
assertEnumStringMember(
opts?: object,
): asserts this is NodePath<t.EnumStringMember>;
assertEnumSymbolBody(
opts?: object,
): asserts this is NodePath<t.EnumSymbolBody>;
assertExistsTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.ExistsTypeAnnotation>;
assertExportAllDeclaration(
opts?: object,
): asserts this is NodePath<t.ExportAllDeclaration>;
assertExportDeclaration(
opts?: object,
): asserts this is NodePath<t.ExportDeclaration>;
assertExportDefaultDeclaration(
opts?: object,
): asserts this is NodePath<t.ExportDefaultDeclaration>;
assertExportDefaultSpecifier(
opts?: object,
): asserts this is NodePath<t.ExportDefaultSpecifier>;
assertExportNamedDeclaration(
opts?: object,
): asserts this is NodePath<t.ExportNamedDeclaration>;
assertExportNamespaceSpecifier(
opts?: object,
): asserts this is NodePath<t.ExportNamespaceSpecifier>;
assertExportSpecifier(
opts?: object,
): asserts this is NodePath<t.ExportSpecifier>;
assertExpression(opts?: object): asserts this is NodePath<t.Expression>;
assertExpressionStatement(
opts?: object,
): asserts this is NodePath<t.ExpressionStatement>;
assertExpressionWrapper(
opts?: object,
): asserts this is NodePath<t.ExpressionWrapper>;
assertFile(opts?: object): asserts this is NodePath<t.File>;
assertFlow(opts?: object): asserts this is NodePath<t.Flow>;
assertFlowBaseAnnotation(
opts?: object,
): asserts this is NodePath<t.FlowBaseAnnotation>;
assertFlowDeclaration(
opts?: object,
): asserts this is NodePath<t.FlowDeclaration>;
assertFlowPredicate(opts?: object): asserts this is NodePath<t.FlowPredicate>;
assertFlowType(opts?: object): asserts this is NodePath<t.FlowType>;
assertFor(opts?: object): asserts this is NodePath<t.For>;
assertForInStatement(
opts?: object,
): asserts this is NodePath<t.ForInStatement>;
assertForOfStatement(
opts?: object,
): asserts this is NodePath<t.ForOfStatement>;
assertForStatement(opts?: object): asserts this is NodePath<t.ForStatement>;
assertForXStatement(opts?: object): asserts this is NodePath<t.ForXStatement>;
assertFunction(opts?: object): asserts this is NodePath<t.Function>;
assertFunctionDeclaration(
opts?: object,
): asserts this is NodePath<t.FunctionDeclaration>;
assertFunctionExpression(
opts?: object,
): asserts this is NodePath<t.FunctionExpression>;
assertFunctionParent(
opts?: object,
): asserts this is NodePath<t.FunctionParent>;
assertFunctionTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.FunctionTypeAnnotation>;
assertFunctionTypeParam(
opts?: object,
): asserts this is NodePath<t.FunctionTypeParam>;
assertGenericTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.GenericTypeAnnotation>;
assertIdentifier(opts?: object): asserts this is NodePath<t.Identifier>;
assertIfStatement(opts?: object): asserts this is NodePath<t.IfStatement>;
assertImmutable(opts?: object): asserts this is NodePath<t.Immutable>;
assertImport(opts?: object): asserts this is NodePath<t.Import>;
assertImportAttribute(
opts?: object,
): asserts this is NodePath<t.ImportAttribute>;
assertImportDeclaration(
opts?: object,
): asserts this is NodePath<t.ImportDeclaration>;
assertImportDefaultSpecifier(
opts?: object,
): asserts this is NodePath<t.ImportDefaultSpecifier>;
assertImportNamespaceSpecifier(
opts?: object,
): asserts this is NodePath<t.ImportNamespaceSpecifier>;
assertImportSpecifier(
opts?: object,
): asserts this is NodePath<t.ImportSpecifier>;
assertInferredPredicate(
opts?: object,
): asserts this is NodePath<t.InferredPredicate>;
assertInterfaceDeclaration(
opts?: object,
): asserts this is NodePath<t.InterfaceDeclaration>;
assertInterfaceExtends(
opts?: object,
): asserts this is NodePath<t.InterfaceExtends>;
assertInterfaceTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.InterfaceTypeAnnotation>;
assertInterpreterDirective(
opts?: object,
): asserts this is NodePath<t.InterpreterDirective>;
assertIntersectionTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.IntersectionTypeAnnotation>;
assertJSX(opts?: object): asserts this is NodePath<t.JSX>;
assertJSXAttribute(opts?: object): asserts this is NodePath<t.JSXAttribute>;
assertJSXClosingElement(
opts?: object,
): asserts this is NodePath<t.JSXClosingElement>;
assertJSXClosingFragment(
opts?: object,
): asserts this is NodePath<t.JSXClosingFragment>;
assertJSXElement(opts?: object): asserts this is NodePath<t.JSXElement>;
assertJSXEmptyExpression(
opts?: object,
): asserts this is NodePath<t.JSXEmptyExpression>;
assertJSXExpressionContainer(
opts?: object,
): asserts this is NodePath<t.JSXExpressionContainer>;
assertJSXFragment(opts?: object): asserts this is NodePath<t.JSXFragment>;
assertJSXIdentifier(opts?: object): asserts this is NodePath<t.JSXIdentifier>;
assertJSXMemberExpression(
opts?: object,
): asserts this is NodePath<t.JSXMemberExpression>;
assertJSXNamespacedName(
opts?: object,
): asserts this is NodePath<t.JSXNamespacedName>;
assertJSXOpeningElement(
opts?: object,
): asserts this is NodePath<t.JSXOpeningElement>;
assertJSXOpeningFragment(
opts?: object,
): asserts this is NodePath<t.JSXOpeningFragment>;
assertJSXSpreadAttribute(
opts?: object,
): asserts this is NodePath<t.JSXSpreadAttribute>;
assertJSXSpreadChild(
opts?: object,
): asserts this is NodePath<t.JSXSpreadChild>;
assertJSXText(opts?: object): asserts this is NodePath<t.JSXText>;
assertLVal(opts?: object): asserts this is NodePath<t.LVal>;
assertLabeledStatement(
opts?: object,
): asserts this is NodePath<t.LabeledStatement>;
assertLiteral(opts?: object): asserts this is NodePath<t.Literal>;
assertLogicalExpression(
opts?: object,
): asserts this is NodePath<t.LogicalExpression>;
assertLoop(opts?: object): asserts this is NodePath<t.Loop>;
assertMemberExpression(
opts?: object,
): asserts this is NodePath<t.MemberExpression>;
assertMetaProperty(opts?: object): asserts this is NodePath<t.MetaProperty>;
assertMethod(opts?: object): asserts this is NodePath<t.Method>;
assertMixedTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.MixedTypeAnnotation>;
assertModuleDeclaration(
opts?: object,
): asserts this is NodePath<t.ModuleDeclaration>;
assertModuleSpecifier(
opts?: object,
): asserts this is NodePath<t.ModuleSpecifier>;
assertNewExpression(opts?: object): asserts this is NodePath<t.NewExpression>;
assertNoop(opts?: object): asserts this is NodePath<t.Noop>;
assertNullLiteral(opts?: object): asserts this is NodePath<t.NullLiteral>;
assertNullLiteralTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.NullLiteralTypeAnnotation>;
assertNullableTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.NullableTypeAnnotation>;
assertNumberLiteral(opts?: object): asserts this is NodePath<t.NumberLiteral>;
assertNumberLiteralTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.NumberLiteralTypeAnnotation>;
assertNumberTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.NumberTypeAnnotation>;
assertNumericLiteral(
opts?: object,
): asserts this is NodePath<t.NumericLiteral>;
assertObjectExpression(
opts?: object,
): asserts this is NodePath<t.ObjectExpression>;
assertObjectMember(opts?: object): asserts this is NodePath<t.ObjectMember>;
assertObjectMethod(opts?: object): asserts this is NodePath<t.ObjectMethod>;
assertObjectPattern(opts?: object): asserts this is NodePath<t.ObjectPattern>;
assertObjectProperty(
opts?: object,
): asserts this is NodePath<t.ObjectProperty>;
assertObjectTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.ObjectTypeAnnotation>;
assertObjectTypeCallProperty(
opts?: object,
): asserts this is NodePath<t.ObjectTypeCallProperty>;
assertObjectTypeIndexer(
opts?: object,
): asserts this is NodePath<t.ObjectTypeIndexer>;
assertObjectTypeInternalSlot(
opts?: object,
): asserts this is NodePath<t.ObjectTypeInternalSlot>;
assertObjectTypeProperty(
opts?: object,
): asserts this is NodePath<t.ObjectTypeProperty>;
assertObjectTypeSpreadProperty(
opts?: object,
): asserts this is NodePath<t.ObjectTypeSpreadProperty>;
assertOpaqueType(opts?: object): asserts this is NodePath<t.OpaqueType>;
assertOptionalCallExpression(
opts?: object,
): asserts this is NodePath<t.OptionalCallExpression>;
assertOptionalMemberExpression(
opts?: object,
): asserts this is NodePath<t.OptionalMemberExpression>;
assertParenthesizedExpression(
opts?: object,
): asserts this is NodePath<t.ParenthesizedExpression>;
assertPattern(opts?: object): asserts this is NodePath<t.Pattern>;
assertPatternLike(opts?: object): asserts this is NodePath<t.PatternLike>;
assertPipelineBareFunction(
opts?: object,
): asserts this is NodePath<t.PipelineBareFunction>;
assertPipelinePrimaryTopicReference(
opts?: object,
): asserts this is NodePath<t.PipelinePrimaryTopicReference>;
assertPipelineTopicExpression(
opts?: object,
): asserts this is NodePath<t.PipelineTopicExpression>;
assertPlaceholder(opts?: object): asserts this is NodePath<t.Placeholder>;
assertPrivate(opts?: object): asserts this is NodePath<t.Private>;
assertPrivateName(opts?: object): asserts this is NodePath<t.PrivateName>;
assertProgram(opts?: object): asserts this is NodePath<t.Program>;
assertProperty(opts?: object): asserts this is NodePath<t.Property>;
assertPureish(opts?: object): asserts this is NodePath<t.Pureish>;
assertQualifiedTypeIdentifier(
opts?: object,
): asserts this is NodePath<t.QualifiedTypeIdentifier>;
assertRecordExpression(
opts?: object,
): asserts this is NodePath<t.RecordExpression>;
assertRegExpLiteral(opts?: object): asserts this is NodePath<t.RegExpLiteral>;
assertRegexLiteral(opts?: object): asserts this is NodePath<t.RegexLiteral>;
assertRestElement(opts?: object): asserts this is NodePath<t.RestElement>;
assertRestProperty(opts?: object): asserts this is NodePath<t.RestProperty>;
assertReturnStatement(
opts?: object,
): asserts this is NodePath<t.ReturnStatement>;
assertScopable(opts?: object): asserts this is NodePath<t.Scopable>;
assertSequenceExpression(
opts?: object,
): asserts this is NodePath<t.SequenceExpression>;
assertSpreadElement(opts?: object): asserts this is NodePath<t.SpreadElement>;
assertSpreadProperty(
opts?: object,
): asserts this is NodePath<t.SpreadProperty>;
assertStatement(opts?: object): asserts this is NodePath<t.Statement>;
assertStaticBlock(opts?: object): asserts this is NodePath<t.StaticBlock>;
assertStringLiteral(opts?: object): asserts this is NodePath<t.StringLiteral>;
assertStringLiteralTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.StringLiteralTypeAnnotation>;
assertStringTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.StringTypeAnnotation>;
assertSuper(opts?: object): asserts this is NodePath<t.Super>;
assertSwitchCase(opts?: object): asserts this is NodePath<t.SwitchCase>;
assertSwitchStatement(
opts?: object,
): asserts this is NodePath<t.SwitchStatement>;
assertSymbolTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.SymbolTypeAnnotation>;
assertTSAnyKeyword(opts?: object): asserts this is NodePath<t.TSAnyKeyword>;
assertTSArrayType(opts?: object): asserts this is NodePath<t.TSArrayType>;
assertTSAsExpression(
opts?: object,
): asserts this is NodePath<t.TSAsExpression>;
assertTSBaseType(opts?: object): asserts this is NodePath<t.TSBaseType>;
assertTSBigIntKeyword(
opts?: object,
): asserts this is NodePath<t.TSBigIntKeyword>;
assertTSBooleanKeyword(
opts?: object,
): asserts this is NodePath<t.TSBooleanKeyword>;
assertTSCallSignatureDeclaration(
opts?: object,
): asserts this is NodePath<t.TSCallSignatureDeclaration>;
assertTSConditionalType(
opts?: object,
): asserts this is NodePath<t.TSConditionalType>;
assertTSConstructSignatureDeclaration(
opts?: object,
): asserts this is NodePath<t.TSConstructSignatureDeclaration>;
assertTSConstructorType(
opts?: object,
): asserts this is NodePath<t.TSConstructorType>;
assertTSDeclareFunction(
opts?: object,
): asserts this is NodePath<t.TSDeclareFunction>;
assertTSDeclareMethod(
opts?: object,
): asserts this is NodePath<t.TSDeclareMethod>;
assertTSEntityName(opts?: object): asserts this is NodePath<t.TSEntityName>;
assertTSEnumDeclaration(
opts?: object,
): asserts this is NodePath<t.TSEnumDeclaration>;
assertTSEnumMember(opts?: object): asserts this is NodePath<t.TSEnumMember>;
assertTSExportAssignment(
opts?: object,
): asserts this is NodePath<t.TSExportAssignment>;
assertTSExpressionWithTypeArguments(
opts?: object,
): asserts this is NodePath<t.TSExpressionWithTypeArguments>;
assertTSExternalModuleReference(
opts?: object,
): asserts this is NodePath<t.TSExternalModuleReference>;
assertTSFunctionType(
opts?: object,
): asserts this is NodePath<t.TSFunctionType>;
assertTSImportEqualsDeclaration(
opts?: object,
): asserts this is NodePath<t.TSImportEqualsDeclaration>;
assertTSImportType(opts?: object): asserts this is NodePath<t.TSImportType>;
assertTSIndexSignature(
opts?: object,
): asserts this is NodePath<t.TSIndexSignature>;
assertTSIndexedAccessType(
opts?: object,
): asserts this is NodePath<t.TSIndexedAccessType>;
assertTSInferType(opts?: object): asserts this is NodePath<t.TSInferType>;
assertTSInterfaceBody(
opts?: object,
): asserts this is NodePath<t.TSInterfaceBody>;
assertTSInterfaceDeclaration(
opts?: object,
): asserts this is NodePath<t.TSInterfaceDeclaration>;
assertTSIntersectionType(
opts?: object,
): asserts this is NodePath<t.TSIntersectionType>;
assertTSIntrinsicKeyword(
opts?: object,
): asserts this is NodePath<t.TSIntrinsicKeyword>;
assertTSLiteralType(opts?: object): asserts this is NodePath<t.TSLiteralType>;
assertTSMappedType(opts?: object): asserts this is NodePath<t.TSMappedType>;
assertTSMethodSignature(
opts?: object,
): asserts this is NodePath<t.TSMethodSignature>;
assertTSModuleBlock(opts?: object): asserts this is NodePath<t.TSModuleBlock>;
assertTSModuleDeclaration(
opts?: object,
): asserts this is NodePath<t.TSModuleDeclaration>;
assertTSNamedTupleMember(
opts?: object,
): asserts this is NodePath<t.TSNamedTupleMember>;
assertTSNamespaceExportDeclaration(
opts?: object,
): asserts this is NodePath<t.TSNamespaceExportDeclaration>;
assertTSNeverKeyword(
opts?: object,
): asserts this is NodePath<t.TSNeverKeyword>;
assertTSNonNullExpression(
opts?: object,
): asserts this is NodePath<t.TSNonNullExpression>;
assertTSNullKeyword(opts?: object): asserts this is NodePath<t.TSNullKeyword>;
assertTSNumberKeyword(
opts?: object,
): asserts this is NodePath<t.TSNumberKeyword>;
assertTSObjectKeyword(
opts?: object,
): asserts this is NodePath<t.TSObjectKeyword>;
assertTSOptionalType(
opts?: object,
): asserts this is NodePath<t.TSOptionalType>;
assertTSParameterProperty(
opts?: object,
): asserts this is NodePath<t.TSParameterProperty>;
assertTSParenthesizedType(
opts?: object,
): asserts this is NodePath<t.TSParenthesizedType>;
assertTSPropertySignature(
opts?: object,
): asserts this is NodePath<t.TSPropertySignature>;
assertTSQualifiedName(
opts?: object,
): asserts this is NodePath<t.TSQualifiedName>;
assertTSRestType(opts?: object): asserts this is NodePath<t.TSRestType>;
assertTSStringKeyword(
opts?: object,
): asserts this is NodePath<t.TSStringKeyword>;
assertTSSymbolKeyword(
opts?: object,
): asserts this is NodePath<t.TSSymbolKeyword>;
assertTSThisType(opts?: object): asserts this is NodePath<t.TSThisType>;
assertTSTupleType(opts?: object): asserts this is NodePath<t.TSTupleType>;
assertTSType(opts?: object): asserts this is NodePath<t.TSType>;
assertTSTypeAliasDeclaration(
opts?: object,
): asserts this is NodePath<t.TSTypeAliasDeclaration>;
assertTSTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.TSTypeAnnotation>;
assertTSTypeAssertion(
opts?: object,
): asserts this is NodePath<t.TSTypeAssertion>;
assertTSTypeElement(opts?: object): asserts this is NodePath<t.TSTypeElement>;
assertTSTypeLiteral(opts?: object): asserts this is NodePath<t.TSTypeLiteral>;
assertTSTypeOperator(
opts?: object,
): asserts this is NodePath<t.TSTypeOperator>;
assertTSTypeParameter(
opts?: object,
): asserts this is NodePath<t.TSTypeParameter>;
assertTSTypeParameterDeclaration(
opts?: object,
): asserts this is NodePath<t.TSTypeParameterDeclaration>;
assertTSTypeParameterInstantiation(
opts?: object,
): asserts this is NodePath<t.TSTypeParameterInstantiation>;
assertTSTypePredicate(
opts?: object,
): asserts this is NodePath<t.TSTypePredicate>;
assertTSTypeQuery(opts?: object): asserts this is NodePath<t.TSTypeQuery>;
assertTSTypeReference(
opts?: object,
): asserts this is NodePath<t.TSTypeReference>;
assertTSUndefinedKeyword(
opts?: object,
): asserts this is NodePath<t.TSUndefinedKeyword>;
assertTSUnionType(opts?: object): asserts this is NodePath<t.TSUnionType>;
assertTSUnknownKeyword(
opts?: object,
): asserts this is NodePath<t.TSUnknownKeyword>;
assertTSVoidKeyword(opts?: object): asserts this is NodePath<t.TSVoidKeyword>;
assertTaggedTemplateExpression(
opts?: object,
): asserts this is NodePath<t.TaggedTemplateExpression>;
assertTemplateElement(
opts?: object,
): asserts this is NodePath<t.TemplateElement>;
assertTemplateLiteral(
opts?: object,
): asserts this is NodePath<t.TemplateLiteral>;
assertTerminatorless(
opts?: object,
): asserts this is NodePath<t.Terminatorless>;
assertThisExpression(
opts?: object,
): asserts this is NodePath<t.ThisExpression>;
assertThisTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.ThisTypeAnnotation>;
assertThrowStatement(
opts?: object,
): asserts this is NodePath<t.ThrowStatement>;
assertTryStatement(opts?: object): asserts this is NodePath<t.TryStatement>;
assertTupleExpression(
opts?: object,
): asserts this is NodePath<t.TupleExpression>;
assertTupleTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.TupleTypeAnnotation>;
assertTypeAlias(opts?: object): asserts this is NodePath<t.TypeAlias>;
assertTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.TypeAnnotation>;
assertTypeCastExpression(
opts?: object,
): asserts this is NodePath<t.TypeCastExpression>;
assertTypeParameter(opts?: object): asserts this is NodePath<t.TypeParameter>;
assertTypeParameterDeclaration(
opts?: object,
): asserts this is NodePath<t.TypeParameterDeclaration>;
assertTypeParameterInstantiation(
opts?: object,
): asserts this is NodePath<t.TypeParameterInstantiation>;
assertTypeofTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.TypeofTypeAnnotation>;
assertUnaryExpression(
opts?: object,
): asserts this is NodePath<t.UnaryExpression>;
assertUnaryLike(opts?: object): asserts this is NodePath<t.UnaryLike>;
assertUnionTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.UnionTypeAnnotation>;
assertUpdateExpression(
opts?: object,
): asserts this is NodePath<t.UpdateExpression>;
assertUserWhitespacable(
opts?: object,
): asserts this is NodePath<t.UserWhitespacable>;
assertV8IntrinsicIdentifier(
opts?: object,
): asserts this is NodePath<t.V8IntrinsicIdentifier>;
assertVariableDeclaration(
opts?: object,
): asserts this is NodePath<t.VariableDeclaration>;
assertVariableDeclarator(
opts?: object,
): asserts this is NodePath<t.VariableDeclarator>;
assertVariance(opts?: object): asserts this is NodePath<t.Variance>;
assertVoidTypeAnnotation(
opts?: object,
): asserts this is NodePath<t.VoidTypeAnnotation>;
assertWhile(opts?: object): asserts this is NodePath<t.While>;
assertWhileStatement(
opts?: object,
): asserts this is NodePath<t.WhileStatement>;
assertWithStatement(opts?: object): asserts this is NodePath<t.WithStatement>;
assertYieldExpression(
opts?: object,
): asserts this is NodePath<t.YieldExpression>;
}

View File

@ -0,0 +1,432 @@
/*
* 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 {
isAnyTypeAnnotation(opts?: object): this is NodePath<t.AnyTypeAnnotation>;
isArgumentPlaceholder(opts?: object): this is NodePath<t.ArgumentPlaceholder>;
isArrayExpression(opts?: object): this is NodePath<t.ArrayExpression>;
isArrayPattern(opts?: object): this is NodePath<t.ArrayPattern>;
isArrayTypeAnnotation(opts?: object): this is NodePath<t.ArrayTypeAnnotation>;
isArrowFunctionExpression(
opts?: object,
): this is NodePath<t.ArrowFunctionExpression>;
isAssignmentExpression(
opts?: object,
): this is NodePath<t.AssignmentExpression>;
isAssignmentPattern(opts?: object): this is NodePath<t.AssignmentPattern>;
isAwaitExpression(opts?: object): this is NodePath<t.AwaitExpression>;
isBigIntLiteral(opts?: object): this is NodePath<t.BigIntLiteral>;
isBinary(opts?: object): this is NodePath<t.Binary>;
isBinaryExpression(opts?: object): this is NodePath<t.BinaryExpression>;
isBindExpression(opts?: object): this is NodePath<t.BindExpression>;
isBlock(opts?: object): this is NodePath<t.Block>;
isBlockParent(opts?: object): this is NodePath<t.BlockParent>;
isBlockStatement(opts?: object): this is NodePath<t.BlockStatement>;
isBooleanLiteral(opts?: object): this is NodePath<t.BooleanLiteral>;
isBooleanLiteralTypeAnnotation(
opts?: object,
): this is NodePath<t.BooleanLiteralTypeAnnotation>;
isBooleanTypeAnnotation(
opts?: object,
): this is NodePath<t.BooleanTypeAnnotation>;
isBreakStatement(opts?: object): this is NodePath<t.BreakStatement>;
isCallExpression(opts?: object): this is NodePath<t.CallExpression>;
isCatchClause(opts?: object): this is NodePath<t.CatchClause>;
isClass(opts?: object): this is NodePath<t.Class>;
isClassBody(opts?: object): this is NodePath<t.ClassBody>;
isClassDeclaration(opts?: object): this is NodePath<t.ClassDeclaration>;
isClassExpression(opts?: object): this is NodePath<t.ClassExpression>;
isClassImplements(opts?: object): this is NodePath<t.ClassImplements>;
isClassMethod(opts?: object): this is NodePath<t.ClassMethod>;
isClassPrivateMethod(opts?: object): this is NodePath<t.ClassPrivateMethod>;
isClassPrivateProperty(
opts?: object,
): this is NodePath<t.ClassPrivateProperty>;
isClassProperty(opts?: object): this is NodePath<t.ClassProperty>;
isCompletionStatement(opts?: object): this is NodePath<t.CompletionStatement>;
isConditional(opts?: object): this is NodePath<t.Conditional>;
isConditionalExpression(
opts?: object,
): this is NodePath<t.ConditionalExpression>;
isContinueStatement(opts?: object): this is NodePath<t.ContinueStatement>;
isDebuggerStatement(opts?: object): this is NodePath<t.DebuggerStatement>;
isDecimalLiteral(opts?: object): this is NodePath<t.DecimalLiteral>;
isDeclaration(opts?: object): this is NodePath<t.Declaration>;
isDeclareClass(opts?: object): this is NodePath<t.DeclareClass>;
isDeclareExportAllDeclaration(
opts?: object,
): this is NodePath<t.DeclareExportAllDeclaration>;
isDeclareExportDeclaration(
opts?: object,
): this is NodePath<t.DeclareExportDeclaration>;
isDeclareFunction(opts?: object): this is NodePath<t.DeclareFunction>;
isDeclareInterface(opts?: object): this is NodePath<t.DeclareInterface>;
isDeclareModule(opts?: object): this is NodePath<t.DeclareModule>;
isDeclareModuleExports(
opts?: object,
): this is NodePath<t.DeclareModuleExports>;
isDeclareOpaqueType(opts?: object): this is NodePath<t.DeclareOpaqueType>;
isDeclareTypeAlias(opts?: object): this is NodePath<t.DeclareTypeAlias>;
isDeclareVariable(opts?: object): this is NodePath<t.DeclareVariable>;
isDeclaredPredicate(opts?: object): this is NodePath<t.DeclaredPredicate>;
isDecorator(opts?: object): this is NodePath<t.Decorator>;
isDirective(opts?: object): this is NodePath<t.Directive>;
isDirectiveLiteral(opts?: object): this is NodePath<t.DirectiveLiteral>;
isDoExpression(opts?: object): this is NodePath<t.DoExpression>;
isDoWhileStatement(opts?: object): this is NodePath<t.DoWhileStatement>;
isEmptyStatement(opts?: object): this is NodePath<t.EmptyStatement>;
isEmptyTypeAnnotation(opts?: object): this is NodePath<t.EmptyTypeAnnotation>;
isEnumBody(opts?: object): this is NodePath<t.EnumBody>;
isEnumBooleanBody(opts?: object): this is NodePath<t.EnumBooleanBody>;
isEnumBooleanMember(opts?: object): this is NodePath<t.EnumBooleanMember>;
isEnumDeclaration(opts?: object): this is NodePath<t.EnumDeclaration>;
isEnumDefaultedMember(opts?: object): this is NodePath<t.EnumDefaultedMember>;
isEnumMember(opts?: object): this is NodePath<t.EnumMember>;
isEnumNumberBody(opts?: object): this is NodePath<t.EnumNumberBody>;
isEnumNumberMember(opts?: object): this is NodePath<t.EnumNumberMember>;
isEnumStringBody(opts?: object): this is NodePath<t.EnumStringBody>;
isEnumStringMember(opts?: object): this is NodePath<t.EnumStringMember>;
isEnumSymbolBody(opts?: object): this is NodePath<t.EnumSymbolBody>;
isExistsTypeAnnotation(
opts?: object,
): this is NodePath<t.ExistsTypeAnnotation>;
isExportAllDeclaration(
opts?: object,
): this is NodePath<t.ExportAllDeclaration>;
isExportDeclaration(opts?: object): this is NodePath<t.ExportDeclaration>;
isExportDefaultDeclaration(
opts?: object,
): this is NodePath<t.ExportDefaultDeclaration>;
isExportDefaultSpecifier(
opts?: object,
): this is NodePath<t.ExportDefaultSpecifier>;
isExportNamedDeclaration(
opts?: object,
): this is NodePath<t.ExportNamedDeclaration>;
isExportNamespaceSpecifier(
opts?: object,
): this is NodePath<t.ExportNamespaceSpecifier>;
isExportSpecifier(opts?: object): this is NodePath<t.ExportSpecifier>;
isExpression(opts?: object): this is NodePath<t.Expression>;
isExpressionStatement(opts?: object): this is NodePath<t.ExpressionStatement>;
isExpressionWrapper(opts?: object): this is NodePath<t.ExpressionWrapper>;
isFile(opts?: object): this is NodePath<t.File>;
isFlow(opts?: object): this is NodePath<t.Flow>;
isFlowBaseAnnotation(opts?: object): this is NodePath<t.FlowBaseAnnotation>;
isFlowDeclaration(opts?: object): this is NodePath<t.FlowDeclaration>;
isFlowPredicate(opts?: object): this is NodePath<t.FlowPredicate>;
isFlowType(opts?: object): this is NodePath<t.FlowType>;
isFor(opts?: object): this is NodePath<t.For>;
isForInStatement(opts?: object): this is NodePath<t.ForInStatement>;
isForOfStatement(opts?: object): this is NodePath<t.ForOfStatement>;
isForStatement(opts?: object): this is NodePath<t.ForStatement>;
isForXStatement(opts?: object): this is NodePath<t.ForXStatement>;
isFunction(opts?: object): this is NodePath<t.Function>;
isFunctionDeclaration(opts?: object): this is NodePath<t.FunctionDeclaration>;
isFunctionExpression(opts?: object): this is NodePath<t.FunctionExpression>;
isFunctionParent(opts?: object): this is NodePath<t.FunctionParent>;
isFunctionTypeAnnotation(
opts?: object,
): this is NodePath<t.FunctionTypeAnnotation>;
isFunctionTypeParam(opts?: object): this is NodePath<t.FunctionTypeParam>;
isGenericTypeAnnotation(
opts?: object,
): this is NodePath<t.GenericTypeAnnotation>;
isIdentifier(opts?: object): this is NodePath<t.Identifier>;
isIfStatement(opts?: object): this is NodePath<t.IfStatement>;
isImmutable(opts?: object): this is NodePath<t.Immutable>;
isImport(opts?: object): this is NodePath<t.Import>;
isImportAttribute(opts?: object): this is NodePath<t.ImportAttribute>;
isImportDeclaration(opts?: object): this is NodePath<t.ImportDeclaration>;
isImportDefaultSpecifier(
opts?: object,
): this is NodePath<t.ImportDefaultSpecifier>;
isImportNamespaceSpecifier(
opts?: object,
): this is NodePath<t.ImportNamespaceSpecifier>;
isImportSpecifier(opts?: object): this is NodePath<t.ImportSpecifier>;
isInferredPredicate(opts?: object): this is NodePath<t.InferredPredicate>;
isInterfaceDeclaration(
opts?: object,
): this is NodePath<t.InterfaceDeclaration>;
isInterfaceExtends(opts?: object): this is NodePath<t.InterfaceExtends>;
isInterfaceTypeAnnotation(
opts?: object,
): this is NodePath<t.InterfaceTypeAnnotation>;
isInterpreterDirective(
opts?: object,
): this is NodePath<t.InterpreterDirective>;
isIntersectionTypeAnnotation(
opts?: object,
): this is NodePath<t.IntersectionTypeAnnotation>;
isJSX(opts?: object): this is NodePath<t.JSX>;
isJSXAttribute(opts?: object): this is NodePath<t.JSXAttribute>;
isJSXClosingElement(opts?: object): this is NodePath<t.JSXClosingElement>;
isJSXClosingFragment(opts?: object): this is NodePath<t.JSXClosingFragment>;
isJSXElement(opts?: object): this is NodePath<t.JSXElement>;
isJSXEmptyExpression(opts?: object): this is NodePath<t.JSXEmptyExpression>;
isJSXExpressionContainer(
opts?: object,
): this is NodePath<t.JSXExpressionContainer>;
isJSXFragment(opts?: object): this is NodePath<t.JSXFragment>;
isJSXIdentifier(opts?: object): this is NodePath<t.JSXIdentifier>;
isJSXMemberExpression(opts?: object): this is NodePath<t.JSXMemberExpression>;
isJSXNamespacedName(opts?: object): this is NodePath<t.JSXNamespacedName>;
isJSXOpeningElement(opts?: object): this is NodePath<t.JSXOpeningElement>;
isJSXOpeningFragment(opts?: object): this is NodePath<t.JSXOpeningFragment>;
isJSXSpreadAttribute(opts?: object): this is NodePath<t.JSXSpreadAttribute>;
isJSXSpreadChild(opts?: object): this is NodePath<t.JSXSpreadChild>;
isJSXText(opts?: object): this is NodePath<t.JSXText>;
isLVal(opts?: object): this is NodePath<t.LVal>;
isLabeledStatement(opts?: object): this is NodePath<t.LabeledStatement>;
isLiteral(opts?: object): this is NodePath<t.Literal>;
isLogicalExpression(opts?: object): this is NodePath<t.LogicalExpression>;
isLoop(opts?: object): this is NodePath<t.Loop>;
isMemberExpression(opts?: object): this is NodePath<t.MemberExpression>;
isMetaProperty(opts?: object): this is NodePath<t.MetaProperty>;
isMethod(opts?: object): this is NodePath<t.Method>;
isMixedTypeAnnotation(opts?: object): this is NodePath<t.MixedTypeAnnotation>;
isModuleDeclaration(opts?: object): this is NodePath<t.ModuleDeclaration>;
isModuleSpecifier(opts?: object): this is NodePath<t.ModuleSpecifier>;
isNewExpression(opts?: object): this is NodePath<t.NewExpression>;
isNoop(opts?: object): this is NodePath<t.Noop>;
isNullLiteral(opts?: object): this is NodePath<t.NullLiteral>;
isNullLiteralTypeAnnotation(
opts?: object,
): this is NodePath<t.NullLiteralTypeAnnotation>;
isNullableTypeAnnotation(
opts?: object,
): this is NodePath<t.NullableTypeAnnotation>;
isNumberLiteral(opts?: object): this is NodePath<t.NumberLiteral>;
isNumberLiteralTypeAnnotation(
opts?: object,
): this is NodePath<t.NumberLiteralTypeAnnotation>;
isNumberTypeAnnotation(
opts?: object,
): this is NodePath<t.NumberTypeAnnotation>;
isNumericLiteral(opts?: object): this is NodePath<t.NumericLiteral>;
isObjectExpression(opts?: object): this is NodePath<t.ObjectExpression>;
isObjectMember(opts?: object): this is NodePath<t.ObjectMember>;
isObjectMethod(opts?: object): this is NodePath<t.ObjectMethod>;
isObjectPattern(opts?: object): this is NodePath<t.ObjectPattern>;
isObjectProperty(opts?: object): this is NodePath<t.ObjectProperty>;
isObjectTypeAnnotation(
opts?: object,
): this is NodePath<t.ObjectTypeAnnotation>;
isObjectTypeCallProperty(
opts?: object,
): this is NodePath<t.ObjectTypeCallProperty>;
isObjectTypeIndexer(opts?: object): this is NodePath<t.ObjectTypeIndexer>;
isObjectTypeInternalSlot(
opts?: object,
): this is NodePath<t.ObjectTypeInternalSlot>;
isObjectTypeProperty(opts?: object): this is NodePath<t.ObjectTypeProperty>;
isObjectTypeSpreadProperty(
opts?: object,
): this is NodePath<t.ObjectTypeSpreadProperty>;
isOpaqueType(opts?: object): this is NodePath<t.OpaqueType>;
isOptionalCallExpression(
opts?: object,
): this is NodePath<t.OptionalCallExpression>;
isOptionalMemberExpression(
opts?: object,
): this is NodePath<t.OptionalMemberExpression>;
isParenthesizedExpression(
opts?: object,
): this is NodePath<t.ParenthesizedExpression>;
isPattern(opts?: object): this is NodePath<t.Pattern>;
isPatternLike(opts?: object): this is NodePath<t.PatternLike>;
isPipelineBareFunction(
opts?: object,
): this is NodePath<t.PipelineBareFunction>;
isPipelinePrimaryTopicReference(
opts?: object,
): this is NodePath<t.PipelinePrimaryTopicReference>;
isPipelineTopicExpression(
opts?: object,
): this is NodePath<t.PipelineTopicExpression>;
isPlaceholder(opts?: object): this is NodePath<t.Placeholder>;
isPrivate(opts?: object): this is NodePath<t.Private>;
isPrivateName(opts?: object): this is NodePath<t.PrivateName>;
isProgram(opts?: object): this is NodePath<t.Program>;
isProperty(opts?: object): this is NodePath<t.Property>;
isPureish(opts?: object): this is NodePath<t.Pureish>;
isQualifiedTypeIdentifier(
opts?: object,
): this is NodePath<t.QualifiedTypeIdentifier>;
isRecordExpression(opts?: object): this is NodePath<t.RecordExpression>;
isRegExpLiteral(opts?: object): this is NodePath<t.RegExpLiteral>;
isRegexLiteral(opts?: object): this is NodePath<t.RegexLiteral>;
isRestElement(opts?: object): this is NodePath<t.RestElement>;
isRestProperty(opts?: object): this is NodePath<t.RestProperty>;
isReturnStatement(opts?: object): this is NodePath<t.ReturnStatement>;
isScopable(opts?: object): this is NodePath<t.Scopable>;
isSequenceExpression(opts?: object): this is NodePath<t.SequenceExpression>;
isSpreadElement(opts?: object): this is NodePath<t.SpreadElement>;
isSpreadProperty(opts?: object): this is NodePath<t.SpreadProperty>;
isStatement(opts?: object): this is NodePath<t.Statement>;
isStaticBlock(opts?: object): this is NodePath<t.StaticBlock>;
isStringLiteral(opts?: object): this is NodePath<t.StringLiteral>;
isStringLiteralTypeAnnotation(
opts?: object,
): this is NodePath<t.StringLiteralTypeAnnotation>;
isStringTypeAnnotation(
opts?: object,
): this is NodePath<t.StringTypeAnnotation>;
isSuper(opts?: object): this is NodePath<t.Super>;
isSwitchCase(opts?: object): this is NodePath<t.SwitchCase>;
isSwitchStatement(opts?: object): this is NodePath<t.SwitchStatement>;
isSymbolTypeAnnotation(
opts?: object,
): this is NodePath<t.SymbolTypeAnnotation>;
isTSAnyKeyword(opts?: object): this is NodePath<t.TSAnyKeyword>;
isTSArrayType(opts?: object): this is NodePath<t.TSArrayType>;
isTSAsExpression(opts?: object): this is NodePath<t.TSAsExpression>;
isTSBaseType(opts?: object): this is NodePath<t.TSBaseType>;
isTSBigIntKeyword(opts?: object): this is NodePath<t.TSBigIntKeyword>;
isTSBooleanKeyword(opts?: object): this is NodePath<t.TSBooleanKeyword>;
isTSCallSignatureDeclaration(
opts?: object,
): this is NodePath<t.TSCallSignatureDeclaration>;
isTSConditionalType(opts?: object): this is NodePath<t.TSConditionalType>;
isTSConstructSignatureDeclaration(
opts?: object,
): this is NodePath<t.TSConstructSignatureDeclaration>;
isTSConstructorType(opts?: object): this is NodePath<t.TSConstructorType>;
isTSDeclareFunction(opts?: object): this is NodePath<t.TSDeclareFunction>;
isTSDeclareMethod(opts?: object): this is NodePath<t.TSDeclareMethod>;
isTSEntityName(opts?: object): this is NodePath<t.TSEntityName>;
isTSEnumDeclaration(opts?: object): this is NodePath<t.TSEnumDeclaration>;
isTSEnumMember(opts?: object): this is NodePath<t.TSEnumMember>;
isTSExportAssignment(opts?: object): this is NodePath<t.TSExportAssignment>;
isTSExpressionWithTypeArguments(
opts?: object,
): this is NodePath<t.TSExpressionWithTypeArguments>;
isTSExternalModuleReference(
opts?: object,
): this is NodePath<t.TSExternalModuleReference>;
isTSFunctionType(opts?: object): this is NodePath<t.TSFunctionType>;
isTSImportEqualsDeclaration(
opts?: object,
): this is NodePath<t.TSImportEqualsDeclaration>;
isTSImportType(opts?: object): this is NodePath<t.TSImportType>;
isTSIndexSignature(opts?: object): this is NodePath<t.TSIndexSignature>;
isTSIndexedAccessType(opts?: object): this is NodePath<t.TSIndexedAccessType>;
isTSInferType(opts?: object): this is NodePath<t.TSInferType>;
isTSInterfaceBody(opts?: object): this is NodePath<t.TSInterfaceBody>;
isTSInterfaceDeclaration(
opts?: object,
): this is NodePath<t.TSInterfaceDeclaration>;
isTSIntersectionType(opts?: object): this is NodePath<t.TSIntersectionType>;
isTSIntrinsicKeyword(opts?: object): this is NodePath<t.TSIntrinsicKeyword>;
isTSLiteralType(opts?: object): this is NodePath<t.TSLiteralType>;
isTSMappedType(opts?: object): this is NodePath<t.TSMappedType>;
isTSMethodSignature(opts?: object): this is NodePath<t.TSMethodSignature>;
isTSModuleBlock(opts?: object): this is NodePath<t.TSModuleBlock>;
isTSModuleDeclaration(opts?: object): this is NodePath<t.TSModuleDeclaration>;
isTSNamedTupleMember(opts?: object): this is NodePath<t.TSNamedTupleMember>;
isTSNamespaceExportDeclaration(
opts?: object,
): this is NodePath<t.TSNamespaceExportDeclaration>;
isTSNeverKeyword(opts?: object): this is NodePath<t.TSNeverKeyword>;
isTSNonNullExpression(opts?: object): this is NodePath<t.TSNonNullExpression>;
isTSNullKeyword(opts?: object): this is NodePath<t.TSNullKeyword>;
isTSNumberKeyword(opts?: object): this is NodePath<t.TSNumberKeyword>;
isTSObjectKeyword(opts?: object): this is NodePath<t.TSObjectKeyword>;
isTSOptionalType(opts?: object): this is NodePath<t.TSOptionalType>;
isTSParameterProperty(opts?: object): this is NodePath<t.TSParameterProperty>;
isTSParenthesizedType(opts?: object): this is NodePath<t.TSParenthesizedType>;
isTSPropertySignature(opts?: object): this is NodePath<t.TSPropertySignature>;
isTSQualifiedName(opts?: object): this is NodePath<t.TSQualifiedName>;
isTSRestType(opts?: object): this is NodePath<t.TSRestType>;
isTSStringKeyword(opts?: object): this is NodePath<t.TSStringKeyword>;
isTSSymbolKeyword(opts?: object): this is NodePath<t.TSSymbolKeyword>;
isTSThisType(opts?: object): this is NodePath<t.TSThisType>;
isTSTupleType(opts?: object): this is NodePath<t.TSTupleType>;
isTSType(opts?: object): this is NodePath<t.TSType>;
isTSTypeAliasDeclaration(
opts?: object,
): this is NodePath<t.TSTypeAliasDeclaration>;
isTSTypeAnnotation(opts?: object): this is NodePath<t.TSTypeAnnotation>;
isTSTypeAssertion(opts?: object): this is NodePath<t.TSTypeAssertion>;
isTSTypeElement(opts?: object): this is NodePath<t.TSTypeElement>;
isTSTypeLiteral(opts?: object): this is NodePath<t.TSTypeLiteral>;
isTSTypeOperator(opts?: object): this is NodePath<t.TSTypeOperator>;
isTSTypeParameter(opts?: object): this is NodePath<t.TSTypeParameter>;
isTSTypeParameterDeclaration(
opts?: object,
): this is NodePath<t.TSTypeParameterDeclaration>;
isTSTypeParameterInstantiation(
opts?: object,
): this is NodePath<t.TSTypeParameterInstantiation>;
isTSTypePredicate(opts?: object): this is NodePath<t.TSTypePredicate>;
isTSTypeQuery(opts?: object): this is NodePath<t.TSTypeQuery>;
isTSTypeReference(opts?: object): this is NodePath<t.TSTypeReference>;
isTSUndefinedKeyword(opts?: object): this is NodePath<t.TSUndefinedKeyword>;
isTSUnionType(opts?: object): this is NodePath<t.TSUnionType>;
isTSUnknownKeyword(opts?: object): this is NodePath<t.TSUnknownKeyword>;
isTSVoidKeyword(opts?: object): this is NodePath<t.TSVoidKeyword>;
isTaggedTemplateExpression(
opts?: object,
): this is NodePath<t.TaggedTemplateExpression>;
isTemplateElement(opts?: object): this is NodePath<t.TemplateElement>;
isTemplateLiteral(opts?: object): this is NodePath<t.TemplateLiteral>;
isTerminatorless(opts?: object): this is NodePath<t.Terminatorless>;
isThisExpression(opts?: object): this is NodePath<t.ThisExpression>;
isThisTypeAnnotation(opts?: object): this is NodePath<t.ThisTypeAnnotation>;
isThrowStatement(opts?: object): this is NodePath<t.ThrowStatement>;
isTryStatement(opts?: object): this is NodePath<t.TryStatement>;
isTupleExpression(opts?: object): this is NodePath<t.TupleExpression>;
isTupleTypeAnnotation(opts?: object): this is NodePath<t.TupleTypeAnnotation>;
isTypeAlias(opts?: object): this is NodePath<t.TypeAlias>;
isTypeAnnotation(opts?: object): this is NodePath<t.TypeAnnotation>;
isTypeCastExpression(opts?: object): this is NodePath<t.TypeCastExpression>;
isTypeParameter(opts?: object): this is NodePath<t.TypeParameter>;
isTypeParameterDeclaration(
opts?: object,
): this is NodePath<t.TypeParameterDeclaration>;
isTypeParameterInstantiation(
opts?: object,
): this is NodePath<t.TypeParameterInstantiation>;
isTypeofTypeAnnotation(
opts?: object,
): this is NodePath<t.TypeofTypeAnnotation>;
isUnaryExpression(opts?: object): this is NodePath<t.UnaryExpression>;
isUnaryLike(opts?: object): this is NodePath<t.UnaryLike>;
isUnionTypeAnnotation(opts?: object): this is NodePath<t.UnionTypeAnnotation>;
isUpdateExpression(opts?: object): this is NodePath<t.UpdateExpression>;
isUserWhitespacable(opts?: object): this is NodePath<t.UserWhitespacable>;
isV8IntrinsicIdentifier(
opts?: object,
): this is NodePath<t.V8IntrinsicIdentifier>;
isVariableDeclaration(opts?: object): this is NodePath<t.VariableDeclaration>;
isVariableDeclarator(opts?: object): this is NodePath<t.VariableDeclarator>;
isVariance(opts?: object): this is NodePath<t.Variance>;
isVoidTypeAnnotation(opts?: object): this is NodePath<t.VoidTypeAnnotation>;
isWhile(opts?: object): this is NodePath<t.While>;
isWhileStatement(opts?: object): this is NodePath<t.WhileStatement>;
isWithStatement(opts?: object): this is NodePath<t.WithStatement>;
isYieldExpression(opts?: object): this is NodePath<t.YieldExpression>;
isReferencedIdentifier(opts?: object): boolean;
isReferencedMemberExpression(opts?: object): boolean;
isBindingIdentifier(opts?: object): boolean;
isStatement(opts?: object): this is NodePath<t.Statement>;
isExpression(opts?: object): this is NodePath<t.Expression>;
isScope(opts?: object): boolean;
isReferenced(opts?: object): boolean;
isBlockScoped(opts?: object): boolean;
isVar(opts?: object): boolean;
isUser(opts?: object): boolean;
isGenerated(opts?: object): boolean;
isPure(opts?: object): boolean;
isFlow(opts?: object): this is NodePath<t.Flow>;
isRestProperty(opts?: object): boolean;
isSpreadProperty(opts?: object): boolean;
isExistentialTypeParam(opts?: object): boolean;
isNumericLiteralTypeAnnotation(opts?: object): boolean;
isForAwaitStatement(opts?: object): boolean;
}

View File

@ -0,0 +1,26 @@
/*
* 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 {
ReferencedIdentifier: t.Identifier | t.JSXIdentifier;
ReferencedMemberExpression: t.MemberExpression;
BindingIdentifier: t.Identifier;
Statement: t.Statement;
Expression: t.Expression;
Scope: t.Scopable | t.Pattern;
Referenced: t.Node;
BlockScoped: t.Node;
Var: t.VariableDeclaration;
User: t.Node;
Generated: t.Node;
Pure: t.Node;
Flow: t.Flow | t.ImportDeclaration | t.ExportDeclaration | t.ImportSpecifier;
RestProperty: t.RestElement;
SpreadProperty: t.RestElement;
ExistentialTypeParam: t.ExistsTypeAnnotation;
NumericLiteralTypeAnnotation: t.NumberLiteralTypeAnnotation;
ForAwaitStatement: t.ForOfStatement;
}

View File

@ -3,6 +3,7 @@ import type TraversalContext from "../context";
import * as virtualTypes from "./lib/virtual-types";
import buildDebug from "debug";
import traverse from "../index";
import type { Visitor } from "../types";
import Scope from "../scope";
import * as t from "@babel/types";
import { path as pathCache } from "../cache";
@ -20,6 +21,8 @@ import * as NodePath_removal from "./removal";
import * as NodePath_modification from "./modification";
import * as NodePath_family from "./family";
import * as NodePath_comments from "./comments";
import type { NodePathAssetions } from "./generated/asserts";
import type { NodePathValidators } from "./generated/validators";
const debug = buildDebug("babel");
@ -27,8 +30,8 @@ export const REMOVED = 1 << 0;
export const SHOULD_STOP = 1 << 1;
export const SHOULD_SKIP = 1 << 2;
export default class NodePath {
constructor(hub: HubInterface, parent: Object) {
class NodePath<T extends t.Node = t.Node> {
constructor(hub: HubInterface, parent: t.Node) {
this.parent = parent;
this.hub = hub;
this.data = null;
@ -37,26 +40,40 @@ export default class NodePath {
this.scope = null;
}
declare parent: Object;
declare parent: t.Node;
declare hub: HubInterface;
declare data: Object;
declare data: object;
declare context: TraversalContext;
declare scope: Scope;
contexts: Array<TraversalContext> = [];
state: any = null;
opts: ?Object = null;
opts: any = null;
// this.shouldSkip = false; this.shouldStop = false; this.removed = false;
_traverseFlags: number = 0;
skipKeys: ?Object = null;
parentPath: ?NodePath = null;
container: ?Object | Array<Object> = null;
listKey: ?string = null;
key: ?string = null;
node: ?Object = null;
type: ?string = null;
skipKeys: any = null;
parentPath: NodePath | null = null;
container: object | null | Array<any> = null;
listKey: string | null = null;
key: string | number | null = null;
node: T = null;
type: string | null = null;
static get({ hub, parentPath, parent, container, listKey, key }): NodePath {
static get({
hub,
parentPath,
parent,
container,
listKey,
key,
}: {
hub?;
parentPath;
parent;
container;
listKey?;
key;
}): NodePath {
if (!hub && parentPath) {
hub = parentPath.hub;
}
@ -104,22 +121,27 @@ export default class NodePath {
return val;
}
buildCodeFrameError(msg: string, Error: typeof Error = SyntaxError): Error {
buildCodeFrameError(
msg: string,
Error: new () => Error = SyntaxError,
): Error {
return this.hub.buildError(this.node, msg, Error);
}
traverse(visitor: Object, state?: any) {
traverse<T>(visitor: Visitor<T>, state: T): void;
traverse(visitor: Visitor): void;
traverse(visitor: any, state?: any) {
traverse(this.node, visitor, this.scope, state, this);
}
set(key: string, node: Object) {
set(key: string, node: any) {
t.validate(this.node, key, node);
this.node[key] = node;
}
getPathLocation(): string {
const parts = [];
let path = this;
let path: NodePath = this;
do {
let key = path.key;
if (path.inList) key = `${path.listKey}[${key}]`;
@ -203,7 +225,7 @@ Object.assign(
NodePath_comments,
);
for (const type of (t.TYPES: Array<string>)) {
for (const type of t.TYPES) {
const typeKey = `is${type}`;
const fn = t[typeKey];
NodePath.prototype[typeKey] = function (opts) {
@ -227,3 +249,23 @@ for (const type of Object.keys(virtualTypes)) {
return virtualType.checkPath(this, opts);
};
}
type NodePathMixins = typeof NodePath_ancestry &
typeof NodePath_inference &
typeof NodePath_replacement &
typeof NodePath_evaluation &
typeof NodePath_conversion &
typeof NodePath_introspection &
typeof NodePath_context &
typeof NodePath_removal &
typeof NodePath_modification &
typeof NodePath_family &
typeof NodePath_comments;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface NodePath<T>
extends NodePathAssetions,
NodePathValidators,
NodePathMixins {}
export default NodePath;

View File

@ -1,4 +1,4 @@
import type NodePath from "./index";
import type NodePath from "../index";
import * as inferers from "./inferers";
import * as t from "@babel/types";
@ -6,7 +6,7 @@ import * as t from "@babel/types";
* Infer the type of the current `NodePath`.
*/
export function getTypeAnnotation(): Object {
export function getTypeAnnotation(): t.FlowType {
if (this.typeAnnotation) return this.typeAnnotation;
let type = this._getTypeAnnotation() || t.anyTypeAnnotation();
@ -23,7 +23,7 @@ const typeAnnotationInferringNodes = new WeakSet();
* todo: split up this method
*/
export function _getTypeAnnotation(): ?Object {
export function _getTypeAnnotation(): any {
const node = this.node;
if (!node) {
@ -106,7 +106,7 @@ export function couldBeBaseType(name: string): boolean {
if (t.isAnyTypeAnnotation(type)) return true;
if (t.isUnionTypeAnnotation(type)) {
for (const type2 of (type.types: Array<Object>)) {
for (const type2 of type.types) {
if (t.isAnyTypeAnnotation(type2) || _isBaseType(name, type2, true)) {
return true;
}
@ -117,13 +117,14 @@ export function couldBeBaseType(name: string): boolean {
}
}
export function baseTypeStrictlyMatches(right: NodePath) {
export function baseTypeStrictlyMatches(rightArg: NodePath): boolean {
const left = this.getTypeAnnotation();
right = right.getTypeAnnotation();
const right = rightArg.getTypeAnnotation();
if (!t.isAnyTypeAnnotation(left) && t.isFlowBaseAnnotation(left)) {
return right.type === left.type;
}
return false;
}
export function isGenericType(genericName: string): boolean {

View File

@ -1,7 +1,8 @@
import type NodePath from "../index";
import * as t from "@babel/types";
import type Binding from "../../scope/binding";
export default function (node: Object) {
export default function (node: any) {
if (!this.isReferenced()) return;
// check if a binding exists of this value and if so then return a union type of all
@ -86,7 +87,7 @@ function getTypeAnnotationBindingConstantViolations(binding, path, name) {
constantViolations = constantViolations.concat(functionConstantViolations);
// push on inferred types of violated paths
for (const violation of (constantViolations: Array<NodePath>)) {
for (const violation of constantViolations) {
types.push(violation.getTypeAnnotation());
}
}
@ -106,7 +107,7 @@ function getTypeAnnotationBindingConstantViolations(binding, path, name) {
return t.createUnionTypeAnnotation(types);
}
function getConstantViolationsBefore(binding, path, functions) {
function getConstantViolationsBefore(binding: Binding, path, functions?) {
const violations = binding.constantViolations.slice();
violations.unshift(binding.path);
return violations.filter(violation => {
@ -117,7 +118,10 @@ function getConstantViolationsBefore(binding, path, functions) {
});
}
function inferAnnotationFromBinaryExpression(name, path) {
function inferAnnotationFromBinaryExpression(
name: string,
path: NodePath<t.BinaryExpression>,
) {
const operator = path.node.operator;
const right = path.get("right").resolve();
@ -144,14 +148,14 @@ function inferAnnotationFromBinaryExpression(name, path) {
if (operator !== "===" && operator !== "==") return;
//
let typeofPath;
let typePath;
let typeofPath: NodePath<t.UnaryExpression>;
let typePath: NodePath<t.Expression>;
if (left.isUnaryExpression({ operator: "typeof" })) {
typeofPath = left;
typePath = right;
typePath = right as NodePath<t.Expression>;
} else if (right.isUnaryExpression({ operator: "typeof" })) {
typeofPath = right;
typePath = left;
typePath = left as NodePath<t.Expression>;
}
if (!typeofPath) return;
@ -159,14 +163,16 @@ function inferAnnotationFromBinaryExpression(name, path) {
if (!typeofPath.get("argument").isIdentifier({ name })) return;
// ensure that the type path is a Literal
typePath = typePath.resolve();
typePath = typePath.resolve() as NodePath<t.Expression>;
if (!typePath.isLiteral()) return;
// and that it's a string so we can infer it
// @ts-expect-error todo(flow->ts): value is not defined for NullLiteral and some other
const typeValue = typePath.node.value;
if (typeof typeValue !== "string") return;
// turn type value into a type annotation
// @ts-expect-error todo(flow->ts): move validation from helper or relax type constraint to just a string
return t.createTypeAnnotationBasedOnTypeof(typeValue);
}
@ -188,7 +194,11 @@ function getParentConditionalPath(binding, path, name) {
}
}
function getConditionalAnnotation(binding, path, name) {
function getConditionalAnnotation<T extends t.Node>(
binding: Binding,
path: NodePath<T>,
name?,
) {
const ifStatement = getParentConditionalPath(binding, path, name);
if (!ifStatement) return;

View File

@ -11,6 +11,7 @@ import * as t from "@babel/types";
*/
export function matchesPattern(
this: NodePath,
pattern: string,
allowPartial?: boolean,
): boolean {
@ -22,7 +23,7 @@ export function matchesPattern(
* if the array has any items, otherwise we just check if it's falsy.
*/
export function has(key): boolean {
export function has(this: NodePath, key: string): boolean {
const val = this.node && this.node[key];
if (val && Array.isArray(val)) {
return !!val.length;
@ -35,7 +36,7 @@ export function has(key): boolean {
* Description
*/
export function isStatic() {
export function isStatic(this: NodePath): boolean {
return this.scope.isStatic(this.node);
}
@ -49,7 +50,7 @@ export const is = has;
* Opposite of `has`.
*/
export function isnt(key): boolean {
export function isnt(this: NodePath, key: string): boolean {
return !this.has(key);
}
@ -57,7 +58,7 @@ export function isnt(key): boolean {
* Check whether the path node `key` strict equals `value`.
*/
export function equals(key, value): boolean {
export function equals(this: NodePath, key: string, value): boolean {
return this.node[key] === value;
}
@ -66,7 +67,7 @@ export function equals(key, value): boolean {
* been removed yet we still internally know the type and need it to calculate node replacement.
*/
export function isNodeType(type: string): boolean {
export function isNodeType(this: NodePath, type: string): boolean {
return t.isType(this.type, type);
}
@ -80,7 +81,7 @@ export function isNodeType(type: string): boolean {
* to tell the path replacement that it's ok to replace this with an expression.
*/
export function canHaveVariableDeclarationOrExpression() {
export function canHaveVariableDeclarationOrExpression(this: NodePath) {
return (
(this.key === "init" || this.key === "left") && this.parentPath.isFor()
);
@ -94,7 +95,10 @@ export function canHaveVariableDeclarationOrExpression() {
* is the same as containing a block statement.
*/
export function canSwapBetweenExpressionAndStatement(replacement) {
export function canSwapBetweenExpressionAndStatement(
this: NodePath,
replacement: t.Node,
): boolean {
if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) {
return false;
}
@ -112,7 +116,10 @@ export function canSwapBetweenExpressionAndStatement(replacement) {
* Check whether the current path references a completion record
*/
export function isCompletionRecord(allowInsideFunction?) {
export function isCompletionRecord(
this: NodePath,
allowInsideFunction?: boolean,
): boolean {
let path = this;
let first = true;
@ -141,14 +148,14 @@ export function isCompletionRecord(allowInsideFunction?) {
* so we can explode it if necessary.
*/
export function isStatementOrBlock() {
export function isStatementOrBlock(this: NodePath): boolean {
if (
this.parentPath.isLabeledStatement() ||
t.isBlockStatement(this.container)
) {
return false;
} else {
return t.STATEMENT_OR_BLOCK_KEYS.includes(this.key);
return t.STATEMENT_OR_BLOCK_KEYS.includes(this.key as string);
}
}
@ -156,7 +163,11 @@ export function isStatementOrBlock() {
* Check if the currently assigned path references the `importName` of `moduleSource`.
*/
export function referencesImport(moduleSource, importName) {
export function referencesImport(
this: NodePath<t.Identifier>,
moduleSource: string,
importName: string,
): boolean {
if (!this.isReferencedIdentifier()) return false;
const binding = this.scope.getBinding(this.node.name);
@ -181,7 +192,10 @@ export function referencesImport(moduleSource, importName) {
return true;
}
if (path.isImportSpecifier() && path.node.imported.name === importName) {
if (
path.isImportSpecifier() &&
t.isIdentifier(path.node.imported, { name: importName })
) {
return true;
}
@ -192,7 +206,7 @@ export function referencesImport(moduleSource, importName) {
* Get the source code associated with this node.
*/
export function getSource() {
export function getSource(this: NodePath): string {
const node = this.node;
if (node.end) {
const code = this.hub.getCode();
@ -201,7 +215,7 @@ export function getSource() {
return "";
}
export function willIMaybeExecuteBefore(target) {
export function willIMaybeExecuteBefore(this: NodePath, target): boolean {
return this._guessExecutionStatusRelativeTo(target) !== "after";
}
@ -282,6 +296,7 @@ type RelativeExecutionStatus = "before" | "after" | "unknown";
*/
export function _guessExecutionStatusRelativeTo(
this: NodePath,
target: NodePath,
): RelativeExecutionStatus {
// check if the two paths are in different functions, we can't track execution of these
@ -354,8 +369,8 @@ export function _guessExecutionStatusRelativeTo(
// otherwise we're associated by a parent node, check which key comes before the other
const keys = t.VISITOR_KEYS[commonPath.type];
const keyPosition = {
this: keys.indexOf(divergence.this.parentKey),
target: keys.indexOf(divergence.target.parentKey),
this: keys.indexOf(divergence.this.parentKey as string),
target: keys.indexOf(divergence.target.parentKey as string),
};
return keyPosition.target > keyPosition.this ? "before" : "after";
}
@ -367,6 +382,7 @@ export function _guessExecutionStatusRelativeTo(
const executionOrderCheckedNodes = new WeakSet();
export function _guessExecutionStatusRelativeToDifferentFunctions(
this: NodePath,
target: NodePath,
): RelativeExecutionStatus {
if (
@ -423,12 +439,15 @@ export function _guessExecutionStatusRelativeToDifferentFunctions(
/**
* Resolve a "pointer" `NodePath` to it's absolute path.
*/
export function resolve(dangerous, resolved) {
export function resolve(this: NodePath, dangerous?, resolved?) {
return this._resolve(dangerous, resolved) || this;
}
export function _resolve(dangerous?, resolved?): ?NodePath {
export function _resolve(
this: NodePath,
dangerous?,
resolved?,
): NodePath | undefined | null {
// detect infinite recursion
// todo: possibly have a max length on this just to be safe
if (resolved && resolved.indexOf(this) >= 0) return;
@ -444,6 +463,7 @@ export function _resolve(dangerous?, resolved?): ?NodePath {
// otherwise it's a request for a pattern and that's a bit more tricky
}
} else if (this.isReferencedIdentifier()) {
// @ts-expect-error todo(flow->ts): think about options to improve type refinements
const binding = this.scope.getBinding(this.node.name);
if (!binding) return;
@ -460,6 +480,7 @@ export function _resolve(dangerous?, resolved?): ?NodePath {
return ret;
}
} else if (this.isTypeCastExpression()) {
// @ ts-ignore todo: babel-types
return this.get("expression").resolve(dangerous, resolved);
} else if (dangerous && this.isMemberExpression()) {
// this is dangerous, as non-direct target assignments will mutate it's state
@ -468,13 +489,14 @@ export function _resolve(dangerous?, resolved?): ?NodePath {
const targetKey = this.toComputedKey();
if (!t.isLiteral(targetKey)) return;
// @ts-expect-error todo(flow->ts): NullLiteral
const targetName = targetKey.value;
const target = this.get("object").resolve(dangerous, resolved);
if (target.isObjectExpression()) {
const props = target.get("properties");
for (const prop of (props: Array)) {
for (const prop of props as any[]) {
if (!prop.isProperty()) continue;
const key = prop.get("key");
@ -496,7 +518,7 @@ export function _resolve(dangerous?, resolved?): ?NodePath {
}
}
export function isConstantExpression() {
export function isConstantExpression(this: NodePath) {
if (this.isIdentifier()) {
const binding = this.scope.getBinding(this.node.name);
if (!binding) return false;
@ -518,7 +540,7 @@ export function isConstantExpression() {
}
if (this.isUnaryExpression()) {
if (this.get("operator").node !== "void") {
if (this.node.operator !== "void") {
return false;
}
@ -535,7 +557,7 @@ export function isConstantExpression() {
return false;
}
export function isInStrictMode() {
export function isInStrictMode(this: NodePath) {
const start = this.isProgram() ? this : this.parentPath;
const strictParent = start.find(path => {
@ -552,10 +574,11 @@ export function isInStrictMode() {
return false;
}
let { node } = path;
if (path.isFunction()) node = node.body;
const body: t.BlockStatement | t.Program = path.isFunction()
? (path.node.body as t.BlockStatement)
: (path.node as t.Program);
for (const directive of node.directives) {
for (const directive of body.directives) {
if (directive.value.value === "use strict") {
return true;
}

View File

@ -1,7 +1,11 @@
import { react } from "@babel/types";
import * as t from "@babel/types";
import type Scope from "../../scope";
import type NodePath from "../index";
import type Binding from "../../scope/binding";
import type { Visitor } from "../../types";
const referenceVisitor = {
const referenceVisitor: Visitor<PathHoister> = {
// This visitor looks for bindings to establish a topmost scope for hoisting.
ReferencedIdentifier(path, state) {
// Don't hoist regular JSX identifiers ('div', 'span', etc).
@ -49,8 +53,16 @@ const referenceVisitor = {
},
};
export default class PathHoister {
constructor(path, scope) {
export default class PathHoister<T extends t.Node = t.Node> {
breakOnScopePaths: NodePath[];
bindings: { [k: string]: Binding };
mutableBinding: boolean;
private scopes: Scope[];
scope: Scope;
private path: NodePath<T>;
private attachAfter: boolean;
constructor(path: NodePath<T>, scope: Scope) {
// Storage for scopes we can't hoist above.
this.breakOnScopePaths = [];
// Storage for bindings that may affect what path we can hoist to.
@ -131,7 +143,7 @@ export default class PathHoister {
path = binding.path;
// We also move past any constant violations.
for (const violationPath of (binding.constantViolations: Array)) {
for (const violationPath of binding.constantViolations) {
if (this.getAttachmentParentForPath(violationPath).key > path.key) {
path = violationPath;
}
@ -156,10 +168,11 @@ export default class PathHoister {
if (this.scope === scope) return;
// needs to be attached to the body
const bodies = scope.path.get("body").get("body");
const bodies = scope.path.get("body").get("body") as NodePath[];
for (let i = 0; i < bodies.length; i++) {
// Don't attach to something that's going to get hoisted,
// like a default parameter
// @ts-expect-error todo(flow->ts): avoid mutating the node, introducing new fields
if (bodies[i].node._blockHoist) continue;
return bodies[i];
}
@ -221,6 +234,7 @@ export default class PathHoister {
// generate declaration and insert it to our point
let uid = attachTo.scope.generateUidIdentifier("ref");
// @ts-expect-error todo(flow->ts): more specific type for this.path
const declarator = t.variableDeclarator(uid, this.path.node);
const insertFn = this.attachAfter ? "insertAfter" : "insertBefore";
@ -234,7 +248,7 @@ export default class PathHoister {
if (parent.isJSXElement() && this.path.container === parent.node.children) {
// turning the `span` in `<div><span /></div>` to an expression so we need to wrap it with
// an expression container
uid = t.JSXExpressionContainer(uid);
uid = t.jsxExpressionContainer(uid);
}
this.path.replaceWith(t.cloneNode(uid));

View File

@ -4,7 +4,7 @@ import * as t from "@babel/types";
export const ReferencedIdentifier = {
types: ["Identifier", "JSXIdentifier"],
checkPath(path: NodePath, opts?: Object): boolean {
checkPath(path: NodePath, opts?: any): boolean {
const { node, parent } = path;
if (!t.isIdentifier(node, opts) && !t.isJSXMemberExpression(parent, opts)) {
if (t.isJSXIdentifier(node, opts)) {
@ -116,6 +116,7 @@ export const Flow = {
} else if (t.isImportDeclaration(node)) {
return node.importKind === "type" || node.importKind === "typeof";
} else if (t.isExportDeclaration(node)) {
// @ts-expect-error todo(flow->ts) `exportKind` does not exist on ExportAllDeclaration
return node.exportKind === "type";
} else if (t.isImportSpecifier(node)) {
return node.importKind === "type" || node.importKind === "typeof";
@ -150,7 +151,7 @@ export const NumericLiteralTypeAnnotation = {
export const ForAwaitStatement = {
types: ["ForOfStatement"],
checkPath({ node }: NodePath): boolean {
checkPath({ node }: NodePath<t.ForOfStatement>): boolean {
return node.await === true;
},
};

View File

@ -4,15 +4,16 @@ import { path as pathCache } from "../cache";
import PathHoister from "./lib/hoister";
import NodePath from "./index";
import * as t from "@babel/types";
import type Scope from "../scope";
/**
* Insert the provided nodes before the current one.
*/
export function insertBefore(nodes) {
export function insertBefore(this: NodePath, nodes_: t.Node | t.Node[]) {
this._assertUnremoved();
nodes = this._verifyNodeList(nodes);
const nodes = this._verifyNodeList(nodes_);
const { parentPath } = this;
@ -28,17 +29,18 @@ export function insertBefore(nodes) {
(parentPath.isForStatement() && this.key === "init")
) {
if (this.node) nodes.push(this.node);
// @ts-expect-error todo(flow->ts): check that nodes is an array of statements
return this.replaceExpressionWithStatements(nodes);
} else if (Array.isArray(this.container)) {
return this._containerInsertBefore(nodes);
} else if (this.isStatementOrBlock()) {
const node = this.node as t.Statement;
const shouldInsertCurrentNode =
this.node &&
(!this.isExpressionStatement() || this.node.expression != null);
node &&
(!this.isExpressionStatement() ||
(node as t.ExpressionStatement).expression != null);
this.replaceWith(
t.blockStatement(shouldInsertCurrentNode ? [this.node] : []),
);
this.replaceWith(t.blockStatement(shouldInsertCurrentNode ? [node] : []));
return this.unshiftContainer("body", nodes);
} else {
throw new Error(
@ -48,11 +50,12 @@ export function insertBefore(nodes) {
}
}
export function _containerInsert(from, nodes) {
export function _containerInsert(this: NodePath, from, nodes) {
this.updateSiblingKeys(from, nodes.length);
const paths = [];
// @ts-expect-error todo(flow->ts): this.container could be a NodePath
this.container.splice(from, 0, ...nodes);
for (let i = 0; i < nodes.length; i++) {
const to = from + i;
@ -78,11 +81,12 @@ export function _containerInsert(from, nodes) {
return paths;
}
export function _containerInsertBefore(nodes) {
export function _containerInsertBefore(this: NodePath, nodes) {
return this._containerInsert(this.key, nodes);
}
export function _containerInsertAfter(nodes) {
export function _containerInsertAfter(this: NodePath, nodes) {
// @ts-expect-error todo(flow->ts): this.key could be a string
return this._containerInsert(this.key + 1, nodes);
}
@ -91,10 +95,10 @@ export function _containerInsertAfter(nodes) {
* expression, ensure that the completion record is correct by pushing the current node.
*/
export function insertAfter(nodes) {
export function insertAfter(this: NodePath, nodes_: t.Node | t.Node[]) {
this._assertUnremoved();
nodes = this._verifyNodeList(nodes);
const nodes = this._verifyNodeList(nodes_);
const { parentPath } = this;
if (
@ -121,31 +125,36 @@ export function insertAfter(nodes) {
(parentPath.isForStatement() && this.key === "init")
) {
if (this.node) {
const node = this.node as t.Expression | t.VariableDeclaration;
let { scope } = this;
// Inserting after the computed key of a method should insert the
// temporary binding in the method's parent's scope.
if (parentPath.isMethod({ computed: true, key: this.node })) {
if (parentPath.isMethod({ computed: true, key: node })) {
scope = scope.parent;
}
const temp = scope.generateDeclaredUidIdentifier();
nodes.unshift(
t.expressionStatement(
t.assignmentExpression("=", t.cloneNode(temp), this.node),
// @ts-expect-error todo(flow->ts): This can be a variable
// declaraion in the "init" of a for statement, but that's
// invalid here.
t.assignmentExpression("=", t.cloneNode(temp), node),
),
);
nodes.push(t.expressionStatement(t.cloneNode(temp)));
}
// @ts-expect-error todo(flow->ts): check that nodes is an array of statements
return this.replaceExpressionWithStatements(nodes);
} else if (Array.isArray(this.container)) {
return this._containerInsertAfter(nodes);
} else if (this.isStatementOrBlock()) {
const node = this.node as t.Statement;
const shouldInsertCurrentNode =
this.node &&
(!this.isExpressionStatement() || this.node.expression != null);
node &&
(!this.isExpressionStatement() ||
(node as t.ExpressionStatement).expression != null);
this.replaceWith(
t.blockStatement(shouldInsertCurrentNode ? [this.node] : []),
);
this.replaceWith(t.blockStatement(shouldInsertCurrentNode ? [node] : []));
return this.pushContainer("body", nodes);
} else {
throw new Error(
@ -159,7 +168,11 @@ export function insertAfter(nodes) {
* Update all sibling node paths after `fromIndex` by `incrementBy`.
*/
export function updateSiblingKeys(fromIndex, incrementBy) {
export function updateSiblingKeys(
this: NodePath,
fromIndex: number,
incrementBy: number,
) {
if (!this.parent) return;
const paths = pathCache.get(this.parent);
@ -170,12 +183,15 @@ export function updateSiblingKeys(fromIndex, incrementBy) {
}
}
export function _verifyNodeList(nodes) {
export function _verifyNodeList(
this: NodePath,
nodes: t.Node | t.Node[],
): t.Node[] {
if (!nodes) {
return [];
}
if (nodes.constructor !== Array) {
if (!Array.isArray(nodes)) {
nodes = [nodes];
}
@ -204,7 +220,11 @@ export function _verifyNodeList(nodes) {
return nodes;
}
export function unshiftContainer(listKey, nodes) {
export function unshiftContainer<Nodes extends t.Node | t.Node[]>(
listKey: string,
nodes: Nodes,
): NodePath[] {
// todo: NodePaths<Nodes>
this._assertUnremoved();
nodes = this._verifyNodeList(nodes);
@ -222,10 +242,14 @@ export function unshiftContainer(listKey, nodes) {
return path._containerInsertBefore(nodes);
}
export function pushContainer(listKey, nodes) {
export function pushContainer(
this: NodePath,
listKey: string,
nodes: t.Node | t.Node[],
) {
this._assertUnremoved();
nodes = this._verifyNodeList(nodes);
const verifiedNodes = this._verifyNodeList(nodes);
// get an invisible path that represents the last node + 1 and replace it with our
// nodes, effectively inlining it
@ -239,15 +263,17 @@ export function pushContainer(listKey, nodes) {
key: container.length,
}).setContext(this.context);
return path.replaceWithMultiple(nodes);
return path.replaceWithMultiple(verifiedNodes);
}
/**
* Hoist the current node to the highest scope possible and return a UID
* referencing it.
*/
export function hoist(scope = this.scope) {
const hoister = new PathHoister(this, scope);
export function hoist<T extends t.Node>(
this: NodePath<T>,
scope: Scope = this.scope,
) {
const hoister = new PathHoister<T>(this, scope);
return hoister.run();
}

View File

@ -2,9 +2,9 @@
import { hooks } from "./lib/removal-hooks";
import { path as pathCache } from "../cache";
import { REMOVED, SHOULD_SKIP } from "./index";
import NodePath, { REMOVED, SHOULD_SKIP } from "./index";
export function remove() {
export function remove(this: NodePath) {
this._assertUnremoved();
this.resync();
@ -22,34 +22,34 @@ export function remove() {
this._markRemoved();
}
export function _removeFromScope() {
export function _removeFromScope(this: NodePath) {
const bindings = this.getBindingIdentifiers();
Object.keys(bindings).forEach(name => this.scope.removeBinding(name));
}
export function _callRemovalHooks() {
for (const fn of (hooks: Array<Function>)) {
export function _callRemovalHooks(this: NodePath) {
for (const fn of hooks) {
if (fn(this, this.parentPath)) return true;
}
}
export function _remove() {
export function _remove(this: NodePath) {
if (Array.isArray(this.container)) {
this.container.splice(this.key, 1);
this.updateSiblingKeys(this.key, -1);
this.container.splice(this.key as number, 1);
this.updateSiblingKeys(this.key as number, -1);
} else {
this._replaceWith(null);
}
}
export function _markRemoved() {
export function _markRemoved(this: NodePath) {
// this.shouldSkip = true; this.removed = true;
this._traverseFlags |= SHOULD_SKIP | REMOVED;
if (this.parent) pathCache.get(this.parent).delete(this.node);
this.node = null;
}
export function _assertUnremoved() {
export function _assertUnremoved(this: NodePath) {
if (this.removed) {
throw this.buildCodeFrameError(
"NodePath has been removed so is read-only.",

View File

@ -22,7 +22,7 @@ const hoistVariablesVisitor = {
const exprs = [];
for (const declar of (path.node.declarations: Array<Object>)) {
for (const declar of path.node.declarations as Array<any>) {
if (declar.init) {
exprs.push(
t.expressionStatement(
@ -44,7 +44,10 @@ const hoistVariablesVisitor = {
* - Remove the current node.
*/
export function replaceWithMultiple(nodes: Array<Object>) {
export function replaceWithMultiple<Nodes extends Array<t.Node>>(
nodes: Nodes,
): NodePath[] {
// todo NodePaths
this.resync();
nodes = this._verifyNodeList(nodes);
@ -70,7 +73,7 @@ export function replaceWithMultiple(nodes: Array<Object>) {
* easier to use, your transforms will be extremely brittle.
*/
export function replaceWithSourceString(replacement) {
export function replaceWithSourceString(this: NodePath, replacement) {
this.resync();
try {
@ -101,7 +104,7 @@ export function replaceWithSourceString(replacement) {
* Replace the current node with another.
*/
export function replaceWith(replacement) {
export function replaceWith(this: NodePath, replacement: t.Node | NodePath) {
this.resync();
if (this.removed) {
@ -187,15 +190,16 @@ export function replaceWith(replacement) {
* Description
*/
export function _replaceWith(node) {
export function _replaceWith(this: NodePath, node) {
if (!this.container) {
throw new ReferenceError("Container is falsy");
}
if (this.inList) {
// @ts-expect-error todo(flow->ts): check if t.validate accepts a numeric key
t.validate(this.parent, this.key, [node]);
} else {
t.validate(this.parent, this.key, node);
t.validate(this.parent, this.key as string, node);
}
this.debug(`Replace with ${node?.type}`);
@ -210,7 +214,10 @@ export function _replaceWith(node) {
* extremely important to retain original semantics.
*/
export function replaceExpressionWithStatements(nodes: Array<Object>) {
export function replaceExpressionWithStatements(
this: NodePath,
nodes: Array<t.Statement>,
) {
this.resync();
const toSequenceExpression = t.toSequenceExpression(nodes, this.scope);
@ -225,12 +232,17 @@ export function replaceExpressionWithStatements(nodes: Array<Object>) {
const container = t.arrowFunctionExpression([], t.blockStatement(nodes));
this.replaceWith(t.callExpression(container, []));
// replaceWith changes the type of "this", but it isn't trackable by TS
type ThisType = NodePath<
t.CallExpression & { callee: t.ArrowFunctionExpression }
>;
this.traverse(hoistVariablesVisitor);
// add implicit returns to all ending expression statements
const completionRecords: Array<NodePath> = this.get(
"callee",
).getCompletionRecords();
const completionRecords: Array<NodePath> = (this as ThisType)
.get("callee")
.getCompletionRecords();
for (const path of completionRecords) {
if (!path.isExpressionStatement()) continue;
@ -239,7 +251,7 @@ export function replaceExpressionWithStatements(nodes: Array<Object>) {
let uid = loop.getData("expressionReplacementReturnUid");
if (!uid) {
const callee = this.get("callee");
const callee = (this as ThisType).get("callee");
uid = callee.scope.generateDeclaredUidIdentifier("ret");
callee
.get("body")
@ -259,26 +271,26 @@ export function replaceExpressionWithStatements(nodes: Array<Object>) {
}
}
const callee = this.get("callee");
const callee = this.get("callee") as NodePath<t.FunctionExpression>;
callee.arrowFunctionToExpression();
// (() => await xxx)() -> await (async () => await xxx)();
if (
isParentAsync &&
traverse.hasType(
this.get("callee.body").node,
(this.get("callee.body") as NodePath<t.BlockStatement>).node,
"AwaitExpression",
t.FUNCTION_TYPES,
)
) {
callee.set("async", true);
this.replaceWith(t.awaitExpression(this.node));
this.replaceWith(t.awaitExpression((this as ThisType).node));
}
return callee.get("body.body");
}
export function replaceInline(nodes: Object | Array<Object>) {
export function replaceInline(this: NodePath, nodes: t.Node | Array<t.Node>) {
this.resync();
if (Array.isArray(nodes)) {

View File

@ -1,5 +1,16 @@
import type NodePath from "../path";
import type * as t from "@babel/types";
import type Scope from "./index";
type BindingKind =
| "var"
| "let"
| "const"
| "module"
| "hoisted"
| "param"
| "local"
| "unknown";
/**
* This class is responsible for a binding inside of a scope.
*
@ -12,7 +23,22 @@ import type NodePath from "../path";
*/
export default class Binding {
constructor({ identifier, scope, path, kind }) {
identifier: t.Identifier;
scope: Scope;
path: NodePath;
kind: BindingKind;
constructor({
identifier,
scope,
path,
kind,
}: {
identifier: t.Identifier;
scope: Scope;
path: NodePath;
kind: BindingKind;
}) {
this.identifier = identifier;
this.scope = scope;
this.path = path;
@ -53,7 +79,7 @@ export default class Binding {
* Register a constant violation with the provided `path`.
*/
reassign(path: Object) {
reassign(path: any) {
this.constant = false;
if (this.constantViolations.indexOf(path) !== -1) {
return;

View File

@ -1,26 +1,57 @@
import Renamer from "./lib/renamer";
import type NodePath from "../path";
import traverse from "../index";
import type { TraverseOptions } from "../index";
import Binding from "./binding";
import globals from "globals";
import * as t from "@babel/types";
import { scope as scopeCache } from "../cache";
import type { Visitor } from "../types";
// Recursively gathers the identifying names of a node.
function gatherNodeParts(node: Object, parts: Array) {
function gatherNodeParts(node: t.Node, parts: any[]) {
switch (node?.type) {
default:
if (t.isModuleDeclaration(node)) {
if (node.source) {
if (
(t.isExportAllDeclaration(node) ||
t.isExportNamedDeclaration(node) ||
t.isImportDeclaration(node)) &&
node.source
) {
gatherNodeParts(node.source, parts);
} else if (node.specifiers && node.specifiers.length) {
} else if (
(t.isExportNamedDeclaration(node) || t.isImportDeclaration(node)) &&
node.specifiers &&
node.specifiers.length
) {
for (const e of node.specifiers) gatherNodeParts(e, parts);
} else if (node.declaration) {
} else if (
(t.isExportDefaultDeclaration(node) ||
t.isExportNamedDeclaration(node)) &&
node.declaration
) {
gatherNodeParts(node.declaration, parts);
}
} else if (t.isModuleSpecifier(node)) {
// todo(flow->ts): should condition instead be:
// ```
// t.isExportSpecifier(node) ||
// t.isImportDefaultSpecifier(node) ||
// t.isImportNamespaceSpecifier(node) ||
// t.isImportSpecifier(node)
// ```
// allowing only nodes with `.local`?
// @ts-expect-error todo(flow->ts)
gatherNodeParts(node.local, parts);
} else if (t.isLiteral(node)) {
// todo(flow->ts): should condition be stricter to ensure value is there
// ```
// !t.isNullLiteral(node) &&
// !t.isRegExpLiteral(node) &&
// !t.isTemplateLiteral(node)
// ```
// @ts-expect-error todo(flow->ts)
parts.push(node.value);
}
break;
@ -147,11 +178,17 @@ function gatherNodeParts(node: Object, parts: Array) {
}
//
interface CollectVisitorState {
assignments: NodePath<t.AssignmentExpression>[];
references: NodePath<t.Identifier | t.JSXIdentifier>[];
constantViolations: NodePath[];
}
const collectorVisitor = {
const collectorVisitor: Visitor<CollectVisitorState> = {
For(path) {
for (const key of (t.FOR_INIT_KEYS: Array)) {
const declar = path.get(key);
for (const key of t.FOR_INIT_KEYS) {
// todo: might be not needed with improvement to babel-types
const declar = path.get(key) as NodePath;
// delegate block scope handling to the `BlockScoped` method
if (declar.isVar()) {
const parentScope =
@ -166,6 +203,7 @@ const collectorVisitor = {
if (path.isBlockScoped()) return;
// this will be hit again once we traverse into it after this iteration
// @ts-expect-error todo(flow->ts): might be not correct for export all declaration
if (path.isExportDeclaration() && path.get("declaration").isDeclaration()) {
return;
}
@ -190,6 +228,7 @@ const collectorVisitor = {
ExportDeclaration: {
exit(path) {
const { node, scope } = path;
// @ts-expect-error todo(flow->ts) declaration is not present on ExportAllDeclaration
const declar = node.declaration;
if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) {
const id = declar.id;
@ -198,7 +237,7 @@ const collectorVisitor = {
const binding = scope.getBinding(id.name);
if (binding) binding.reference(path);
} else if (t.isVariableDeclaration(declar)) {
for (const decl of (declar.declarations: Array<Object>)) {
for (const decl of declar.declarations) {
for (const name of Object.keys(t.getBindingIdentifiers(decl))) {
const binding = scope.getBinding(name);
if (binding) binding.reference(path);
@ -209,6 +248,7 @@ const collectorVisitor = {
},
LabeledStatement(path) {
// @ts-expect-error todo(flow->ts): possible bug - statement might not have name and so should not be added as global
path.scope.getProgramParent().addGlobal(path.node);
path.scope.getBlockParent().registerDeclaration(path);
},
@ -245,7 +285,7 @@ const collectorVisitor = {
Block(path) {
const paths = path.get("body");
for (const bodyPath of (paths: Array)) {
for (const bodyPath of paths) {
if (bodyPath.isFunctionDeclaration()) {
path.scope.getBlockParent().registerDeclaration(bodyPath);
}
@ -281,11 +321,25 @@ const collectorVisitor = {
let uid = 0;
export default class Scope {
uid;
path: NodePath;
block: t.Node;
labels;
inited;
bindings: { [name: string]: Binding };
references: object;
globals: object;
uids: object;
data: object;
crawling: boolean;
/**
* This searches the current "scope" and collects all references/bindings
* within.
*/
constructor(path: NodePath) {
const { node } = path;
const cached = scopeCache.get(node);
@ -330,11 +384,16 @@ export default class Scope {
return this.path.hub;
}
traverse<S>(
node: t.Node | t.Node[],
opts: TraverseOptions<S>,
state: S,
): void;
traverse(node: t.Node | t.Node[], opts?: TraverseOptions, state?: any): void;
/**
* Traverse node with current scope and path.
*/
traverse(node: Object, opts: Object, state?) {
traverse(node: any, opts: any, state?) {
traverse(node, opts, this, state, this.path);
}
@ -360,7 +419,7 @@ export default class Scope {
* Generate a unique `_id1` binding.
*/
generateUid(name: string = "temp") {
generateUid(name: string = "temp"): string {
name = t
.toIdentifier(name)
.replace(/^_+/, "")
@ -395,7 +454,7 @@ export default class Scope {
return `_${id}`;
}
generateUidBasedOnNode(node: Object, defaultName?: String) {
generateUidBasedOnNode(node: t.Node, defaultName?: string) {
const parts = [];
gatherNodeParts(node, parts);
@ -409,7 +468,7 @@ export default class Scope {
* Generate a unique identifier based on a node.
*/
generateUidIdentifierBasedOnNode(node: Object, defaultName?: String): Object {
generateUidIdentifierBasedOnNode(node: t.Node, defaultName?: string) {
return t.identifier(this.generateUidBasedOnNode(node, defaultName));
}
@ -423,7 +482,7 @@ export default class Scope {
* - Bound identifiers
*/
isStatic(node: Object): boolean {
isStatic(node: t.Node): boolean {
if (t.isThisExpression(node) || t.isSuper(node)) {
return true;
}
@ -444,7 +503,7 @@ export default class Scope {
* Possibly generate a memoised identifier if it is not static and has consequences.
*/
maybeGenerateMemoised(node: Object, dontPush?: boolean): ?Object {
maybeGenerateMemoised(node: t.Node, dontPush?: boolean) {
if (this.isStatic(node)) {
return null;
} else {
@ -457,7 +516,12 @@ export default class Scope {
}
}
checkBlockScopedCollisions(local, kind: string, name: string, id: Object) {
checkBlockScopedCollisions(
local: Binding,
kind: string,
name: string,
id: any,
) {
// ignore parameters
if (kind === "param") return;
@ -483,7 +547,7 @@ export default class Scope {
}
}
rename(oldName: string, newName: string, block?) {
rename(oldName: string, newName?: string, block?: t.Node) {
const binding = this.getBinding(oldName);
if (binding) {
newName = newName || this.generateUidIdentifier(oldName).name;
@ -501,7 +565,7 @@ export default class Scope {
dump() {
const sep = "-".repeat(60);
console.log(sep);
let scope = this;
let scope: Scope = this;
do {
console.log("#", scope.block.type);
for (const name of Object.keys(scope.bindings)) {
@ -518,7 +582,7 @@ export default class Scope {
}
// TODO: (Babel 8) Split i in two parameters, and use an object of flags
toArray(node: Object, i?: number | boolean, allowArrayLike?: boolean) {
toArray(node: t.Node, i?: number | boolean, allowArrayLike?: boolean) {
if (t.isIdentifier(node)) {
const binding = this.getBinding(node.name);
if (binding?.constant && binding.path.isGenericType("Array")) {
@ -567,6 +631,7 @@ export default class Scope {
helperName = "maybeArrayLike";
}
// @ts-expect-error todo(flow->ts): t.Node is not valid to use in args, function argument typeneeds to be clarified
return t.callExpression(this.hub.addHelper(helperName), args);
}
@ -578,7 +643,7 @@ export default class Scope {
return this.labels.get(name);
}
registerLabel(path: NodePath) {
registerLabel(path: NodePath<t.LabeledStatement>) {
this.labels.set(path.node.label.name, path);
}
@ -589,18 +654,19 @@ export default class Scope {
this.registerBinding("hoisted", path.get("id"), path);
} else if (path.isVariableDeclaration()) {
const declarations = path.get("declarations");
for (const declar of (declarations: Array)) {
for (const declar of declarations) {
this.registerBinding(path.node.kind, declar);
}
} else if (path.isClassDeclaration()) {
this.registerBinding("let", path);
} else if (path.isImportDeclaration()) {
const specifiers = path.get("specifiers");
for (const specifier of (specifiers: Array)) {
for (const specifier of specifiers) {
this.registerBinding("module", specifier);
}
} else if (path.isExportDeclaration()) {
const declar = path.get("declaration");
// todo: improve babel-types
const declar = path.get("declaration") as NodePath;
if (
declar.isClassDeclaration() ||
declar.isFunctionDeclaration() ||
@ -625,7 +691,11 @@ export default class Scope {
}
}
registerBinding(kind: string, path: NodePath, bindingPath = path) {
registerBinding(
kind: Binding["kind"],
path: NodePath,
bindingPath: NodePath = path,
) {
if (!kind) throw new ReferenceError("no `kind`");
if (path.isVariableDeclaration()) {
@ -642,7 +712,7 @@ export default class Scope {
for (const name of Object.keys(ids)) {
parent.references[name] = true;
for (const id of (ids[name]: Array<Object>)) {
for (const id of ids[name]) {
const local = this.getOwnBinding(name);
if (local) {
@ -668,12 +738,13 @@ export default class Scope {
}
}
addGlobal(node: Object) {
// todo: flow->ts maybe add more specific type
addGlobal(node: Extract<t.Node, { name: string }>) {
this.globals[node.name] = node;
}
hasUid(name): boolean {
let scope = this;
hasUid(name: string): boolean {
let scope: Scope = this;
do {
if (scope.uids[name]) return true;
@ -683,7 +754,7 @@ export default class Scope {
}
hasGlobal(name: string): boolean {
let scope = this;
let scope: Scope = this;
do {
if (scope.globals[name]) return true;
@ -696,7 +767,7 @@ export default class Scope {
return !!this.getProgramParent().references[name];
}
isPure(node, constantsOnly?: boolean) {
isPure(node: t.Node, constantsOnly?: boolean) {
if (t.isIdentifier(node)) {
const binding = this.getBinding(node.name);
if (!binding) return false;
@ -718,12 +789,12 @@ export default class Scope {
this.isPure(node.right, constantsOnly)
);
} else if (t.isArrayExpression(node)) {
for (const elem of (node.elements: Array<Object>)) {
for (const elem of node.elements) {
if (!this.isPure(elem, constantsOnly)) return false;
}
return true;
} else if (t.isObjectExpression(node)) {
for (const prop of (node.properties: Array<Object>)) {
for (const prop of node.properties) {
if (!this.isPure(prop, constantsOnly)) return false;
}
return true;
@ -732,6 +803,7 @@ export default class Scope {
if (node.kind === "get" || node.kind === "set") return false;
return true;
} else if (t.isProperty(node)) {
// @ts-expect-error todo(flow->ts): computed in not present on private properties
if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
return this.isPure(node.value, constantsOnly);
} else if (t.isUnaryExpression(node)) {
@ -743,7 +815,7 @@ export default class Scope {
this.isPure(node.quasi, constantsOnly)
);
} else if (t.isTemplateLiteral(node)) {
for (const expression of (node.expressions: Array<Object>)) {
for (const expression of node.expressions) {
if (!this.isPure(expression, constantsOnly)) return false;
}
return true;
@ -756,7 +828,7 @@ export default class Scope {
* Set some arbitrary data on the current scope.
*/
setData(key, val) {
setData(key: string, val: any) {
return (this.data[key] = val);
}
@ -764,8 +836,8 @@ export default class Scope {
* Recursively walk up scope tree looking for the data `key`.
*/
getData(key) {
let scope = this;
getData(key: string): any {
let scope: Scope = this;
do {
const data = scope.data[key];
if (data != null) return data;
@ -777,8 +849,8 @@ export default class Scope {
* remove it.
*/
removeData(key) {
let scope = this;
removeData(key: string) {
let scope: Scope = this;
do {
const data = scope.data[key];
if (data != null) scope.data[key] = null;
@ -820,7 +892,7 @@ export default class Scope {
const programParent = this.getProgramParent();
if (programParent.crawling) return;
const state = {
const state: CollectVisitorState = {
references: [],
constantViolations: [],
assignments: [],
@ -860,11 +932,11 @@ export default class Scope {
}
push(opts: {
id: Object,
init: ?Object,
unique: ?boolean,
_blockHoist: ?number,
kind: "var" | "let",
id: t.LVal;
init?: t.Expression;
unique?: boolean;
_blockHoist?: number | undefined;
kind?: "var" | "let";
}) {
let path = this.path;
@ -878,6 +950,7 @@ export default class Scope {
if (path.isLoop() || path.isCatchClause() || path.isFunction()) {
path.ensureBlock();
// @ts-expect-error todo(flow->ts): improve types
path = path.get("body");
}
@ -890,6 +963,7 @@ export default class Scope {
if (!declarPath) {
const declar = t.variableDeclaration(kind, []);
// @ts-expect-error todo(flow->ts): avoid modifying nodes
declar._blockHoist = blockHoist;
[declarPath] = path.unshiftContainer("body", [declar]);
@ -906,7 +980,7 @@ export default class Scope {
*/
getProgramParent() {
let scope = this;
let scope: Scope = this;
do {
if (scope.path.isProgram()) {
return scope;
@ -919,8 +993,8 @@ export default class Scope {
* Walk up the scope tree until we hit either a Function or return null.
*/
getFunctionParent() {
let scope = this;
getFunctionParent(): Scope | null {
let scope: Scope = this;
do {
if (scope.path.isFunctionParent()) {
return scope;
@ -935,7 +1009,7 @@ export default class Scope {
*/
getBlockParent() {
let scope = this;
let scope: Scope = this;
do {
if (scope.path.isBlockParent()) {
return scope;
@ -950,10 +1024,10 @@ export default class Scope {
* Walks the scope tree and gathers **all** bindings.
*/
getAllBindings(): Object {
getAllBindings(): any {
const ids = Object.create(null);
let scope = this;
let scope: Scope = this;
do {
for (const key of Object.keys(scope.bindings)) {
if (key in ids === false) {
@ -970,11 +1044,11 @@ export default class Scope {
* Walks the scope tree and gathers all declarations of `kind`.
*/
getAllBindingsOfKind(): Object {
getAllBindingsOfKind(...kinds: string[]): any {
const ids = Object.create(null);
for (const kind of (arguments: Array)) {
let scope = this;
for (const kind of kinds) {
let scope: Scope = this;
do {
for (const name of Object.keys(scope.bindings)) {
const binding = scope.bindings[name];
@ -987,12 +1061,12 @@ export default class Scope {
return ids;
}
bindingIdentifierEquals(name: string, node: Object): boolean {
bindingIdentifierEquals(name: string, node: t.Node): boolean {
return this.getBindingIdentifier(name) === node;
}
getBinding(name: string) {
let scope = this;
getBinding(name: string): Binding | undefined {
let scope: Scope = this;
let previousPath;
do {
@ -1016,15 +1090,17 @@ export default class Scope {
} while ((scope = scope.parent));
}
getOwnBinding(name: string) {
getOwnBinding(name: string): Binding | undefined {
return this.bindings[name];
}
getBindingIdentifier(name: string) {
// todo: return probably can be undefined…
getBindingIdentifier(name: string): t.Identifier {
return this.getBinding(name)?.identifier;
}
getOwnBindingIdentifier(name: string) {
// todo: flow->ts return probably can be undefined
getOwnBindingIdentifier(name: string): t.Identifier {
const binding = this.bindings[name];
return binding?.identifier;
}
@ -1051,7 +1127,7 @@ export default class Scope {
* Move a binding of `name` to another `scope`.
*/
moveBindingTo(name, scope) {
moveBindingTo(name: string, scope: Scope) {
const info = this.getBinding(name);
if (info) {
info.scope.removeOwnBinding(name);
@ -1069,7 +1145,7 @@ export default class Scope {
this.getBinding(name)?.scope.removeOwnBinding(name);
// clear uids with this name - https://github.com/babel/babel/issues/2101
let scope = this;
let scope: Scope = this;
do {
if (scope.uids[name]) {
scope.uids[name] = false;

View File

@ -1,8 +1,9 @@
import Binding from "../binding";
import splitExportDeclaration from "@babel/helper-split-export-declaration";
import * as t from "@babel/types";
import type { Visitor } from "../../types";
const renameVisitor = {
const renameVisitor: Visitor<Renamer> = {
ReferencedIdentifier({ node }, state) {
if (node.name === state.oldName) {
node.name = state.newName;
@ -135,11 +136,6 @@ export default class Renamer {
this.binding.identifier.name = newName;
}
if (binding.type === "hoisted") {
// https://github.com/babel/babel/issues/2435
// todo: hoist and convert function to a let
}
if (parentDeclar) {
this.maybeConvertFromClassFunctionDeclaration(parentDeclar);
this.maybeConvertFromClassFunctionExpression(parentDeclar);

View File

@ -0,0 +1,31 @@
import * as t from "@babel/types";
import { NodePath } from "./index";
import { VirtualTypeAliases } from "./path/generated/virtual-types";
export type Visitor<S = {}> = VisitNodeObject<S, t.Node> &
{
[Type in t.Node["type"]]?: VisitNode<S, Extract<t.Node, { type: Type }>>;
} &
{
[K in keyof t.Aliases]?: VisitNode<S, t.Aliases[K]>;
} &
{
[K in keyof VirtualTypeAliases]?: VisitNode<S, VirtualTypeAliases[K]>;
} & {
[k: string]: VisitNode<S, t.Node>;
};
export type VisitNode<S, P extends t.Node> =
| VisitNodeFunction<S, P>
| VisitNodeObject<S, P>;
export type VisitNodeFunction<S, P extends t.Node> = (
this: S,
path: NodePath<P>,
state: S,
) => void;
export interface VisitNodeObject<S, P extends t.Node> {
enter?: VisitNodeFunction<S, P>;
exit?: VisitNodeFunction<S, P>;
}

View File

@ -50,7 +50,7 @@ export function explode(visitor) {
ensureCallbackArrays(visitor);
// add type wrappers
for (const nodeType of (Object.keys(visitor): Array)) {
for (const nodeType of Object.keys(visitor)) {
if (shouldIgnoreKey(nodeType)) continue;
const wrapper = virtualTypes[nodeType];
@ -66,7 +66,7 @@ export function explode(visitor) {
delete visitor[nodeType];
if (wrapper.types) {
for (const type of (wrapper.types: Array<string>)) {
for (const type of wrapper.types) {
// merge the visitor if necessary or just put it back in
if (visitor[type]) {
mergePair(visitor[type], fns);
@ -85,7 +85,7 @@ export function explode(visitor) {
const fns = visitor[nodeType];
let aliases: ?Array<string> = t.FLIPPED_ALIAS_KEYS[nodeType];
let aliases: Array<string> | undefined = t.FLIPPED_ALIAS_KEYS[nodeType];
const deprecratedKey = t.DEPRECATED_KEYS[nodeType];
if (deprecratedKey) {
@ -176,9 +176,9 @@ function validateVisitorMethods(path, val) {
}
export function merge(
visitors: Array,
states: Array = [],
wrapper?: ?Function,
visitors: any[],
states: any[] = [],
wrapper?: Function | null,
) {
const rootVisitor = {};
@ -204,7 +204,7 @@ export function merge(
return rootVisitor;
}
function wrapWithStateOrWrapper(oldVisitor, state, wrapper: ?Function) {
function wrapWithStateOrWrapper(oldVisitor, state, wrapper?: Function | null) {
const newVisitor = {};
for (const key of Object.keys(oldVisitor)) {

View File

@ -182,9 +182,9 @@ describe("modification", function () {
const tagName = path.node.openingElement.name.name;
if (tagName !== "span") return;
path.insertBefore(
t.JSXElement(
t.JSXOpeningElement(t.JSXIdentifier("div"), [], false),
t.JSXClosingElement(t.JSXIdentifier("div")),
t.jsxElement(
t.jsxOpeningElement(t.jsxIdentifier("div"), [], false),
t.jsxClosingElement(t.jsxIdentifier("div")),
[],
),
);
@ -292,9 +292,9 @@ describe("modification", function () {
const tagName = path.node.openingElement.name.name;
if (tagName !== "span") return;
path.insertAfter(
t.JSXElement(
t.JSXOpeningElement(t.JSXIdentifier("div"), [], false),
t.JSXClosingElement(t.JSXIdentifier("div")),
t.jsxElement(
t.jsxOpeningElement(t.jsxIdentifier("div"), [], false),
t.jsxClosingElement(t.jsxIdentifier("div")),
[],
),
);

View File

@ -40,9 +40,9 @@ export default function traverse<T>(
function traverseSimpleImpl<T>(
node: any,
enter: Function | undefined | null,
exit: Function | undefined | null,
state: T | undefined | null,
enter: Function | undefined,
exit: Function | undefined,
state: T | undefined,
ancestors: TraversalAncestors,
) {
const keys = VISITOR_KEYS[node.type];

View File

@ -14,10 +14,7 @@ export default function isType(
/**
* Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`.
*/
export default function isType(
nodeType: string | undefined | null,
targetType: string,
): boolean {
export default function isType(nodeType: string, targetType: string): boolean {
if (nodeType === targetType) return true;
// This is a fast-path. If the test above failed, but an alias key is found, then the