Refactor @babel/types to be 100% ES-module (#6741)

This generates the dynamic functions at buildtime and also
splits the package into smaller files to avoid dependency circles.
This commit is contained in:
Daniel Tschinder 2017-12-02 12:20:10 +01:00 committed by GitHub
parent 95fe785354
commit 8270903ba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 4689 additions and 1579 deletions

View File

@ -16,6 +16,9 @@ build: clean
# Build babylon before building all other projects
make build-babylon
./node_modules/.bin/gulp build
node ./packages/babel-types/scripts/generateTypeHelpers.js
# call build again as the generated files might need to be compiled again.
./node_modules/.bin/gulp build
ifneq ("$(BABEL_ENV)", "cov")
make build-standalone
make build-preset-env-standalone

View File

@ -0,0 +1,31 @@
"use strict";
const fs = require("fs");
const path = require("path");
const generateBuilders = require("./generators/generateBuilders");
const generateValidators = require("./generators/generateValidators");
const generateAsserts = require("./generators/generateAsserts");
const generateConstants = require("./generators/generateConstants");
const format = require("./utils/formatCode");
const baseDir = path.join(__dirname, "../src");
function writeFile(content, location) {
const file = path.join(baseDir, location);
try {
fs.mkdirSync(path.dirname(file));
} catch (error) {
if (error.code !== "EEXIST") {
throw error;
}
}
fs.writeFileSync(file, format(content, file));
}
console.log("Generating @babel/types dynamic functions");
writeFile(generateBuilders(), "builders/generated/index.js");
writeFile(generateValidators(), "validators/generated/index.js");
writeFile(generateAsserts(), "asserts/generated/index.js");
writeFile(generateConstants(), "constants/generated/index.js");

View File

@ -0,0 +1,43 @@
"use strict";
const definitions = require("../../lib/definitions");
function addAssertHelper(type) {
return `export function assert${type}(node: Object, opts?: Object = {}): void {
assert("${type}", node, opts) }
`;
}
module.exports = function generateAsserts() {
let output = `// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import is from "../../validators/is";
function assert(type: string, node: Object, opts?: Object): void {
if (!is(type, node, opts)) {
throw new Error(
\`Expected type "\${type}" with option \${JSON.stringify(opts)}\`,
);
}
}\n\n`;
Object.keys(definitions.VISITOR_KEYS).forEach(type => {
output += addAssertHelper(type);
});
Object.keys(definitions.FLIPPED_ALIAS_KEYS).forEach(type => {
output += addAssertHelper(type);
});
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const newType = definitions.DEPRECATED_KEYS[type];
output += `export function assert${type}(node: Object, opts: Object): void {
console.trace("The node type ${type} has been renamed to ${newType}");
assert("${type}", node, opts);
}\n`;
});
return output;
};

View File

@ -0,0 +1,28 @@
"use strict";
const definitions = require("../../lib/definitions");
const lowerFirst = require("../utils/lowerFirst");
module.exports = function generateBuilders() {
let output = `// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import builder from "../builder";\n\n`;
Object.keys(definitions.BUILDER_KEYS).forEach(type => {
output += `export function ${type}(...args: Array<any>): Object { return builder("${type}", ...args); }
export { ${type} as ${lowerFirst(type)} };\n`;
});
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const newType = definitions.DEPRECATED_KEYS[type];
output += `export function ${type}(...args: Array<any>): Object {
console.trace("The node type ${type} has been renamed to ${newType}");
return ${type}("${type}", ...args);
}
export { ${type} as ${lowerFirst(type)} };\n`;
});
return output;
};

View File

@ -0,0 +1,17 @@
"use strict";
const definitions = require("../../lib/definitions");
module.exports = function generateConstants() {
let output = `// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import { FLIPPED_ALIAS_KEYS } from "../../definitions";\n\n`;
Object.keys(definitions.FLIPPED_ALIAS_KEYS).forEach(type => {
output += `export const ${type.toUpperCase()}_TYPES = FLIPPED_ALIAS_KEYS["${type}"];\n`;
});
return output;
};

View File

@ -0,0 +1,35 @@
"use strict";
const definitions = require("../../lib/definitions");
function addIsHelper(type) {
return `export function is${type}(node: Object, opts?: Object): boolean {
return is("${type}", node, opts) }
`;
}
module.exports = function generateValidators() {
let output = `// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import is from "../is";\n\n`;
Object.keys(definitions.VISITOR_KEYS).forEach(type => {
output += addIsHelper(type);
});
Object.keys(definitions.FLIPPED_ALIAS_KEYS).forEach(type => {
output += addIsHelper(type);
});
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const newType = definitions.DEPRECATED_KEYS[type];
output += `export function is${type}(node: Object, opts: Object): boolean {
console.trace("The node type ${type} has been renamed to ${newType}");
return is("${type}", node, opts);
}\n`;
});
return output;
};

View File

@ -0,0 +1,9 @@
"use strict";
const prettier = require("prettier");
module.exports = function formatCode(code, filename) {
filename = filename || __filename;
const prettierConfig = prettier.resolveConfig.sync(filename);
return prettier.format(code, prettierConfig);
};

View File

@ -0,0 +1,4 @@
"use strict";
module.exports = function lowerFirst(string) {
return string[0].toLowerCase() + string.slice(1);
};

View File

@ -0,0 +1,9 @@
// @flow
import isNode from "../validators/isNode";
export default function assertNode(node?: Object): void {
if (!isNode(node)) {
const type = (node && node.type) || JSON.stringify(node);
throw new TypeError(`Not a valid node of type "${type}"`);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
// @flow
import loClone from "lodash/clone";
import { NODE_FIELDS, BUILDER_KEYS } from "../definitions";
import validate from "../validators/validate";
export default function builder(type: string, ...args: Array<any>): Object {
const keys = BUILDER_KEYS[type];
const countArgs = args.length;
if (countArgs > keys.length) {
throw new Error(
`${type}: Too many arguments passed. Received ${countArgs} but can receive no more than ${keys.length}`,
);
}
const node = { type };
let i = 0;
keys.forEach(key => {
const field = NODE_FIELDS[type][key];
let arg;
if (i < countArgs) arg = args[i];
if (arg === undefined) arg = loClone(field.default);
node[key] = arg;
i++;
});
for (const key in node) {
validate(node, key, node[key]);
}
return node;
}

View File

@ -0,0 +1,34 @@
// @flow
import {
stringTypeAnnotation,
numberTypeAnnotation,
voidTypeAnnotation,
booleanTypeAnnotation,
genericTypeAnnotation,
identifier,
} from "../generated";
/**
* Create a type annotation based on typeof expression.
*/
export default function createTypeAnnotationBasedOnTypeof(
type: string,
): Object {
if (type === "string") {
return stringTypeAnnotation();
} else if (type === "number") {
return numberTypeAnnotation();
} else if (type === "undefined") {
return voidTypeAnnotation();
} else if (type === "boolean") {
return booleanTypeAnnotation();
} else if (type === "function") {
return genericTypeAnnotation(identifier("Function"));
} else if (type === "object") {
return genericTypeAnnotation(identifier("Object"));
} else if (type === "symbol") {
return genericTypeAnnotation(identifier("Symbol"));
} else {
throw new Error("Invalid typeof value");
}
}

View File

@ -0,0 +1,19 @@
// @flow
import { unionTypeAnnotation } from "../generated";
import removeTypeDuplicates from "../../modifications/flow/removeTypeDuplicates";
/**
* Takes an array of `types` and flattens them, removing duplicates and
* returns a `UnionTypeAnnotation` node containg them.
*/
export default function createUnionTypeAnnotation(
types: Array<Object>,
): Object {
const flattened = removeTypeDuplicates(types);
if (flattened.length === 1) {
return flattened[0];
} else {
return unionTypeAnnotation(flattened);
}
}

View File

@ -0,0 +1,839 @@
// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import builder from "../builder";
export function ArrayExpression(...args: Array<any>): Object {
return builder("ArrayExpression", ...args);
}
export { ArrayExpression as arrayExpression };
export function AssignmentExpression(...args: Array<any>): Object {
return builder("AssignmentExpression", ...args);
}
export { AssignmentExpression as assignmentExpression };
export function BinaryExpression(...args: Array<any>): Object {
return builder("BinaryExpression", ...args);
}
export { BinaryExpression as binaryExpression };
export function Directive(...args: Array<any>): Object {
return builder("Directive", ...args);
}
export { Directive as directive };
export function DirectiveLiteral(...args: Array<any>): Object {
return builder("DirectiveLiteral", ...args);
}
export { DirectiveLiteral as directiveLiteral };
export function BlockStatement(...args: Array<any>): Object {
return builder("BlockStatement", ...args);
}
export { BlockStatement as blockStatement };
export function BreakStatement(...args: Array<any>): Object {
return builder("BreakStatement", ...args);
}
export { BreakStatement as breakStatement };
export function CallExpression(...args: Array<any>): Object {
return builder("CallExpression", ...args);
}
export { CallExpression as callExpression };
export function CatchClause(...args: Array<any>): Object {
return builder("CatchClause", ...args);
}
export { CatchClause as catchClause };
export function ConditionalExpression(...args: Array<any>): Object {
return builder("ConditionalExpression", ...args);
}
export { ConditionalExpression as conditionalExpression };
export function ContinueStatement(...args: Array<any>): Object {
return builder("ContinueStatement", ...args);
}
export { ContinueStatement as continueStatement };
export function DebuggerStatement(...args: Array<any>): Object {
return builder("DebuggerStatement", ...args);
}
export { DebuggerStatement as debuggerStatement };
export function DoWhileStatement(...args: Array<any>): Object {
return builder("DoWhileStatement", ...args);
}
export { DoWhileStatement as doWhileStatement };
export function EmptyStatement(...args: Array<any>): Object {
return builder("EmptyStatement", ...args);
}
export { EmptyStatement as emptyStatement };
export function ExpressionStatement(...args: Array<any>): Object {
return builder("ExpressionStatement", ...args);
}
export { ExpressionStatement as expressionStatement };
export function File(...args: Array<any>): Object {
return builder("File", ...args);
}
export { File as file };
export function ForInStatement(...args: Array<any>): Object {
return builder("ForInStatement", ...args);
}
export { ForInStatement as forInStatement };
export function ForStatement(...args: Array<any>): Object {
return builder("ForStatement", ...args);
}
export { ForStatement as forStatement };
export function FunctionDeclaration(...args: Array<any>): Object {
return builder("FunctionDeclaration", ...args);
}
export { FunctionDeclaration as functionDeclaration };
export function FunctionExpression(...args: Array<any>): Object {
return builder("FunctionExpression", ...args);
}
export { FunctionExpression as functionExpression };
export function Identifier(...args: Array<any>): Object {
return builder("Identifier", ...args);
}
export { Identifier as identifier };
export function IfStatement(...args: Array<any>): Object {
return builder("IfStatement", ...args);
}
export { IfStatement as ifStatement };
export function LabeledStatement(...args: Array<any>): Object {
return builder("LabeledStatement", ...args);
}
export { LabeledStatement as labeledStatement };
export function StringLiteral(...args: Array<any>): Object {
return builder("StringLiteral", ...args);
}
export { StringLiteral as stringLiteral };
export function NumericLiteral(...args: Array<any>): Object {
return builder("NumericLiteral", ...args);
}
export { NumericLiteral as numericLiteral };
export function NullLiteral(...args: Array<any>): Object {
return builder("NullLiteral", ...args);
}
export { NullLiteral as nullLiteral };
export function BooleanLiteral(...args: Array<any>): Object {
return builder("BooleanLiteral", ...args);
}
export { BooleanLiteral as booleanLiteral };
export function RegExpLiteral(...args: Array<any>): Object {
return builder("RegExpLiteral", ...args);
}
export { RegExpLiteral as regExpLiteral };
export function LogicalExpression(...args: Array<any>): Object {
return builder("LogicalExpression", ...args);
}
export { LogicalExpression as logicalExpression };
export function MemberExpression(...args: Array<any>): Object {
return builder("MemberExpression", ...args);
}
export { MemberExpression as memberExpression };
export function NewExpression(...args: Array<any>): Object {
return builder("NewExpression", ...args);
}
export { NewExpression as newExpression };
export function Program(...args: Array<any>): Object {
return builder("Program", ...args);
}
export { Program as program };
export function ObjectExpression(...args: Array<any>): Object {
return builder("ObjectExpression", ...args);
}
export { ObjectExpression as objectExpression };
export function ObjectMethod(...args: Array<any>): Object {
return builder("ObjectMethod", ...args);
}
export { ObjectMethod as objectMethod };
export function ObjectProperty(...args: Array<any>): Object {
return builder("ObjectProperty", ...args);
}
export { ObjectProperty as objectProperty };
export function RestElement(...args: Array<any>): Object {
return builder("RestElement", ...args);
}
export { RestElement as restElement };
export function ReturnStatement(...args: Array<any>): Object {
return builder("ReturnStatement", ...args);
}
export { ReturnStatement as returnStatement };
export function SequenceExpression(...args: Array<any>): Object {
return builder("SequenceExpression", ...args);
}
export { SequenceExpression as sequenceExpression };
export function SwitchCase(...args: Array<any>): Object {
return builder("SwitchCase", ...args);
}
export { SwitchCase as switchCase };
export function SwitchStatement(...args: Array<any>): Object {
return builder("SwitchStatement", ...args);
}
export { SwitchStatement as switchStatement };
export function ThisExpression(...args: Array<any>): Object {
return builder("ThisExpression", ...args);
}
export { ThisExpression as thisExpression };
export function ThrowStatement(...args: Array<any>): Object {
return builder("ThrowStatement", ...args);
}
export { ThrowStatement as throwStatement };
export function TryStatement(...args: Array<any>): Object {
return builder("TryStatement", ...args);
}
export { TryStatement as tryStatement };
export function UnaryExpression(...args: Array<any>): Object {
return builder("UnaryExpression", ...args);
}
export { UnaryExpression as unaryExpression };
export function UpdateExpression(...args: Array<any>): Object {
return builder("UpdateExpression", ...args);
}
export { UpdateExpression as updateExpression };
export function VariableDeclaration(...args: Array<any>): Object {
return builder("VariableDeclaration", ...args);
}
export { VariableDeclaration as variableDeclaration };
export function VariableDeclarator(...args: Array<any>): Object {
return builder("VariableDeclarator", ...args);
}
export { VariableDeclarator as variableDeclarator };
export function WhileStatement(...args: Array<any>): Object {
return builder("WhileStatement", ...args);
}
export { WhileStatement as whileStatement };
export function WithStatement(...args: Array<any>): Object {
return builder("WithStatement", ...args);
}
export { WithStatement as withStatement };
export function AssignmentPattern(...args: Array<any>): Object {
return builder("AssignmentPattern", ...args);
}
export { AssignmentPattern as assignmentPattern };
export function ArrayPattern(...args: Array<any>): Object {
return builder("ArrayPattern", ...args);
}
export { ArrayPattern as arrayPattern };
export function ArrowFunctionExpression(...args: Array<any>): Object {
return builder("ArrowFunctionExpression", ...args);
}
export { ArrowFunctionExpression as arrowFunctionExpression };
export function ClassBody(...args: Array<any>): Object {
return builder("ClassBody", ...args);
}
export { ClassBody as classBody };
export function ClassDeclaration(...args: Array<any>): Object {
return builder("ClassDeclaration", ...args);
}
export { ClassDeclaration as classDeclaration };
export function ClassExpression(...args: Array<any>): Object {
return builder("ClassExpression", ...args);
}
export { ClassExpression as classExpression };
export function ExportAllDeclaration(...args: Array<any>): Object {
return builder("ExportAllDeclaration", ...args);
}
export { ExportAllDeclaration as exportAllDeclaration };
export function ExportDefaultDeclaration(...args: Array<any>): Object {
return builder("ExportDefaultDeclaration", ...args);
}
export { ExportDefaultDeclaration as exportDefaultDeclaration };
export function ExportNamedDeclaration(...args: Array<any>): Object {
return builder("ExportNamedDeclaration", ...args);
}
export { ExportNamedDeclaration as exportNamedDeclaration };
export function ExportSpecifier(...args: Array<any>): Object {
return builder("ExportSpecifier", ...args);
}
export { ExportSpecifier as exportSpecifier };
export function ForOfStatement(...args: Array<any>): Object {
return builder("ForOfStatement", ...args);
}
export { ForOfStatement as forOfStatement };
export function ImportDeclaration(...args: Array<any>): Object {
return builder("ImportDeclaration", ...args);
}
export { ImportDeclaration as importDeclaration };
export function ImportDefaultSpecifier(...args: Array<any>): Object {
return builder("ImportDefaultSpecifier", ...args);
}
export { ImportDefaultSpecifier as importDefaultSpecifier };
export function ImportNamespaceSpecifier(...args: Array<any>): Object {
return builder("ImportNamespaceSpecifier", ...args);
}
export { ImportNamespaceSpecifier as importNamespaceSpecifier };
export function ImportSpecifier(...args: Array<any>): Object {
return builder("ImportSpecifier", ...args);
}
export { ImportSpecifier as importSpecifier };
export function MetaProperty(...args: Array<any>): Object {
return builder("MetaProperty", ...args);
}
export { MetaProperty as metaProperty };
export function ClassMethod(...args: Array<any>): Object {
return builder("ClassMethod", ...args);
}
export { ClassMethod as classMethod };
export function ObjectPattern(...args: Array<any>): Object {
return builder("ObjectPattern", ...args);
}
export { ObjectPattern as objectPattern };
export function SpreadElement(...args: Array<any>): Object {
return builder("SpreadElement", ...args);
}
export { SpreadElement as spreadElement };
export function Super(...args: Array<any>): Object {
return builder("Super", ...args);
}
export { Super as super };
export function TaggedTemplateExpression(...args: Array<any>): Object {
return builder("TaggedTemplateExpression", ...args);
}
export { TaggedTemplateExpression as taggedTemplateExpression };
export function TemplateElement(...args: Array<any>): Object {
return builder("TemplateElement", ...args);
}
export { TemplateElement as templateElement };
export function TemplateLiteral(...args: Array<any>): Object {
return builder("TemplateLiteral", ...args);
}
export { TemplateLiteral as templateLiteral };
export function YieldExpression(...args: Array<any>): Object {
return builder("YieldExpression", ...args);
}
export { YieldExpression as yieldExpression };
export function AnyTypeAnnotation(...args: Array<any>): Object {
return builder("AnyTypeAnnotation", ...args);
}
export { AnyTypeAnnotation as anyTypeAnnotation };
export function ArrayTypeAnnotation(...args: Array<any>): Object {
return builder("ArrayTypeAnnotation", ...args);
}
export { ArrayTypeAnnotation as arrayTypeAnnotation };
export function BooleanTypeAnnotation(...args: Array<any>): Object {
return builder("BooleanTypeAnnotation", ...args);
}
export { BooleanTypeAnnotation as booleanTypeAnnotation };
export function BooleanLiteralTypeAnnotation(...args: Array<any>): Object {
return builder("BooleanLiteralTypeAnnotation", ...args);
}
export { BooleanLiteralTypeAnnotation as booleanLiteralTypeAnnotation };
export function NullLiteralTypeAnnotation(...args: Array<any>): Object {
return builder("NullLiteralTypeAnnotation", ...args);
}
export { NullLiteralTypeAnnotation as nullLiteralTypeAnnotation };
export function ClassImplements(...args: Array<any>): Object {
return builder("ClassImplements", ...args);
}
export { ClassImplements as classImplements };
export function DeclareClass(...args: Array<any>): Object {
return builder("DeclareClass", ...args);
}
export { DeclareClass as declareClass };
export function DeclareFunction(...args: Array<any>): Object {
return builder("DeclareFunction", ...args);
}
export { DeclareFunction as declareFunction };
export function DeclareInterface(...args: Array<any>): Object {
return builder("DeclareInterface", ...args);
}
export { DeclareInterface as declareInterface };
export function DeclareModule(...args: Array<any>): Object {
return builder("DeclareModule", ...args);
}
export { DeclareModule as declareModule };
export function DeclareModuleExports(...args: Array<any>): Object {
return builder("DeclareModuleExports", ...args);
}
export { DeclareModuleExports as declareModuleExports };
export function DeclareTypeAlias(...args: Array<any>): Object {
return builder("DeclareTypeAlias", ...args);
}
export { DeclareTypeAlias as declareTypeAlias };
export function DeclareOpaqueType(...args: Array<any>): Object {
return builder("DeclareOpaqueType", ...args);
}
export { DeclareOpaqueType as declareOpaqueType };
export function DeclareVariable(...args: Array<any>): Object {
return builder("DeclareVariable", ...args);
}
export { DeclareVariable as declareVariable };
export function DeclareExportDeclaration(...args: Array<any>): Object {
return builder("DeclareExportDeclaration", ...args);
}
export { DeclareExportDeclaration as declareExportDeclaration };
export function DeclareExportAllDeclaration(...args: Array<any>): Object {
return builder("DeclareExportAllDeclaration", ...args);
}
export { DeclareExportAllDeclaration as declareExportAllDeclaration };
export function DeclaredPredicate(...args: Array<any>): Object {
return builder("DeclaredPredicate", ...args);
}
export { DeclaredPredicate as declaredPredicate };
export function ExistsTypeAnnotation(...args: Array<any>): Object {
return builder("ExistsTypeAnnotation", ...args);
}
export { ExistsTypeAnnotation as existsTypeAnnotation };
export function FunctionTypeAnnotation(...args: Array<any>): Object {
return builder("FunctionTypeAnnotation", ...args);
}
export { FunctionTypeAnnotation as functionTypeAnnotation };
export function FunctionTypeParam(...args: Array<any>): Object {
return builder("FunctionTypeParam", ...args);
}
export { FunctionTypeParam as functionTypeParam };
export function GenericTypeAnnotation(...args: Array<any>): Object {
return builder("GenericTypeAnnotation", ...args);
}
export { GenericTypeAnnotation as genericTypeAnnotation };
export function InferredPredicate(...args: Array<any>): Object {
return builder("InferredPredicate", ...args);
}
export { InferredPredicate as inferredPredicate };
export function InterfaceExtends(...args: Array<any>): Object {
return builder("InterfaceExtends", ...args);
}
export { InterfaceExtends as interfaceExtends };
export function InterfaceDeclaration(...args: Array<any>): Object {
return builder("InterfaceDeclaration", ...args);
}
export { InterfaceDeclaration as interfaceDeclaration };
export function IntersectionTypeAnnotation(...args: Array<any>): Object {
return builder("IntersectionTypeAnnotation", ...args);
}
export { IntersectionTypeAnnotation as intersectionTypeAnnotation };
export function MixedTypeAnnotation(...args: Array<any>): Object {
return builder("MixedTypeAnnotation", ...args);
}
export { MixedTypeAnnotation as mixedTypeAnnotation };
export function EmptyTypeAnnotation(...args: Array<any>): Object {
return builder("EmptyTypeAnnotation", ...args);
}
export { EmptyTypeAnnotation as emptyTypeAnnotation };
export function NullableTypeAnnotation(...args: Array<any>): Object {
return builder("NullableTypeAnnotation", ...args);
}
export { NullableTypeAnnotation as nullableTypeAnnotation };
export function NumberLiteralTypeAnnotation(...args: Array<any>): Object {
return builder("NumberLiteralTypeAnnotation", ...args);
}
export { NumberLiteralTypeAnnotation as numberLiteralTypeAnnotation };
export function NumberTypeAnnotation(...args: Array<any>): Object {
return builder("NumberTypeAnnotation", ...args);
}
export { NumberTypeAnnotation as numberTypeAnnotation };
export function ObjectTypeAnnotation(...args: Array<any>): Object {
return builder("ObjectTypeAnnotation", ...args);
}
export { ObjectTypeAnnotation as objectTypeAnnotation };
export function ObjectTypeCallProperty(...args: Array<any>): Object {
return builder("ObjectTypeCallProperty", ...args);
}
export { ObjectTypeCallProperty as objectTypeCallProperty };
export function ObjectTypeIndexer(...args: Array<any>): Object {
return builder("ObjectTypeIndexer", ...args);
}
export { ObjectTypeIndexer as objectTypeIndexer };
export function ObjectTypeProperty(...args: Array<any>): Object {
return builder("ObjectTypeProperty", ...args);
}
export { ObjectTypeProperty as objectTypeProperty };
export function ObjectTypeSpreadProperty(...args: Array<any>): Object {
return builder("ObjectTypeSpreadProperty", ...args);
}
export { ObjectTypeSpreadProperty as objectTypeSpreadProperty };
export function OpaqueType(...args: Array<any>): Object {
return builder("OpaqueType", ...args);
}
export { OpaqueType as opaqueType };
export function QualifiedTypeIdentifier(...args: Array<any>): Object {
return builder("QualifiedTypeIdentifier", ...args);
}
export { QualifiedTypeIdentifier as qualifiedTypeIdentifier };
export function StringLiteralTypeAnnotation(...args: Array<any>): Object {
return builder("StringLiteralTypeAnnotation", ...args);
}
export { StringLiteralTypeAnnotation as stringLiteralTypeAnnotation };
export function StringTypeAnnotation(...args: Array<any>): Object {
return builder("StringTypeAnnotation", ...args);
}
export { StringTypeAnnotation as stringTypeAnnotation };
export function ThisTypeAnnotation(...args: Array<any>): Object {
return builder("ThisTypeAnnotation", ...args);
}
export { ThisTypeAnnotation as thisTypeAnnotation };
export function TupleTypeAnnotation(...args: Array<any>): Object {
return builder("TupleTypeAnnotation", ...args);
}
export { TupleTypeAnnotation as tupleTypeAnnotation };
export function TypeofTypeAnnotation(...args: Array<any>): Object {
return builder("TypeofTypeAnnotation", ...args);
}
export { TypeofTypeAnnotation as typeofTypeAnnotation };
export function TypeAlias(...args: Array<any>): Object {
return builder("TypeAlias", ...args);
}
export { TypeAlias as typeAlias };
export function TypeAnnotation(...args: Array<any>): Object {
return builder("TypeAnnotation", ...args);
}
export { TypeAnnotation as typeAnnotation };
export function TypeCastExpression(...args: Array<any>): Object {
return builder("TypeCastExpression", ...args);
}
export { TypeCastExpression as typeCastExpression };
export function TypeParameter(...args: Array<any>): Object {
return builder("TypeParameter", ...args);
}
export { TypeParameter as typeParameter };
export function TypeParameterDeclaration(...args: Array<any>): Object {
return builder("TypeParameterDeclaration", ...args);
}
export { TypeParameterDeclaration as typeParameterDeclaration };
export function TypeParameterInstantiation(...args: Array<any>): Object {
return builder("TypeParameterInstantiation", ...args);
}
export { TypeParameterInstantiation as typeParameterInstantiation };
export function UnionTypeAnnotation(...args: Array<any>): Object {
return builder("UnionTypeAnnotation", ...args);
}
export { UnionTypeAnnotation as unionTypeAnnotation };
export function VoidTypeAnnotation(...args: Array<any>): Object {
return builder("VoidTypeAnnotation", ...args);
}
export { VoidTypeAnnotation as voidTypeAnnotation };
export function JSXAttribute(...args: Array<any>): Object {
return builder("JSXAttribute", ...args);
}
export { JSXAttribute as jSXAttribute };
export function JSXClosingElement(...args: Array<any>): Object {
return builder("JSXClosingElement", ...args);
}
export { JSXClosingElement as jSXClosingElement };
export function JSXElement(...args: Array<any>): Object {
return builder("JSXElement", ...args);
}
export { JSXElement as jSXElement };
export function JSXEmptyExpression(...args: Array<any>): Object {
return builder("JSXEmptyExpression", ...args);
}
export { JSXEmptyExpression as jSXEmptyExpression };
export function JSXExpressionContainer(...args: Array<any>): Object {
return builder("JSXExpressionContainer", ...args);
}
export { JSXExpressionContainer as jSXExpressionContainer };
export function JSXSpreadChild(...args: Array<any>): Object {
return builder("JSXSpreadChild", ...args);
}
export { JSXSpreadChild as jSXSpreadChild };
export function JSXIdentifier(...args: Array<any>): Object {
return builder("JSXIdentifier", ...args);
}
export { JSXIdentifier as jSXIdentifier };
export function JSXMemberExpression(...args: Array<any>): Object {
return builder("JSXMemberExpression", ...args);
}
export { JSXMemberExpression as jSXMemberExpression };
export function JSXNamespacedName(...args: Array<any>): Object {
return builder("JSXNamespacedName", ...args);
}
export { JSXNamespacedName as jSXNamespacedName };
export function JSXOpeningElement(...args: Array<any>): Object {
return builder("JSXOpeningElement", ...args);
}
export { JSXOpeningElement as jSXOpeningElement };
export function JSXSpreadAttribute(...args: Array<any>): Object {
return builder("JSXSpreadAttribute", ...args);
}
export { JSXSpreadAttribute as jSXSpreadAttribute };
export function JSXText(...args: Array<any>): Object {
return builder("JSXText", ...args);
}
export { JSXText as jSXText };
export function JSXFragment(...args: Array<any>): Object {
return builder("JSXFragment", ...args);
}
export { JSXFragment as jSXFragment };
export function JSXOpeningFragment(...args: Array<any>): Object {
return builder("JSXOpeningFragment", ...args);
}
export { JSXOpeningFragment as jSXOpeningFragment };
export function JSXClosingFragment(...args: Array<any>): Object {
return builder("JSXClosingFragment", ...args);
}
export { JSXClosingFragment as jSXClosingFragment };
export function Noop(...args: Array<any>): Object {
return builder("Noop", ...args);
}
export { Noop as noop };
export function ParenthesizedExpression(...args: Array<any>): Object {
return builder("ParenthesizedExpression", ...args);
}
export { ParenthesizedExpression as parenthesizedExpression };
export function AwaitExpression(...args: Array<any>): Object {
return builder("AwaitExpression", ...args);
}
export { AwaitExpression as awaitExpression };
export function BindExpression(...args: Array<any>): Object {
return builder("BindExpression", ...args);
}
export { BindExpression as bindExpression };
export function ClassProperty(...args: Array<any>): Object {
return builder("ClassProperty", ...args);
}
export { ClassProperty as classProperty };
export function Import(...args: Array<any>): Object {
return builder("Import", ...args);
}
export { Import as import };
export function Decorator(...args: Array<any>): Object {
return builder("Decorator", ...args);
}
export { Decorator as decorator };
export function DoExpression(...args: Array<any>): Object {
return builder("DoExpression", ...args);
}
export { DoExpression as doExpression };
export function ExportDefaultSpecifier(...args: Array<any>): Object {
return builder("ExportDefaultSpecifier", ...args);
}
export { ExportDefaultSpecifier as exportDefaultSpecifier };
export function ExportNamespaceSpecifier(...args: Array<any>): Object {
return builder("ExportNamespaceSpecifier", ...args);
}
export { ExportNamespaceSpecifier as exportNamespaceSpecifier };
export function TSParameterProperty(...args: Array<any>): Object {
return builder("TSParameterProperty", ...args);
}
export { TSParameterProperty as tSParameterProperty };
export function TSDeclareFunction(...args: Array<any>): Object {
return builder("TSDeclareFunction", ...args);
}
export { TSDeclareFunction as tSDeclareFunction };
export function TSDeclareMethod(...args: Array<any>): Object {
return builder("TSDeclareMethod", ...args);
}
export { TSDeclareMethod as tSDeclareMethod };
export function TSQualifiedName(...args: Array<any>): Object {
return builder("TSQualifiedName", ...args);
}
export { TSQualifiedName as tSQualifiedName };
export function TSCallSignatureDeclaration(...args: Array<any>): Object {
return builder("TSCallSignatureDeclaration", ...args);
}
export { TSCallSignatureDeclaration as tSCallSignatureDeclaration };
export function TSConstructSignatureDeclaration(...args: Array<any>): Object {
return builder("TSConstructSignatureDeclaration", ...args);
}
export { TSConstructSignatureDeclaration as tSConstructSignatureDeclaration };
export function TSPropertySignature(...args: Array<any>): Object {
return builder("TSPropertySignature", ...args);
}
export { TSPropertySignature as tSPropertySignature };
export function TSMethodSignature(...args: Array<any>): Object {
return builder("TSMethodSignature", ...args);
}
export { TSMethodSignature as tSMethodSignature };
export function TSIndexSignature(...args: Array<any>): Object {
return builder("TSIndexSignature", ...args);
}
export { TSIndexSignature as tSIndexSignature };
export function TSAnyKeyword(...args: Array<any>): Object {
return builder("TSAnyKeyword", ...args);
}
export { TSAnyKeyword as tSAnyKeyword };
export function TSNumberKeyword(...args: Array<any>): Object {
return builder("TSNumberKeyword", ...args);
}
export { TSNumberKeyword as tSNumberKeyword };
export function TSObjectKeyword(...args: Array<any>): Object {
return builder("TSObjectKeyword", ...args);
}
export { TSObjectKeyword as tSObjectKeyword };
export function TSBooleanKeyword(...args: Array<any>): Object {
return builder("TSBooleanKeyword", ...args);
}
export { TSBooleanKeyword as tSBooleanKeyword };
export function TSStringKeyword(...args: Array<any>): Object {
return builder("TSStringKeyword", ...args);
}
export { TSStringKeyword as tSStringKeyword };
export function TSSymbolKeyword(...args: Array<any>): Object {
return builder("TSSymbolKeyword", ...args);
}
export { TSSymbolKeyword as tSSymbolKeyword };
export function TSVoidKeyword(...args: Array<any>): Object {
return builder("TSVoidKeyword", ...args);
}
export { TSVoidKeyword as tSVoidKeyword };
export function TSUndefinedKeyword(...args: Array<any>): Object {
return builder("TSUndefinedKeyword", ...args);
}
export { TSUndefinedKeyword as tSUndefinedKeyword };
export function TSNullKeyword(...args: Array<any>): Object {
return builder("TSNullKeyword", ...args);
}
export { TSNullKeyword as tSNullKeyword };
export function TSNeverKeyword(...args: Array<any>): Object {
return builder("TSNeverKeyword", ...args);
}
export { TSNeverKeyword as tSNeverKeyword };
export function TSThisType(...args: Array<any>): Object {
return builder("TSThisType", ...args);
}
export { TSThisType as tSThisType };
export function TSFunctionType(...args: Array<any>): Object {
return builder("TSFunctionType", ...args);
}
export { TSFunctionType as tSFunctionType };
export function TSConstructorType(...args: Array<any>): Object {
return builder("TSConstructorType", ...args);
}
export { TSConstructorType as tSConstructorType };
export function TSTypeReference(...args: Array<any>): Object {
return builder("TSTypeReference", ...args);
}
export { TSTypeReference as tSTypeReference };
export function TSTypePredicate(...args: Array<any>): Object {
return builder("TSTypePredicate", ...args);
}
export { TSTypePredicate as tSTypePredicate };
export function TSTypeQuery(...args: Array<any>): Object {
return builder("TSTypeQuery", ...args);
}
export { TSTypeQuery as tSTypeQuery };
export function TSTypeLiteral(...args: Array<any>): Object {
return builder("TSTypeLiteral", ...args);
}
export { TSTypeLiteral as tSTypeLiteral };
export function TSArrayType(...args: Array<any>): Object {
return builder("TSArrayType", ...args);
}
export { TSArrayType as tSArrayType };
export function TSTupleType(...args: Array<any>): Object {
return builder("TSTupleType", ...args);
}
export { TSTupleType as tSTupleType };
export function TSUnionType(...args: Array<any>): Object {
return builder("TSUnionType", ...args);
}
export { TSUnionType as tSUnionType };
export function TSIntersectionType(...args: Array<any>): Object {
return builder("TSIntersectionType", ...args);
}
export { TSIntersectionType as tSIntersectionType };
export function TSParenthesizedType(...args: Array<any>): Object {
return builder("TSParenthesizedType", ...args);
}
export { TSParenthesizedType as tSParenthesizedType };
export function TSTypeOperator(...args: Array<any>): Object {
return builder("TSTypeOperator", ...args);
}
export { TSTypeOperator as tSTypeOperator };
export function TSIndexedAccessType(...args: Array<any>): Object {
return builder("TSIndexedAccessType", ...args);
}
export { TSIndexedAccessType as tSIndexedAccessType };
export function TSMappedType(...args: Array<any>): Object {
return builder("TSMappedType", ...args);
}
export { TSMappedType as tSMappedType };
export function TSLiteralType(...args: Array<any>): Object {
return builder("TSLiteralType", ...args);
}
export { TSLiteralType as tSLiteralType };
export function TSExpressionWithTypeArguments(...args: Array<any>): Object {
return builder("TSExpressionWithTypeArguments", ...args);
}
export { TSExpressionWithTypeArguments as tSExpressionWithTypeArguments };
export function TSInterfaceDeclaration(...args: Array<any>): Object {
return builder("TSInterfaceDeclaration", ...args);
}
export { TSInterfaceDeclaration as tSInterfaceDeclaration };
export function TSInterfaceBody(...args: Array<any>): Object {
return builder("TSInterfaceBody", ...args);
}
export { TSInterfaceBody as tSInterfaceBody };
export function TSTypeAliasDeclaration(...args: Array<any>): Object {
return builder("TSTypeAliasDeclaration", ...args);
}
export { TSTypeAliasDeclaration as tSTypeAliasDeclaration };
export function TSAsExpression(...args: Array<any>): Object {
return builder("TSAsExpression", ...args);
}
export { TSAsExpression as tSAsExpression };
export function TSTypeAssertion(...args: Array<any>): Object {
return builder("TSTypeAssertion", ...args);
}
export { TSTypeAssertion as tSTypeAssertion };
export function TSEnumDeclaration(...args: Array<any>): Object {
return builder("TSEnumDeclaration", ...args);
}
export { TSEnumDeclaration as tSEnumDeclaration };
export function TSEnumMember(...args: Array<any>): Object {
return builder("TSEnumMember", ...args);
}
export { TSEnumMember as tSEnumMember };
export function TSModuleDeclaration(...args: Array<any>): Object {
return builder("TSModuleDeclaration", ...args);
}
export { TSModuleDeclaration as tSModuleDeclaration };
export function TSModuleBlock(...args: Array<any>): Object {
return builder("TSModuleBlock", ...args);
}
export { TSModuleBlock as tSModuleBlock };
export function TSImportEqualsDeclaration(...args: Array<any>): Object {
return builder("TSImportEqualsDeclaration", ...args);
}
export { TSImportEqualsDeclaration as tSImportEqualsDeclaration };
export function TSExternalModuleReference(...args: Array<any>): Object {
return builder("TSExternalModuleReference", ...args);
}
export { TSExternalModuleReference as tSExternalModuleReference };
export function TSNonNullExpression(...args: Array<any>): Object {
return builder("TSNonNullExpression", ...args);
}
export { TSNonNullExpression as tSNonNullExpression };
export function TSExportAssignment(...args: Array<any>): Object {
return builder("TSExportAssignment", ...args);
}
export { TSExportAssignment as tSExportAssignment };
export function TSNamespaceExportDeclaration(...args: Array<any>): Object {
return builder("TSNamespaceExportDeclaration", ...args);
}
export { TSNamespaceExportDeclaration as tSNamespaceExportDeclaration };
export function TSTypeAnnotation(...args: Array<any>): Object {
return builder("TSTypeAnnotation", ...args);
}
export { TSTypeAnnotation as tSTypeAnnotation };
export function TSTypeParameterInstantiation(...args: Array<any>): Object {
return builder("TSTypeParameterInstantiation", ...args);
}
export { TSTypeParameterInstantiation as tSTypeParameterInstantiation };
export function TSTypeParameterDeclaration(...args: Array<any>): Object {
return builder("TSTypeParameterDeclaration", ...args);
}
export { TSTypeParameterDeclaration as tSTypeParameterDeclaration };
export function TSTypeParameter(...args: Array<any>): Object {
return builder("TSTypeParameter", ...args);
}
export { TSTypeParameter as tSTypeParameter };
export function NumberLiteral(...args: Array<any>): Object {
console.trace(
"The node type NumberLiteral has been renamed to NumericLiteral",
);
return NumberLiteral("NumberLiteral", ...args);
}
export { NumberLiteral as numberLiteral };
export function RegexLiteral(...args: Array<any>): Object {
console.trace("The node type RegexLiteral has been renamed to RegExpLiteral");
return RegexLiteral("RegexLiteral", ...args);
}
export { RegexLiteral as regexLiteral };
export function RestProperty(...args: Array<any>): Object {
console.trace("The node type RestProperty has been renamed to RestElement");
return RestProperty("RestProperty", ...args);
}
export { RestProperty as restProperty };
export function SpreadProperty(...args: Array<any>): Object {
console.trace(
"The node type SpreadProperty has been renamed to SpreadElement",
);
return SpreadProperty("SpreadProperty", ...args);
}
export { SpreadProperty as spreadProperty };

View File

@ -0,0 +1,27 @@
// @flow
import {
isJSXText,
isJSXExpressionContainer,
isJSXEmptyExpression,
} from "../../validators/generated";
import cleanJSXElementLiteralChild from "../../utils/react/cleanJSXElementLiteralChild";
export default function buildChildren(node: Object): Array<Object> {
const elements = [];
for (let i = 0; i < node.children.length; i++) {
let child = node.children[i];
if (isJSXText(child)) {
cleanJSXElementLiteralChild(child, elements);
continue;
}
if (isJSXExpressionContainer(child)) child = child.expression;
if (isJSXEmptyExpression(child)) continue;
elements.push(child);
}
return elements;
}

View File

@ -0,0 +1,16 @@
// @flow
/**
* Create a shallow clone of a `node` excluding `_private` properties.
*/
export default function clone<T: Object>(node: T): T {
if (!node) return node;
const newNode = (({}: any): T);
Object.keys(node).forEach(key => {
if (key[0] === "_") return;
newNode[key] = node[key];
});
return newNode;
}

View File

@ -0,0 +1,28 @@
// @flow
/**
* Create a deep clone of a `node` and all of it's child nodes
* excluding `_private` properties.
*/
export default function cloneDeep<T: Object>(node: T): T {
if (!node) return node;
const newNode = (({}: any): T);
Object.keys(node).forEach(key => {
if (key[0] === "_") return;
let val = node[key];
if (val) {
if (val.type) {
val = cloneDeep(val);
} else if (Array.isArray(val)) {
val = val.map(cloneDeep);
}
}
newNode[key] = val;
});
return newNode;
}

View File

@ -0,0 +1,12 @@
// @flow
import clone from "./clone";
/**
* Create a shallow clone of a `node` excluding `_private` and location properties.
*/
export default function cloneWithoutLoc<T: Object>(node: T): T {
const newNode = clone(node);
newNode.loc = null;
return newNode;
}

View File

@ -0,0 +1,19 @@
// @flow
import addComments from "./addComments";
/**
* Add comment of certain type to a node.
*/
export default function addComment<T: Object>(
node: T,
type: string,
content: string,
line?: boolean,
): T {
return addComments(node, type, [
{
type: line ? "CommentLine" : "CommentBlock",
value: content,
},
]);
}

View File

@ -0,0 +1,26 @@
// @flow
/**
* Add comments of certain type to a node.
*/
export default function addComments<T: Object>(
node: T,
type: string,
comments: Array<Object>,
): T {
if (!comments || !node) return node;
const key = `${type}Comments`;
if (node[key]) {
if (type === "leading") {
node[key] = comments.concat(node[key]);
} else {
node[key] = node[key].concat(comments);
}
} else {
node[key] = comments;
}
return node;
}

View File

@ -0,0 +1,9 @@
// @flow
import inherit from "../utils/inherit";
export default function inheritInnerComments(
child: Object,
parent: Object,
): void {
inherit("innerComments", child, parent);
}

View File

@ -0,0 +1,9 @@
// @flow
import inherit from "../utils/inherit";
export default function inheritLeadingComments(
child: Object,
parent: Object,
): void {
inherit("leadingComments", child, parent);
}

View File

@ -0,0 +1,9 @@
// @flow
import inherit from "../utils/inherit";
export default function inheritTrailingComments(
child: Object,
parent: Object,
): void {
inherit("trailingComments", child, parent);
}

View File

@ -0,0 +1,18 @@
// @flow
import inheritTrailingComments from "./inheritTrailingComments";
import inheritLeadingComments from "./inheritLeadingComments";
import inheritInnerComments from "./inheritInnerComments";
/**
* Inherit all unique comments from `parent` node to `child` node.
*/
export default function inheritsComments<T: Object>(
child: T,
parent: Object,
): T {
inheritTrailingComments(child, parent);
inheritLeadingComments(child, parent);
inheritInnerComments(child, parent);
return child;
}

View File

@ -0,0 +1,13 @@
// @flow
import { COMMENT_KEYS } from "../constants";
/**
* Remove comment properties from a node.
*/
export default function removeComments<T: Object>(node: T): T {
COMMENT_KEYS.forEach(key => {
node[key] = null;
});
return node;
}

View File

@ -0,0 +1,49 @@
// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import { FLIPPED_ALIAS_KEYS } from "../../definitions";
export const EXPRESSION_TYPES = FLIPPED_ALIAS_KEYS["Expression"];
export const BINARY_TYPES = FLIPPED_ALIAS_KEYS["Binary"];
export const SCOPABLE_TYPES = FLIPPED_ALIAS_KEYS["Scopable"];
export const BLOCKPARENT_TYPES = FLIPPED_ALIAS_KEYS["BlockParent"];
export const BLOCK_TYPES = FLIPPED_ALIAS_KEYS["Block"];
export const STATEMENT_TYPES = FLIPPED_ALIAS_KEYS["Statement"];
export const TERMINATORLESS_TYPES = FLIPPED_ALIAS_KEYS["Terminatorless"];
export const COMPLETIONSTATEMENT_TYPES =
FLIPPED_ALIAS_KEYS["CompletionStatement"];
export const CONDITIONAL_TYPES = FLIPPED_ALIAS_KEYS["Conditional"];
export const LOOP_TYPES = FLIPPED_ALIAS_KEYS["Loop"];
export const WHILE_TYPES = FLIPPED_ALIAS_KEYS["While"];
export const EXPRESSIONWRAPPER_TYPES = FLIPPED_ALIAS_KEYS["ExpressionWrapper"];
export const FOR_TYPES = FLIPPED_ALIAS_KEYS["For"];
export const FORXSTATEMENT_TYPES = FLIPPED_ALIAS_KEYS["ForXStatement"];
export const FUNCTION_TYPES = FLIPPED_ALIAS_KEYS["Function"];
export const FUNCTIONPARENT_TYPES = FLIPPED_ALIAS_KEYS["FunctionParent"];
export const PUREISH_TYPES = FLIPPED_ALIAS_KEYS["Pureish"];
export const DECLARATION_TYPES = FLIPPED_ALIAS_KEYS["Declaration"];
export const PATTERNLIKE_TYPES = FLIPPED_ALIAS_KEYS["PatternLike"];
export const LVAL_TYPES = FLIPPED_ALIAS_KEYS["LVal"];
export const TSENTITYNAME_TYPES = FLIPPED_ALIAS_KEYS["TSEntityName"];
export const LITERAL_TYPES = FLIPPED_ALIAS_KEYS["Literal"];
export const IMMUTABLE_TYPES = FLIPPED_ALIAS_KEYS["Immutable"];
export const USERWHITESPACABLE_TYPES = FLIPPED_ALIAS_KEYS["UserWhitespacable"];
export const METHOD_TYPES = FLIPPED_ALIAS_KEYS["Method"];
export const OBJECTMEMBER_TYPES = FLIPPED_ALIAS_KEYS["ObjectMember"];
export const PROPERTY_TYPES = FLIPPED_ALIAS_KEYS["Property"];
export const UNARYLIKE_TYPES = FLIPPED_ALIAS_KEYS["UnaryLike"];
export const PATTERN_TYPES = FLIPPED_ALIAS_KEYS["Pattern"];
export const CLASS_TYPES = FLIPPED_ALIAS_KEYS["Class"];
export const MODULEDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ModuleDeclaration"];
export const EXPORTDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ExportDeclaration"];
export const MODULESPECIFIER_TYPES = FLIPPED_ALIAS_KEYS["ModuleSpecifier"];
export const FLOW_TYPES = FLIPPED_ALIAS_KEYS["Flow"];
export const FLOWBASEANNOTATION_TYPES =
FLIPPED_ALIAS_KEYS["FlowBaseAnnotation"];
export const FLOWDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["FlowDeclaration"];
export const FLOWPREDICATE_TYPES = FLIPPED_ALIAS_KEYS["FlowPredicate"];
export const JSX_TYPES = FLIPPED_ALIAS_KEYS["JSX"];
export const TSTYPEELEMENT_TYPES = FLIPPED_ALIAS_KEYS["TSTypeElement"];
export const TSTYPE_TYPES = FLIPPED_ALIAS_KEYS["TSType"];

View File

@ -1,5 +1,4 @@
/* eslint max-len: "off" */
// @flow
export const STATEMENT_OR_BLOCK_KEYS = ["consequent", "body", "alternate"];
export const FLATTENABLE_KEYS = ["body", "expressions"];
export const FOR_INIT_KEYS = ["left", "init"];
@ -62,30 +61,3 @@ export const BLOCK_SCOPED_SYMBOL = Symbol.for("var used to be block scoped");
export const NOT_LOCAL_BINDING = Symbol.for(
"should not be considered a local binding",
);
export const RESERVED_WORDS_ES3_ONLY = new Set([
"abstract",
"boolean",
"byte",
"char",
"double",
"enum",
"final",
"float",
"goto",
"implements",
"int",
"interface",
"long",
"native",
"package",
"private",
"protected",
"public",
"short",
"static",
"synchronized",
"throws",
"transient",
"volatile",
]);

View File

@ -1,321 +0,0 @@
import isPlainObject from "lodash/isPlainObject";
import isRegExp from "lodash/isRegExp";
import type { Scope } from "@babel/traverse";
import * as t from "./index";
export function toComputedKey(
node: Object,
key: Object = node.key || node.property,
): Object {
if (!node.computed) {
if (t.isIdentifier(key)) key = t.stringLiteral(key.name);
}
return key;
}
function gatherSequenceExpressions(
nodes: Array<Object>,
scope: Scope,
declars: Array<Object>,
): ?Object {
const exprs = [];
let ensureLastUndefined = true;
for (const node of nodes) {
ensureLastUndefined = false;
if (t.isExpression(node)) {
exprs.push(node);
} else if (t.isExpressionStatement(node)) {
exprs.push(node.expression);
} else if (t.isVariableDeclaration(node)) {
if (node.kind !== "var") return; // bailed
for (const declar of (node.declarations: Array)) {
const bindings = t.getBindingIdentifiers(declar);
for (const key in bindings) {
declars.push({
kind: node.kind,
id: bindings[key],
});
}
if (declar.init) {
exprs.push(t.assignmentExpression("=", declar.id, declar.init));
}
}
ensureLastUndefined = true;
} else if (t.isIfStatement(node)) {
const consequent = node.consequent
? gatherSequenceExpressions([node.consequent], scope, declars)
: scope.buildUndefinedNode();
const alternate = node.alternate
? gatherSequenceExpressions([node.alternate], scope, declars)
: scope.buildUndefinedNode();
if (!consequent || !alternate) return; // bailed
exprs.push(t.conditionalExpression(node.test, consequent, alternate));
} else if (t.isBlockStatement(node)) {
const body = gatherSequenceExpressions(node.body, scope, declars);
if (!body) return; // bailed
exprs.push(body);
} else if (t.isEmptyStatement(node)) {
// empty statement so ensure the last item is undefined if we're last
ensureLastUndefined = true;
} else {
// bailed, we can't turn this statement into an expression
return;
}
}
if (ensureLastUndefined) {
exprs.push(scope.buildUndefinedNode());
}
if (exprs.length === 1) {
return exprs[0];
} else {
return t.sequenceExpression(exprs);
}
}
/**
* Turn an array of statement `nodes` into a `SequenceExpression`.
*
* Variable declarations are turned into simple assignments and their
* declarations hoisted to the top of the current scope.
*
* Expression statements are just resolved to their expression.
*/
export function toSequenceExpression(
nodes: Array<Object>,
scope: Scope,
): ?Object {
if (!nodes || !nodes.length) return;
const declars = [];
const result = gatherSequenceExpressions(nodes, scope, declars);
if (!result) return;
for (const declar of declars) {
scope.push(declar);
}
return result;
}
export function toKeyAlias(node: Object, key: Object = node.key): string {
let alias;
if (node.kind === "method") {
return toKeyAlias.increment() + "";
} else if (t.isIdentifier(key)) {
alias = key.name;
} else if (t.isStringLiteral(key)) {
alias = JSON.stringify(key.value);
} else {
alias = JSON.stringify(t.removePropertiesDeep(t.cloneDeep(key)));
}
if (node.computed) {
alias = `[${alias}]`;
}
if (node.static) {
alias = `static:${alias}`;
}
return alias;
}
toKeyAlias.uid = 0;
toKeyAlias.increment = function() {
if (toKeyAlias.uid >= Number.MAX_SAFE_INTEGER) {
return (toKeyAlias.uid = 0);
} else {
return toKeyAlias.uid++;
}
};
export function toIdentifier(name: string): string {
name = name + "";
// replace all non-valid identifiers with dashes
name = name.replace(/[^a-zA-Z0-9$_]/g, "-");
// remove all dashes and numbers from start of name
name = name.replace(/^[-0-9]+/, "");
// camel case
name = name.replace(/[-\s]+(.)?/g, function(match, c) {
return c ? c.toUpperCase() : "";
});
if (!t.isValidIdentifier(name)) {
name = `_${name}`;
}
return name || "_";
}
export function toBindingIdentifierName(name: string): string {
name = toIdentifier(name);
if (name === "eval" || name === "arguments") name = "_" + name;
return name;
}
/**
* [Please add a description.]
* @returns {Object|Boolean}
*/
export function toStatement(node: Object, ignore?: boolean) {
if (t.isStatement(node)) {
return node;
}
let mustHaveId = false;
let newType;
if (t.isClass(node)) {
mustHaveId = true;
newType = "ClassDeclaration";
} else if (t.isFunction(node)) {
mustHaveId = true;
newType = "FunctionDeclaration";
} else if (t.isAssignmentExpression(node)) {
return t.expressionStatement(node);
}
if (mustHaveId && !node.id) {
newType = false;
}
if (!newType) {
if (ignore) {
return false;
} else {
throw new Error(`cannot turn ${node.type} to a statement`);
}
}
node.type = newType;
return node;
}
export function toExpression(node: Object): Object {
if (t.isExpressionStatement(node)) {
node = node.expression;
}
// return unmodified node
// important for things like ArrowFunctions where
// type change from ArrowFunction to FunctionExpression
// produces bugs like -> `()=>a` to `function () a`
// without generating a BlockStatement for it
// ref: https://github.com/babel/babili/issues/130
if (t.isExpression(node)) {
return node;
}
// convert all classes and functions
// ClassDeclaration -> ClassExpression
// FunctionDeclaration, ObjectMethod, ClassMethod -> FunctionExpression
if (t.isClass(node)) {
node.type = "ClassExpression";
} else if (t.isFunction(node)) {
node.type = "FunctionExpression";
}
// if it's still not an expression
if (!t.isExpression(node)) {
throw new Error(`cannot turn ${node.type} to an expression`);
}
return node;
}
export function toBlock(node: Object, parent: Object): Object {
if (t.isBlockStatement(node)) {
return node;
}
if (t.isEmptyStatement(node)) {
node = [];
}
if (!Array.isArray(node)) {
if (!t.isStatement(node)) {
if (t.isFunction(parent)) {
node = t.returnStatement(node);
} else {
node = t.expressionStatement(node);
}
}
node = [node];
}
return t.blockStatement(node);
}
export function valueToNode(value: any): Object {
// undefined
if (value === undefined) {
return t.identifier("undefined");
}
// boolean
if (value === true || value === false) {
return t.booleanLiteral(value);
}
// null
if (value === null) {
return t.nullLiteral();
}
// strings
if (typeof value === "string") {
return t.stringLiteral(value);
}
// numbers
if (typeof value === "number") {
return t.numericLiteral(value);
}
// regexes
if (isRegExp(value)) {
const pattern = value.source;
const flags = value.toString().match(/\/([a-z]+|)$/)[1];
return t.regExpLiteral(pattern, flags);
}
// array
if (Array.isArray(value)) {
return t.arrayExpression(value.map(t.valueToNode));
}
// object
if (isPlainObject(value)) {
const props = [];
for (const key in value) {
let nodeKey;
if (t.isValidIdentifier(key)) {
nodeKey = t.identifier(key);
} else {
nodeKey = t.stringLiteral(key);
}
props.push(t.objectProperty(nodeKey, t.valueToNode(value[key])));
}
return t.objectExpression(props);
}
throw new Error("don't know how to turn this value into a node");
}

View File

@ -0,0 +1,15 @@
// @flow
import toBlock from "./toBlock";
/**
* Ensure the `key` (defaults to "body") of a `node` is a block.
* Casting it to a block if it is not.
*
* Returns the BlockStatement
*/
export default function ensureBlock(
node: Object,
key: string = "body",
): Object {
return (node[key] = toBlock(node[key], node));
}

View File

@ -0,0 +1,84 @@
// @flow
import type { Scope } from "@babel/traverse";
import getBindingIdentifiers from "../retrievers/getBindingIdentifiers";
import {
isExpression,
isExpressionStatement,
isVariableDeclaration,
isIfStatement,
isBlockStatement,
isEmptyStatement,
} from "../validators/generated";
import {
sequenceExpression,
assignmentExpression,
conditionalExpression,
} from "../builders/generated";
export default function gatherSequenceExpressions(
nodes: Array<Object>,
scope: Scope,
declars: Array<Object>,
): ?Object {
const exprs = [];
let ensureLastUndefined = true;
for (const node of nodes) {
ensureLastUndefined = false;
if (isExpression(node)) {
exprs.push(node);
} else if (isExpressionStatement(node)) {
exprs.push(node.expression);
} else if (isVariableDeclaration(node)) {
if (node.kind !== "var") return; // bailed
for (const declar of (node.declarations: Array<any>)) {
const bindings = getBindingIdentifiers(declar);
for (const key in bindings) {
declars.push({
kind: node.kind,
id: bindings[key],
});
}
if (declar.init) {
exprs.push(assignmentExpression("=", declar.id, declar.init));
}
}
ensureLastUndefined = true;
} else if (isIfStatement(node)) {
const consequent = node.consequent
? gatherSequenceExpressions([node.consequent], scope, declars)
: scope.buildUndefinedNode();
const alternate = node.alternate
? gatherSequenceExpressions([node.alternate], scope, declars)
: scope.buildUndefinedNode();
if (!consequent || !alternate) return; // bailed
exprs.push(conditionalExpression(node.test, consequent, alternate));
} else if (isBlockStatement(node)) {
const body = gatherSequenceExpressions(node.body, scope, declars);
if (!body) return; // bailed
exprs.push(body);
} else if (isEmptyStatement(node)) {
// empty statement so ensure the last item is undefined if we're last
ensureLastUndefined = true;
} else {
// bailed, we can't turn this statement into an expression
return;
}
}
if (ensureLastUndefined) {
exprs.push(scope.buildUndefinedNode());
}
if (exprs.length === 1) {
return exprs[0];
} else {
return sequenceExpression(exprs);
}
}

View File

@ -0,0 +1,9 @@
// @flow
import toIdentifier from "./toIdentifier";
export default function toBindingIdentifierName(name: string): string {
name = toIdentifier(name);
if (name === "eval" || name === "arguments") name = "_" + name;
return name;
}

View File

@ -0,0 +1,36 @@
// @flow
import {
isBlockStatement,
isFunction,
isEmptyStatement,
isStatement,
} from "../validators/generated";
import {
returnStatement,
expressionStatement,
blockStatement,
} from "../builders/generated";
export default function toBlock(node: Object, parent: Object): Object {
if (isBlockStatement(node)) {
return node;
}
let blockNodes = [];
if (isEmptyStatement(node)) {
blockNodes = [];
} else {
if (!isStatement(node)) {
if (isFunction(parent)) {
node = returnStatement(node);
} else {
node = expressionStatement(node);
}
}
blockNodes = [node];
}
return blockStatement(blockNodes);
}

View File

@ -0,0 +1,12 @@
// @flow
import { isIdentifier } from "../validators/generated";
import { stringLiteral } from "../builders/generated";
export default function toComputedKey(
node: Object,
key: Object = node.key || node.property,
): Object {
if (!node.computed && isIdentifier(key)) key = stringLiteral(key.name);
return key;
}

View File

@ -0,0 +1,39 @@
// @flow
import {
isExpression,
isFunction,
isClass,
isExpressionStatement,
} from "../validators/generated";
export default function toExpression(node: Object): Object {
if (isExpressionStatement(node)) {
node = node.expression;
}
// return unmodified node
// important for things like ArrowFunctions where
// type change from ArrowFunction to FunctionExpression
// produces bugs like -> `()=>a` to `function () a`
// without generating a BlockStatement for it
// ref: https://github.com/babel/babili/issues/130
if (isExpression(node)) {
return node;
}
// convert all classes and functions
// ClassDeclaration -> ClassExpression
// FunctionDeclaration, ObjectMethod, ClassMethod -> FunctionExpression
if (isClass(node)) {
node.type = "ClassExpression";
} else if (isFunction(node)) {
node.type = "FunctionExpression";
}
// if it's still not an expression
if (!isExpression(node)) {
throw new Error(`cannot turn ${node.type} to an expression`);
}
return node;
}

View File

@ -0,0 +1,23 @@
// @flow
import isValidIdentifier from "../validators/isValidIdentifier";
export default function toIdentifier(name: string): string {
name = name + "";
// replace all non-valid identifiers with dashes
name = name.replace(/[^a-zA-Z0-9$_]/g, "-");
// remove all dashes and numbers from start of name
name = name.replace(/^[-0-9]+/, "");
// camel case
name = name.replace(/[-\s]+(.)?/g, function(match, c) {
return c ? c.toUpperCase() : "";
});
if (!isValidIdentifier(name)) {
name = `_${name}`;
}
return name || "_";
}

View File

@ -0,0 +1,41 @@
// @flow
import { isIdentifier, isStringLiteral } from "../validators/generated";
import cloneDeep from "../clone/cloneDeep";
import removePropertiesDeep from "../modifications/removePropertiesDeep";
export default function toKeyAlias(
node: Object,
key: Object = node.key,
): string {
let alias;
if (node.kind === "method") {
return toKeyAlias.increment() + "";
} else if (isIdentifier(key)) {
alias = key.name;
} else if (isStringLiteral(key)) {
alias = JSON.stringify(key.value);
} else {
alias = JSON.stringify(removePropertiesDeep(cloneDeep(key)));
}
if (node.computed) {
alias = `[${alias}]`;
}
if (node.static) {
alias = `static:${alias}`;
}
return alias;
}
toKeyAlias.uid = 0;
toKeyAlias.increment = function() {
if (toKeyAlias.uid >= Number.MAX_SAFE_INTEGER) {
return (toKeyAlias.uid = 0);
} else {
return toKeyAlias.uid++;
}
};

View File

@ -0,0 +1,28 @@
// @flow
import type { Scope } from "@babel/traverse";
import gatherSequenceExpressions from "./gatherSequenceExpressions";
/**
* Turn an array of statement `nodes` into a `SequenceExpression`.
*
* Variable declarations are turned into simple assignments and their
* declarations hoisted to the top of the current scope.
*
* Expression statements are just resolved to their expression.
*/
export default function toSequenceExpression(
nodes: Array<Object>,
scope: Scope,
): ?Object {
if (!nodes || !nodes.length) return;
const declars = [];
const result = gatherSequenceExpressions(nodes, scope, declars);
if (!result) return;
for (const declar of declars) {
scope.push(declar);
}
return result;
}

View File

@ -0,0 +1,43 @@
// @flow
import {
isStatement,
isFunction,
isClass,
isAssignmentExpression,
} from "../validators/generated";
import { expressionStatement } from "../builders/generated";
export default function toStatement(node: Object, ignore?: boolean) {
if (isStatement(node)) {
return node;
}
let mustHaveId = false;
let newType;
if (isClass(node)) {
mustHaveId = true;
newType = "ClassDeclaration";
} else if (isFunction(node)) {
mustHaveId = true;
newType = "FunctionDeclaration";
} else if (isAssignmentExpression(node)) {
return expressionStatement(node);
}
if (mustHaveId && !node.id) {
newType = false;
}
if (!newType) {
if (ignore) {
return false;
} else {
throw new Error(`cannot turn ${node.type} to a statement`);
}
}
node.type = newType;
return node;
}

View File

@ -0,0 +1,71 @@
// @flow
import isPlainObject from "lodash/isPlainObject";
import isRegExp from "lodash/isRegExp";
import isValidIdentifier from "../validators/isValidIdentifier";
import {
identifier,
booleanLiteral,
nullLiteral,
stringLiteral,
numericLiteral,
regExpLiteral,
arrayExpression,
objectProperty,
objectExpression,
} from "../builders/generated";
export default function valueToNode(value: any): Object {
// undefined
if (value === undefined) {
return identifier("undefined");
}
// boolean
if (value === true || value === false) {
return booleanLiteral(value);
}
// null
if (value === null) {
return nullLiteral();
}
// strings
if (typeof value === "string") {
return stringLiteral(value);
}
// numbers
if (typeof value === "number") {
return numericLiteral(value);
}
// regexes
if (isRegExp(value)) {
const pattern = value.source;
const flags = value.toString().match(/\/([a-z]+|)$/)[1];
return regExpLiteral(pattern, flags);
}
// array
if (Array.isArray(value)) {
return arrayExpression(value.map(valueToNode));
}
// object
if (isPlainObject(value)) {
const props = [];
for (const key in value) {
let nodeKey;
if (isValidIdentifier(key)) {
nodeKey = identifier(key);
} else {
nodeKey = stringLiteral(key);
}
props.push(objectProperty(nodeKey, valueToNode(value[key])));
}
return objectExpression(props);
}
throw new Error("don't know how to turn this value into a node");
}

View File

@ -1,5 +1,5 @@
// @flow
import * as t from "../index";
import isValidIdentifier from "../validators/isValidIdentifier";
import {
BINARY_OPERATORS,
@ -15,7 +15,7 @@ import defineType, {
assertEach,
chain,
assertOneOf,
} from "./index";
} from "./utils";
defineType("ArrayExpression", {
fields: {
@ -372,7 +372,7 @@ defineType("Identifier", {
...patternLikeCommon,
name: {
validate(node, key, val) {
if (!t.isValidIdentifier(val)) {
if (!isValidIdentifier(val)) {
// throw new TypeError(`"${val}" is not a valid identifer name`);
}
},

View File

@ -5,7 +5,7 @@ import defineType, {
chain,
assertEach,
assertOneOf,
} from "./index";
} from "./utils";
import { functionCommon, patternLikeCommon } from "./core";
defineType("AssignmentPattern", {

View File

@ -4,7 +4,7 @@ import defineType, {
assertNodeType,
assertValueType,
chain,
} from "./index";
} from "./utils";
import { classMethodOrPropertyCommon } from "./es2015";
defineType("AwaitExpression", {

View File

@ -4,7 +4,7 @@ import defineType, {
assertNodeType,
assertValueType,
chain,
} from "./index";
} from "./utils";
defineType("AnyTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"],

View File

@ -1,177 +1,39 @@
// @flow
import * as t from "../index";
import toFastProperties from "to-fast-properties";
import "./core";
import "./es2015";
import "./flow";
import "./jsx";
import "./misc";
import "./experimental";
import "./typescript";
import {
VISITOR_KEYS,
ALIAS_KEYS,
FLIPPED_ALIAS_KEYS,
NODE_FIELDS,
BUILDER_KEYS,
DEPRECATED_KEYS,
} from "./utils";
export const VISITOR_KEYS = {};
export const ALIAS_KEYS = {};
export const NODE_FIELDS = {};
export const BUILDER_KEYS = {};
export const DEPRECATED_KEYS = {};
// We do this here, because at this point the visitor keys should be ready and setup
toFastProperties(VISITOR_KEYS);
toFastProperties(ALIAS_KEYS);
toFastProperties(FLIPPED_ALIAS_KEYS);
toFastProperties(NODE_FIELDS);
toFastProperties(BUILDER_KEYS);
toFastProperties(DEPRECATED_KEYS);
function getType(val) {
if (Array.isArray(val)) {
return "array";
} else if (val === null) {
return "null";
} else if (val === undefined) {
return "undefined";
} else {
return typeof val;
}
}
const TYPES = Object.keys(VISITOR_KEYS)
.concat(Object.keys(FLIPPED_ALIAS_KEYS))
.concat(Object.keys(DEPRECATED_KEYS));
export function assertEach(callback: Function): Function {
function validator(node, key, val) {
if (!Array.isArray(val)) return;
for (let i = 0; i < val.length; i++) {
callback(node, `${key}[${i}]`, val[i]);
}
}
validator.each = callback;
return validator;
}
export function assertOneOf(...vals: Array<any>): Function {
function validate(node: Object, key: string, val: any): void {
if (vals.indexOf(val) < 0) {
throw new TypeError(
`Property ${key} expected value to be one of ${JSON.stringify(
vals,
)} but got ${JSON.stringify(val)}`,
);
}
}
validate.oneOf = vals;
return validate;
}
export function assertNodeType(...types: Array<string>): Function {
function validate(node, key, val) {
let valid = false;
for (const type of types) {
if (t.is(type, val)) {
valid = true;
break;
}
}
if (!valid) {
throw new TypeError(
`Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(
types,
)} ` + `but instead got ${JSON.stringify(val && val.type)}`,
);
}
}
validate.oneOfNodeTypes = types;
return validate;
}
export function assertNodeOrValueType(...types: Array<string>): Function {
function validate(node, key, val) {
let valid = false;
for (const type of types) {
if (getType(val) === type || t.is(type, val)) {
valid = true;
break;
}
}
if (!valid) {
throw new TypeError(
`Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(
types,
)} ` + `but instead got ${JSON.stringify(val && val.type)}`,
);
}
}
validate.oneOfNodeOrValueTypes = types;
return validate;
}
export function assertValueType(type: string): Function {
function validate(node, key, val) {
const valid = getType(val) === type;
if (!valid) {
throw new TypeError(
`Property ${key} expected type of ${type} but got ${getType(val)}`,
);
}
}
validate.type = type;
return validate;
}
export function chain(...fns: Array<Function>): Function {
function validate(...args) {
for (const fn of fns) {
fn(...args);
}
}
validate.chainOf = fns;
return validate;
}
export default function defineType(
type: string,
opts: {
fields?: {
[string]: {| validate?: Function, default?: any, optional?: boolean |},
},
visitor?: Array<string>,
aliases?: Array<string>,
builder?: Array<string>,
inherits?: string,
deprecatedAlias?: string,
} = {},
) {
const inherits = (opts.inherits && store[opts.inherits]) || {};
const fields = opts.fields || inherits.fields || {};
const visitor = opts.visitor || inherits.visitor || [];
const aliases = opts.aliases || inherits.aliases || [];
const builder = opts.builder || inherits.builder || opts.visitor || [];
if (opts.deprecatedAlias) {
DEPRECATED_KEYS[opts.deprecatedAlias] = type;
}
// ensure all field keys are represented in `fields`
for (const key of (visitor.concat(builder): Array<string>)) {
// $FlowIssue
fields[key] = fields[key] || {};
}
for (const key in fields) {
const field = fields[key];
if (builder.indexOf(key) === -1) {
field.optional = true;
}
if (field.default === undefined) {
field.default = null;
} else if (!field.validate) {
field.validate = assertValueType(getType(field.default));
}
}
VISITOR_KEYS[type] = opts.visitor = visitor;
BUILDER_KEYS[type] = opts.builder = builder;
NODE_FIELDS[type] = opts.fields = fields;
ALIAS_KEYS[type] = opts.aliases = aliases;
store[type] = opts;
}
const store = {};
export {
VISITOR_KEYS,
ALIAS_KEYS,
FLIPPED_ALIAS_KEYS,
NODE_FIELDS,
BUILDER_KEYS,
DEPRECATED_KEYS,
TYPES,
};

View File

@ -1,8 +0,0 @@
import "./index";
import "./core";
import "./es2015";
import "./flow";
import "./jsx";
import "./misc";
import "./experimental";
import "./typescript";

View File

@ -4,7 +4,7 @@ import defineType, {
assertValueType,
chain,
assertEach,
} from "./index";
} from "./utils";
defineType("JSXAttribute", {
visitor: ["name", "value"],

View File

@ -1,5 +1,5 @@
// @flow
import defineType, { assertNodeType } from "./index";
import defineType, { assertNodeType } from "./utils";
defineType("Noop", {
visitor: [],

View File

@ -1,12 +1,11 @@
// @flow
import defineType, {
assertEach,
assertNodeType,
assertOneOf,
assertValueType,
chain,
} from "./index";
} from "./utils";
import { functionDeclarationCommon } from "./core";
import { classMethodOrDeclareMethodCommon } from "./es2015";

View File

@ -0,0 +1,182 @@
// @flow
import is from "../validators/is";
export const VISITOR_KEYS: { [string]: Array<string> } = {};
export const ALIAS_KEYS: { [string]: Array<string> } = {};
export const FLIPPED_ALIAS_KEYS: { [string]: Array<string> } = {};
export const NODE_FIELDS: { [string]: {} } = {};
export const BUILDER_KEYS: { [string]: Array<string> } = {};
export const DEPRECATED_KEYS: { [string]: string } = {};
function getType(val) {
if (Array.isArray(val)) {
return "array";
} else if (val === null) {
return "null";
} else if (val === undefined) {
return "undefined";
} else {
return typeof val;
}
}
export function assertEach(callback: Function): Function {
function validator(node, key, val) {
if (!Array.isArray(val)) return;
for (let i = 0; i < val.length; i++) {
callback(node, `${key}[${i}]`, val[i]);
}
}
validator.each = callback;
return validator;
}
export function assertOneOf(...values: Array<any>): Function {
function validate(node: Object, key: string, val: any) {
if (values.indexOf(val) < 0) {
throw new TypeError(
`Property ${key} expected value to be one of ${JSON.stringify(
values,
)} but got ${JSON.stringify(val)}`,
);
}
}
validate.oneOf = values;
return validate;
}
export function assertNodeType(...types: Array<string>): Function {
function validate(node, key, val) {
let valid = false;
for (const type of types) {
if (is(type, val)) {
valid = true;
break;
}
}
if (!valid) {
throw new TypeError(
`Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(
types,
)} ` + `but instead got ${JSON.stringify(val && val.type)}`,
);
}
}
validate.oneOfNodeTypes = types;
return validate;
}
export function assertNodeOrValueType(...types: Array<string>): Function {
function validate(node, key, val) {
let valid = false;
for (const type of types) {
if (getType(val) === type || is(type, val)) {
valid = true;
break;
}
}
if (!valid) {
throw new TypeError(
`Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(
types,
)} ` + `but instead got ${JSON.stringify(val && val.type)}`,
);
}
}
validate.oneOfNodeOrValueTypes = types;
return validate;
}
export function assertValueType(type: string): Function {
function validate(node, key, val) {
const valid = getType(val) === type;
if (!valid) {
throw new TypeError(
`Property ${key} expected type of ${type} but got ${getType(val)}`,
);
}
}
validate.type = type;
return validate;
}
export function chain(...fns: Array<Function>): Function {
function validate(...args) {
for (const fn of fns) {
fn(...args);
}
}
validate.chainOf = fns;
return validate;
}
export default function defineType(
type: string,
opts: {
fields?: {
[string]: {| validate?: Function, default?: any, optional?: boolean |},
},
visitor?: Array<string>,
aliases?: Array<string>,
builder?: Array<string>,
inherits?: string,
deprecatedAlias?: string,
} = {},
) {
const inherits = (opts.inherits && store[opts.inherits]) || {};
const fields: Object = opts.fields || inherits.fields || {};
const visitor: Array<string> = opts.visitor || inherits.visitor || [];
const aliases: Array<string> = opts.aliases || inherits.aliases || [];
const builder: Array<string> =
opts.builder || inherits.builder || opts.visitor || [];
if (opts.deprecatedAlias) {
DEPRECATED_KEYS[opts.deprecatedAlias] = type;
}
// ensure all field keys are represented in `fields`
for (const key of (visitor.concat(builder): Array<string>)) {
fields[key] = fields[key] || {};
}
for (const key in fields) {
const field = fields[key];
if (builder.indexOf(key) === -1) {
field.optional = true;
}
if (field.default === undefined) {
field.default = null;
} else if (!field.validate) {
field.validate = assertValueType(getType(field.default));
}
}
VISITOR_KEYS[type] = opts.visitor = visitor;
BUILDER_KEYS[type] = opts.builder = builder;
NODE_FIELDS[type] = opts.fields = fields;
ALIAS_KEYS[type] = opts.aliases = aliases;
aliases.forEach(alias => {
FLIPPED_ALIAS_KEYS[alias] = FLIPPED_ALIAS_KEYS[alias] || [];
FLIPPED_ALIAS_KEYS[alias].push(type);
});
store[type] = opts;
}
const store = {};

View File

@ -1,601 +1,123 @@
import toFastProperties from "to-fast-properties";
import loClone from "lodash/clone";
import uniq from "lodash/uniq";
// @flow
import isReactComponent from "./validators/react/isReactComponent";
import isCompatTag from "./validators/react/isCompatTag";
import buildChildren from "./builders/react/buildChildren";
const t = exports;
/**
* Registers `is[Type]` and `assert[Type]` generated functions for a given `type`.
* Pass `skipAliasCheck` to force it to directly compare `node.type` with `type`.
*/
function registerType(type: string) {
let is = t[`is${type}`];
if (!is) {
is = t[`is${type}`] = function(node, opts) {
return t.is(type, node, opts);
};
}
t[`assert${type}`] = function(node, opts) {
opts = opts || {};
if (!is(node, opts)) {
throw new Error(
`Expected type ${JSON.stringify(type)} with option ${JSON.stringify(
opts,
)}`,
);
}
};
}
//
// asserts
export { default as assertNode } from "./asserts/assertNode";
export * from "./asserts/generated";
//builders
export {
STATEMENT_OR_BLOCK_KEYS,
FLATTENABLE_KEYS,
FOR_INIT_KEYS,
COMMENT_KEYS,
LOGICAL_OPERATORS,
UPDATE_OPERATORS,
BOOLEAN_NUMBER_BINARY_OPERATORS,
EQUALITY_BINARY_OPERATORS,
COMPARISON_BINARY_OPERATORS,
BOOLEAN_BINARY_OPERATORS,
NUMBER_BINARY_OPERATORS,
BINARY_OPERATORS,
BOOLEAN_UNARY_OPERATORS,
NUMBER_UNARY_OPERATORS,
STRING_UNARY_OPERATORS,
UNARY_OPERATORS,
INHERIT_KEYS,
BLOCK_SCOPED_SYMBOL,
NOT_LOCAL_BINDING,
} from "./constants";
import "./definitions/init";
import {
VISITOR_KEYS,
ALIAS_KEYS,
NODE_FIELDS,
BUILDER_KEYS,
DEPRECATED_KEYS,
} from "./definitions";
export { VISITOR_KEYS, ALIAS_KEYS, NODE_FIELDS, BUILDER_KEYS, DEPRECATED_KEYS };
import * as _react from "./react";
export { _react as react };
import { traverse, traverseFast } from "./traverse";
export { traverse, traverseFast };
/**
* Registers `is[Type]` and `assert[Type]` for all types.
*/
for (const type in t.VISITOR_KEYS) {
registerType(type);
}
/**
* Flip `ALIAS_KEYS` for faster access in the reverse direction.
*/
t.FLIPPED_ALIAS_KEYS = {};
Object.keys(t.ALIAS_KEYS).forEach(function(type) {
t.ALIAS_KEYS[type].forEach(function(alias) {
const types = (t.FLIPPED_ALIAS_KEYS[alias] =
t.FLIPPED_ALIAS_KEYS[alias] || []);
types.push(type);
});
});
/**
* Registers `is[Alias]` and `assert[Alias]` functions for all aliases.
*/
Object.keys(t.FLIPPED_ALIAS_KEYS).forEach(function(type) {
t[type.toUpperCase() + "_TYPES"] = t.FLIPPED_ALIAS_KEYS[type];
registerType(type);
});
export const TYPES = Object.keys(t.VISITOR_KEYS)
.concat(Object.keys(t.FLIPPED_ALIAS_KEYS))
.concat(Object.keys(t.DEPRECATED_KEYS));
/**
* Returns whether `node` is of given `type`.
*
* For better performance, use this instead of `is[Type]` when `type` is unknown.
* Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`.
*/
export function is(type: string, node: Object, opts?: Object): boolean {
if (!node) return false;
const matches = isType(node.type, type);
if (!matches) return false;
if (typeof opts === "undefined") {
return true;
} else {
return t.shallowEqual(node, opts);
}
}
/**
* Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`.
*/
export 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
// targetType was a primary node type, so there's no need to check the aliases.
if (t.ALIAS_KEYS[targetType]) return false;
const aliases: ?Array<string> = t.FLIPPED_ALIAS_KEYS[targetType];
if (aliases) {
if (aliases[0] === nodeType) return true;
for (const alias of aliases) {
if (nodeType === alias) return true;
}
}
return false;
}
/**
* Description
*/
Object.keys(t.BUILDER_KEYS).forEach(function(type) {
const keys = t.BUILDER_KEYS[type];
function builder() {
if (arguments.length > keys.length) {
throw new Error(
`t.${type}: Too many arguments passed. Received ${arguments.length} but can receive ` +
`no more than ${keys.length}`,
);
}
const node = {};
node.type = type;
let i = 0;
for (const key of (keys: Array<string>)) {
const field = t.NODE_FIELDS[type][key];
let arg = arguments[i++];
if (arg === undefined) arg = loClone(field.default);
node[key] = arg;
}
for (const key in node) {
validate(node, key, node[key]);
}
return node;
}
t[type] = builder;
t[type[0].toLowerCase() + type.slice(1)] = builder;
});
/**
* Description
*/
for (const type in t.DEPRECATED_KEYS) {
const newType = t.DEPRECATED_KEYS[type];
function proxy(fn) {
return function() {
console.trace(`The node type ${type} has been renamed to ${newType}`);
return fn.apply(this, arguments);
};
}
t[type] = t[type[0].toLowerCase() + type.slice(1)] = proxy(t[newType]);
t[`is${type}`] = proxy(t[`is${newType}`]);
t[`assert${type}`] = proxy(t[`assert${newType}`]);
}
/**
* Description
*/
export function validate(node?: Object, key: string, val: any) {
if (!node) return;
const fields = t.NODE_FIELDS[node.type];
if (!fields) return;
const field = fields[key];
if (!field || !field.validate) return;
if (field.optional && val == null) return;
field.validate(node, key, val);
}
/**
* Test if an object is shallowly equal.
*/
export function shallowEqual(actual: Object, expected: Object): boolean {
const keys = Object.keys(expected);
for (const key of (keys: Array<string>)) {
if (actual[key] !== expected[key]) {
return false;
}
}
return true;
}
/**
* Append a node to a member expression.
*/
export function appendToMemberExpression(
member: Object,
append: Object,
computed?: boolean,
): Object {
member.object = t.memberExpression(
member.object,
member.property,
member.computed,
);
member.property = append;
member.computed = !!computed;
return member;
}
/**
* Prepend a node to a member expression.
*/
export function prependToMemberExpression(
member: Object,
prepend: Object,
): Object {
member.object = t.memberExpression(prepend, member.object);
return member;
}
/**
* Ensure the `key` (defaults to "body") of a `node` is a block.
* Casting it to a block if it is not.
*/
export function ensureBlock(node: Object, key: string = "body"): Object {
return (node[key] = t.toBlock(node[key], node));
}
/**
* Create a shallow clone of a `node` excluding `_private` properties.
*/
export function clone(node: Object): Object {
if (!node) return node;
const newNode = {};
for (const key in node) {
if (key[0] === "_") continue;
newNode[key] = node[key];
}
return newNode;
}
/**
* Create a shallow clone of a `node` excluding `_private` and location properties.
*/
export function cloneWithoutLoc(node: Object): Object {
const newNode = clone(node);
newNode.loc = null;
return newNode;
}
/**
* Create a deep clone of a `node` and all of it's child nodes
* exluding `_private` properties.
*/
export function cloneDeep(node: Object): Object {
if (!node) return node;
const newNode = {};
for (const key in node) {
if (key[0] === "_") continue;
let val = node[key];
if (val) {
if (val.type) {
val = t.cloneDeep(val);
} else if (Array.isArray(val)) {
val = val.map(t.cloneDeep);
}
}
newNode[key] = val;
}
return newNode;
}
/**
* Determines whether or not the input node `member` matches the
* input `match`.
*
* For example, given the match `React.createClass` it would match the
* parsed nodes of `React.createClass` and `React["createClass"]`.
*/
export function matchesPattern(
member: Object,
match: string | Array<string>,
allowPartial?: boolean,
): boolean {
// not a member expression
if (!t.isMemberExpression(member)) return false;
const parts = Array.isArray(match) ? match : match.split(".");
const nodes = [];
let node;
for (node = member; t.isMemberExpression(node); node = node.object) {
nodes.push(node.property);
}
nodes.push(node);
if (nodes.length < parts.length) return false;
if (!allowPartial && nodes.length > parts.length) return false;
for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
const node = nodes[j];
let value;
if (t.isIdentifier(node)) {
value = node.name;
} else if (t.isStringLiteral(node)) {
value = node.value;
} else {
return false;
}
if (parts[i] !== value) return false;
}
return true;
}
/**
* Build a function that when called will return whether or not the
* input `node` `MemberExpression` matches the input `match`.
*
* For example, given the match `React.createClass` it would match the
* parsed nodes of `React.createClass` and `React["createClass"]`.
*/
export function buildMatchMemberExpression(
match: string,
allowPartial?: boolean,
): Object => boolean {
const parts = match.split(".");
return function(member) {
return matchesPattern(member, parts, allowPartial);
};
}
/**
* Add comment of certain type to a node.
*/
export function addComment(
node: Object,
type: string,
content: string,
line?: boolean,
): Object {
addComments(node, type, [
{
type: line ? "CommentLine" : "CommentBlock",
value: content,
},
]);
}
/**
* Add comments of certain type to a node.
*/
export function addComments(
node: Object,
type: string,
comments: Array,
): Object {
if (!comments || !node) return;
const key = `${type}Comments`;
if (node[key]) {
if (type === "leading") {
node[key] = comments.concat(node[key]);
} else {
node[key] = node[key].concat(comments);
}
} else {
node[key] = comments;
}
return node;
}
/**
* Remove comment properties from a node.
*/
export function removeComments(node: Object): Object {
for (const key of t.COMMENT_KEYS) {
node[key] = null;
}
return node;
}
/**
* Inherit all unique comments from `parent` node to `child` node.
*/
export function inheritsComments(child: Object, parent: Object): Object {
inheritTrailingComments(child, parent);
inheritLeadingComments(child, parent);
inheritInnerComments(child, parent);
return child;
}
export function inheritTrailingComments(child: Object, parent: Object) {
_inheritComments("trailingComments", child, parent);
}
export function inheritLeadingComments(child: Object, parent: Object) {
_inheritComments("leadingComments", child, parent);
}
export function inheritInnerComments(child: Object, parent: Object) {
_inheritComments("innerComments", child, parent);
}
function _inheritComments(key, child, parent) {
if (child && parent) {
child[key] = uniq([].concat(child[key], parent[key]).filter(Boolean));
}
}
/**
* Inherit all contextual properties from `parent` node to `child` node.
*/
export function inherits(child: Object, parent: Object): Object {
if (!child || !parent) return child;
// optionally inherit specific properties if not null
for (const key of (t.INHERIT_KEYS.optional: Array<string>)) {
if (child[key] == null) {
child[key] = parent[key];
}
}
// force inherit "private" properties
for (const key in parent) {
if (key[0] === "_" && key !== "__clone") child[key] = parent[key];
}
// force inherit select properties
for (const key of (t.INHERIT_KEYS.force: Array<string>)) {
child[key] = parent[key];
}
t.inheritsComments(child, parent);
return child;
}
/**
* TODO
*/
export function assertNode(node?) {
if (!isNode(node)) {
// $FlowFixMe
throw new TypeError("Not a valid node " + (node && node.type));
}
}
/**
* TODO
*/
export function isNode(node?): boolean {
return !!(node && VISITOR_KEYS[node.type]);
}
// Optimize property access.
toFastProperties(t);
toFastProperties(t.VISITOR_KEYS);
const CLEAR_KEYS: Array = ["tokens", "start", "end", "loc", "raw", "rawValue"];
const CLEAR_KEYS_PLUS_COMMENTS: Array = t.COMMENT_KEYS
.concat(["comments"])
.concat(CLEAR_KEYS);
/**
* Remove all of the _* properties from a node along with the additional metadata
* properties like location data and raw token data.
*/
export function removeProperties(node: Node, opts?: Object): void {
opts = opts || {};
const map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS;
for (const key of map) {
if (node[key] != null) node[key] = undefined;
}
for (const key in node) {
if (key[0] === "_" && node[key] != null) node[key] = undefined;
}
const syms: Array<Symbol> = Object.getOwnPropertySymbols(node);
for (const sym of syms) {
node[sym] = null;
}
}
export function removePropertiesDeep(tree: Node, opts?: Object): Node {
traverseFast(tree, removeProperties, opts);
return tree;
}
//
default as createTypeAnnotationBasedOnTypeof,
} from "./builders/flow/createTypeAnnotationBasedOnTypeof";
export {
getBindingIdentifiers,
getOuterBindingIdentifiers,
} from "./retrievers";
default as createUnionTypeAnnotation,
} from "./builders/flow/createUnionTypeAnnotation";
export * from "./builders/generated";
export {
isBinding,
isReferenced,
isValidIdentifier,
isValidES3Identifier,
isLet,
isBlockScoped,
isVar,
isSpecifierDefault,
isScope,
isImmutable,
isNodesEquivalent,
} from "./validators";
// clone
export { default as clone } from "./clone/clone";
export { default as cloneDeep } from "./clone/cloneDeep";
export { default as cloneWithoutLoc } from "./clone/cloneWithoutLoc";
// comments
export { default as addComment } from "./comments/addComment";
export { default as addComments } from "./comments/addComments";
export {
toComputedKey,
toSequenceExpression,
toKeyAlias,
toIdentifier,
toBindingIdentifierName,
toStatement,
toExpression,
toBlock,
valueToNode,
} from "./converters";
default as inheritInnerComments,
} from "./comments/inheritInnerComments";
export {
default as inheritLeadingComments,
} from "./comments/inheritLeadingComments";
export { default as inheritsComments } from "./comments/inheritsComments";
export {
default as inheritTrailingComments,
} from "./comments/inheritTrailingComments";
export { default as removeComments } from "./comments/removeComments";
// constants
export * from "./constants/generated";
export * from "./constants";
// converters
export { default as ensureBlock } from "./converters/ensureBlock";
export {
createUnionTypeAnnotation,
removeTypeDuplicates,
createTypeAnnotationBasedOnTypeof,
} from "./flow";
default as toBindingIdentifierName,
} from "./converters/toBindingIdentifierName";
export { default as toBlock } from "./converters/toBlock";
export { default as toComputedKey } from "./converters/toComputedKey";
export { default as toExpression } from "./converters/toExpression";
export { default as toIdentifier } from "./converters/toIdentifier";
export { default as toKeyAlias } from "./converters/toKeyAlias";
export {
default as toSequenceExpression,
} from "./converters/toSequenceExpression";
export { default as toStatement } from "./converters/toStatement";
export { default as valueToNode } from "./converters/valueToNode";
// definitions
export * from "./definitions";
// modifications
export {
default as appendToMemberExpression,
} from "./modifications/appendToMemberExpression";
export { default as inherits } from "./modifications/inherits";
export {
default as prependToMemberExpression,
} from "./modifications/prependToMemberExpression";
export { default as removeProperties } from "./modifications/removeProperties";
export {
default as removePropertiesDeep,
} from "./modifications/removePropertiesDeep";
export {
default as removeTypeDuplicates,
} from "./modifications/flow/removeTypeDuplicates";
// retrievers
export {
default as getBindingIdentifiers,
} from "./retrievers/getBindingIdentifiers";
export {
default as getOuterBindingIdentifiers,
} from "./retrievers/getOuterBindingIdentifiers";
// traverse
export { default as traverse } from "./traverse/traverse";
export type * from "./traverse/traverse";
export { default as traverseFast } from "./traverse/traverseFast";
// utils
export { default as shallowEqual } from "./utils/shallowEqual";
// validators
export { default as is } from "./validators/is";
export { default as isBinding } from "./validators/isBinding";
export { default as isBlockScoped } from "./validators/isBlockScoped";
export { default as isImmutable } from "./validators/isImmutable";
export { default as isLet } from "./validators/isLet";
export { default as isNode } from "./validators/isNode";
export { default as isNodesEquivalent } from "./validators/isNodesEquivalent";
export { default as isReferenced } from "./validators/isReferenced";
export { default as isScope } from "./validators/isScope";
export { default as isSpecifierDefault } from "./validators/isSpecifierDefault";
export { default as isType } from "./validators/isType";
export {
default as isValidES3Identifier,
} from "./validators/isValidES3Identifier";
export { default as isValidIdentifier } from "./validators/isValidIdentifier";
export { default as isVar } from "./validators/isVar";
export { default as matchesPattern } from "./validators/matchesPattern";
export { default as validate } from "./validators/validate";
export {
default as buildMatchMemberExpression,
} from "./validators/buildMatchMemberExpression";
export * from "./validators/generated";
// react
export const react = {
isReactComponent,
isCompatTag,
buildChildren,
};

View File

@ -0,0 +1,21 @@
// @flow
import { memberExpression } from "../builders/generated";
/**
* Append a node to a member expression.
*/
export default function appendToMemberExpression<T: Object>(
member: T,
append: Object,
computed?: boolean = false,
): T {
member.object = memberExpression(
member.object,
member.property,
member.computed,
);
member.property = append;
member.computed = !!computed;
return member;
}

View File

@ -1,25 +1,17 @@
import * as t from "./index";
/**
* Takes an array of `types` and flattens them, removing duplicates and
* returns a `UnionTypeAnnotation` node containg them.
*/
export function createUnionTypeAnnotation(types: Array<Object>) {
const flattened = removeTypeDuplicates(types);
if (flattened.length === 1) {
return flattened[0];
} else {
return t.unionTypeAnnotation(flattened);
}
}
// @flow
import {
isAnyTypeAnnotation,
isGenericTypeAnnotation,
isUnionTypeAnnotation,
isFlowBaseAnnotation,
} from "../../validators/generated";
/**
* Dedupe type annotations.
*/
export function removeTypeDuplicates(nodes: Array<Object>): Array<Object> {
export default function removeTypeDuplicates(
nodes: Array<Object>,
): Array<Object> {
const generics = {};
const bases = {};
@ -38,18 +30,16 @@ export function removeTypeDuplicates(nodes: Array<Object>): Array<Object> {
}
// this type matches anything
if (t.isAnyTypeAnnotation(node)) {
if (isAnyTypeAnnotation(node)) {
return [node];
}
//
if (t.isFlowBaseAnnotation(node)) {
if (isFlowBaseAnnotation(node)) {
bases[node.type] = node;
continue;
}
//
if (t.isUnionTypeAnnotation(node)) {
if (isUnionTypeAnnotation(node)) {
if (typeGroups.indexOf(node.types) < 0) {
nodes = nodes.concat(node.types);
typeGroups.push(node.types);
@ -58,7 +48,7 @@ export function removeTypeDuplicates(nodes: Array<Object>): Array<Object> {
}
// find a matching generic type and merge and deduplicate the type parameters
if (t.isGenericTypeAnnotation(node)) {
if (isGenericTypeAnnotation(node)) {
const name = node.id.name;
if (generics[name]) {
@ -94,27 +84,3 @@ export function removeTypeDuplicates(nodes: Array<Object>): Array<Object> {
return types;
}
/**
* Create a type anotation based on typeof expression.
*/
export function createTypeAnnotationBasedOnTypeof(type: string) {
if (type === "string") {
return t.stringTypeAnnotation();
} else if (type === "number") {
return t.numberTypeAnnotation();
} else if (type === "undefined") {
return t.voidTypeAnnotation();
} else if (type === "boolean") {
return t.booleanTypeAnnotation();
} else if (type === "function") {
return t.genericTypeAnnotation(t.identifier("Function"));
} else if (type === "object") {
return t.genericTypeAnnotation(t.identifier("Object"));
} else if (type === "symbol") {
return t.genericTypeAnnotation(t.identifier("Symbol"));
} else {
throw new Error("Invalid typeof value");
}
}

View File

@ -0,0 +1,31 @@
// @flow
import { INHERIT_KEYS } from "../constants";
import inheritsComments from "../comments/inheritsComments";
/**
* Inherit all contextual properties from `parent` node to `child` node.
*/
export default function inherits<T: Object>(child: T, parent: Object): T {
if (!child || !parent) return child;
// optionally inherit specific properties if not null
for (const key of (INHERIT_KEYS.optional: Array<string>)) {
if (child[key] == null) {
child[key] = parent[key];
}
}
// force inherit "private" properties
for (const key in parent) {
if (key[0] === "_" && key !== "__clone") child[key] = parent[key];
}
// force inherit select properties
for (const key of (INHERIT_KEYS.force: Array<string>)) {
child[key] = parent[key];
}
inheritsComments(child, parent);
return child;
}

View File

@ -0,0 +1,14 @@
// @flow
import { memberExpression } from "../builders/generated";
/**
* Prepend a node to a member expression.
*/
export default function prependToMemberExpression<T: Object>(
member: T,
prepend: Object,
): T {
member.object = memberExpression(prepend, member.object);
return member;
}

View File

@ -0,0 +1,31 @@
// @flow
import { COMMENT_KEYS } from "../constants";
const CLEAR_KEYS = ["tokens", "start", "end", "loc", "raw", "rawValue"];
const CLEAR_KEYS_PLUS_COMMENTS = COMMENT_KEYS.concat(["comments"]).concat(
CLEAR_KEYS,
);
/**
* Remove all of the _* properties from a node along with the additional metadata
* properties like location data and raw token data.
*/
export default function removeProperties(
node: Object,
opts?: Object = {},
): void {
const map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS;
for (const key of map) {
if (node[key] != null) node[key] = undefined;
}
for (const key in node) {
if (key[0] === "_" && node[key] != null) node[key] = undefined;
}
const symbols: Array<Symbol> = Object.getOwnPropertySymbols(node);
for (const sym of symbols) {
node[sym] = null;
}
}

View File

@ -0,0 +1,12 @@
// @flow
import traverseFast from "../traverse/traverseFast";
import removeProperties from "./removeProperties";
export default function removePropertiesDeep<T: Object>(
tree: T,
opts?: Object,
): T {
traverseFast(tree, removeProperties, opts);
return tree;
}

View File

@ -1,14 +1,20 @@
import * as t from "./index";
// @flow
import {
isExportDeclaration,
isIdentifier,
isDeclaration,
isFunctionDeclaration,
isFunctionExpression,
} from "../validators/generated";
/**
* Return a list of binding identifiers associated with the input `node`.
*/
export function getBindingIdentifiers(
export default function getBindingIdentifiers(
node: Object,
duplicates?: boolean,
outerOnly?: boolean,
): Object {
): { [string]: Object | Array<Object> } {
let search = [].concat(node);
const ids = Object.create(null);
@ -16,9 +22,9 @@ export function getBindingIdentifiers(
const id = search.shift();
if (!id) continue;
const keys = t.getBindingIdentifiers.keys[id.type];
const keys = getBindingIdentifiers.keys[id.type];
if (t.isIdentifier(id)) {
if (isIdentifier(id)) {
if (duplicates) {
const _ids = (ids[id.name] = ids[id.name] || []);
_ids.push(id);
@ -28,20 +34,20 @@ export function getBindingIdentifiers(
continue;
}
if (t.isExportDeclaration(id)) {
if (t.isDeclaration(id.declaration)) {
if (isExportDeclaration(id)) {
if (isDeclaration(id.declaration)) {
search.push(id.declaration);
}
continue;
}
if (outerOnly) {
if (t.isFunctionDeclaration(id)) {
if (isFunctionDeclaration(id)) {
search.push(id.id);
continue;
}
if (t.isFunctionExpression(id)) {
if (isFunctionExpression(id)) {
continue;
}
}
@ -56,13 +62,13 @@ export function getBindingIdentifiers(
}
}
// $FlowIssue Object.create() seems broken
return ids;
}
/**
* Mapping of types to their identifier keys.
*/
getBindingIdentifiers.keys = {
DeclareClass: ["id"],
DeclareFunction: ["id"],
@ -107,10 +113,3 @@ getBindingIdentifiers.keys = {
VariableDeclaration: ["declarations"],
VariableDeclarator: ["id"],
};
export function getOuterBindingIdentifiers(
node: Object,
duplicates?: boolean,
): Object {
return getBindingIdentifiers(node, duplicates, true);
}

View File

@ -0,0 +1,9 @@
// @flow
import getBindingIdentifiers from "./getBindingIdentifiers";
export default function getOuterBindingIdentifiers(
node: Object,
duplicates?: boolean,
): { [string]: Object | Array<Object> } {
return getBindingIdentifiers(node, duplicates, true);
}

View File

@ -1,34 +1,5 @@
import { VISITOR_KEYS } from "./index";
/**
* A prefix AST traversal implementation meant for simple searching
* and processing.
*/
export function traverseFast(
node: Node,
enter: (node: Node) => void,
opts?: Object,
) {
if (!node) return;
const keys = VISITOR_KEYS[node.type];
if (!keys) return;
opts = opts || {};
enter(node, opts);
for (const key of keys) {
const subNode = node[key];
if (Array.isArray(subNode)) {
for (const node of subNode) {
traverseFast(node, enter, opts);
}
} else {
traverseFast(subNode, enter, opts);
}
}
}
// @flow
import { VISITOR_KEYS } from "../definitions";
export type TraversalAncestors = Array<{
node: BabelNode,
@ -46,20 +17,27 @@ export type TraversalHandlers<T> = {
* state object. Exposes ancestry data to each handler so that more complex
* AST data can be taken into account.
*/
export function traverse<T>(
export default function traverse<T>(
node: BabelNode,
handlers: TraversalHandler<T> | TraversalHandlers<T>,
state?: T,
) {
): void {
if (typeof handlers === "function") {
handlers = { enter: handlers };
}
const { enter, exit } = handlers;
const { enter, exit } = (handlers: TraversalHandlers<T>);
traverseSimpleImpl(node, enter, exit, state, []);
}
function traverseSimpleImpl(node, enter, exit, state, ancestors) {
function traverseSimpleImpl<T>(
node: Object,
enter: ?Function,
exit: ?Function,
state: ?T,
ancestors: TraversalAncestors,
) {
const keys = VISITOR_KEYS[node.type];
if (!keys) return;

View File

@ -0,0 +1,32 @@
// @flow
import { VISITOR_KEYS } from "../definitions";
/**
* A prefix AST traversal implementation meant for simple searching
* and processing.
*/
export default function traverseFast(
node: Object,
enter: (node: Node, opts?: Object) => void,
opts?: Object,
): void {
if (!node) return;
const keys = VISITOR_KEYS[node.type];
if (!keys) return;
opts = opts || {};
enter(node, opts);
for (const key of keys) {
const subNode = node[key];
if (Array.isArray(subNode)) {
for (const node of subNode) {
traverseFast(node, enter, opts);
}
} else {
traverseFast(subNode, enter, opts);
}
}
}

View File

@ -0,0 +1,12 @@
// @flow
import uniq from "lodash/uniq";
export default function inherit(
key: string,
child: Object,
parent: Object,
): void {
if (child && parent) {
child[key] = uniq([].concat(child[key], parent[key]).filter(Boolean));
}
}

View File

@ -1,12 +1,7 @@
import * as t from "./index";
// @flow
import { stringLiteral } from "../../builders/generated";
export const isReactComponent = t.buildMatchMemberExpression("React.Component");
export function isCompatTag(tagName?: string): boolean {
return !!tagName && /^[a-z]|-/.test(tagName);
}
function cleanJSXElementLiteralChild(
export default function cleanJSXElementLiteralChild(
child: { value: string },
args: Array<Object>,
) {
@ -51,25 +46,5 @@ function cleanJSXElementLiteralChild(
}
}
if (str) args.push(t.stringLiteral(str));
}
export function buildChildren(node: Object): Array<Object> {
const elems = [];
for (let i = 0; i < node.children.length; i++) {
let child = node.children[i];
if (t.isJSXText(child)) {
cleanJSXElementLiteralChild(child, elems);
continue;
}
if (t.isJSXExpressionContainer(child)) child = child.expression;
if (t.isJSXEmptyExpression(child)) continue;
elems.push(child);
}
return elems;
if (str) args.push(stringLiteral(str));
}

View File

@ -0,0 +1,15 @@
// @flow
export default function shallowEqual(
actual: Object,
expected: Object,
): boolean {
const keys = Object.keys(expected);
for (const key of (keys: Array<string>)) {
if (actual[key] !== expected[key]) {
return false;
}
}
return true;
}

View File

@ -1,316 +0,0 @@
import { getBindingIdentifiers } from "./retrievers";
import esutils from "esutils";
import * as t from "./index";
import { BLOCK_SCOPED_SYMBOL, RESERVED_WORDS_ES3_ONLY } from "./constants";
/**
* Check if the input `node` is a binding identifier.
*/
export function isBinding(node: Object, parent: Object): boolean {
const keys = getBindingIdentifiers.keys[parent.type];
if (keys) {
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const val = parent[key];
if (Array.isArray(val)) {
if (val.indexOf(node) >= 0) return true;
} else {
if (val === node) return true;
}
}
}
return false;
}
/**
* Check if the input `node` is a reference to a bound variable.
*/
export function isReferenced(node: Object, parent: Object): boolean {
switch (parent.type) {
// yes: object::NODE
// yes: NODE::callee
case "BindExpression":
return parent.object === node || parent.callee === node;
// yes: PARENT[NODE]
// yes: NODE.child
// no: parent.NODE
case "MemberExpression":
case "JSXMemberExpression":
if (parent.property === node && parent.computed) {
return true;
} else if (parent.object === node) {
return true;
} else {
return false;
}
// no: new.NODE
// no: NODE.target
case "MetaProperty":
return false;
// yes: { [NODE]: "" }
// yes: { NODE }
// no: { NODE: "" }
case "ObjectProperty":
if (parent.key === node) {
return parent.computed;
}
// no: let NODE = init;
// yes: let id = NODE;
case "VariableDeclarator":
return parent.id !== node;
// no: function NODE() {}
// no: function foo(NODE) {}
case "ArrowFunctionExpression":
case "FunctionDeclaration":
case "FunctionExpression":
for (const param of (parent.params: Array<any>)) {
if (param === node) return false;
}
return parent.id !== node;
// no: export { foo as NODE };
// yes: export { NODE as foo };
// no: export { NODE as foo } from "foo";
case "ExportSpecifier":
if (parent.source) {
return false;
} else {
return parent.local === node;
}
// no: export NODE from "foo";
// no: export * as NODE from "foo";
case "ExportNamespaceSpecifier":
case "ExportDefaultSpecifier":
return false;
// no: <div NODE="foo" />
case "JSXAttribute":
return parent.name !== node;
// no: class { NODE = value; }
// yes: class { [NODE] = value; }
// yes: class { key = NODE; }
case "ClassProperty":
if (parent.key === node) {
return parent.computed;
} else {
return parent.value === node;
}
// no: import NODE from "foo";
// no: import * as NODE from "foo";
// no: import { NODE as foo } from "foo";
// no: import { foo as NODE } from "foo";
// no: import NODE from "bar";
case "ImportDefaultSpecifier":
case "ImportNamespaceSpecifier":
case "ImportSpecifier":
return false;
// no: class NODE {}
case "ClassDeclaration":
case "ClassExpression":
return parent.id !== node;
// yes: class { [NODE]() {} }
case "ClassMethod":
case "ObjectMethod":
return parent.key === node && parent.computed;
// no: NODE: for (;;) {}
case "LabeledStatement":
return false;
// no: try {} catch (NODE) {}
case "CatchClause":
return parent.param !== node;
// no: function foo(...NODE) {}
case "RestElement":
return false;
// yes: left = NODE;
// no: NODE = right;
case "AssignmentExpression":
return parent.right === node;
// no: [NODE = foo] = [];
// yes: [foo = NODE] = [];
case "AssignmentPattern":
return parent.right === node;
// no: [NODE] = [];
// no: ({ NODE }) = [];
case "ObjectPattern":
case "ArrayPattern":
return false;
}
return true;
}
/**
* Check if the input `name` is a valid identifier name
* and isn't a reserved word.
*/
export function isValidIdentifier(name: string): boolean {
if (
typeof name !== "string" ||
esutils.keyword.isReservedWordES6(name, true)
) {
return false;
} else if (name === "await") {
// invalid in module, valid in script; better be safe (see #4952)
return false;
} else {
return esutils.keyword.isIdentifierNameES6(name);
}
}
/**
* Check if the input `name` is a valid identifier name according to the ES3 specification.
*
* Additional ES3 reserved words are
*/
export function isValidES3Identifier(name: string): boolean {
return isValidIdentifier(name, true) && !RESERVED_WORDS_ES3_ONLY.has(name);
}
/**
* Check if the input `node` is a `let` variable declaration.
*/
export function isLet(node: Object): boolean {
return (
t.isVariableDeclaration(node) &&
(node.kind !== "var" || node[BLOCK_SCOPED_SYMBOL])
);
}
/**
* Check if the input `node` is block scoped.
*/
export function isBlockScoped(node: Object): boolean {
return (
t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isLet(node)
);
}
/**
* Check if the input `node` is a variable declaration.
*/
export function isVar(node: Object): boolean {
return (
t.isVariableDeclaration(node, { kind: "var" }) && !node[BLOCK_SCOPED_SYMBOL]
);
}
/**
* Check if the input `specifier` is a `default` import or export.
*/
export function isSpecifierDefault(specifier: Object): boolean {
return (
t.isImportDefaultSpecifier(specifier) ||
t.isIdentifier(specifier.imported || specifier.exported, {
name: "default",
})
);
}
/**
* Check if the input `node` is a scope.
*/
export function isScope(node: Object, parent: Object): boolean {
if (t.isBlockStatement(node) && t.isFunction(parent, { body: node })) {
return false;
}
if (t.isBlockStatement(node) && t.isCatchClause(parent, { body: node })) {
return false;
}
return t.isScopable(node);
}
/**
* Check if the input `node` is definitely immutable.
*/
export function isImmutable(node: Object): boolean {
if (t.isType(node.type, "Immutable")) return true;
if (t.isIdentifier(node)) {
if (node.name === "undefined") {
// immutable!
return true;
} else {
// no idea...
return false;
}
}
return false;
}
/**
* Check if two nodes are equivalent
*/
export function isNodesEquivalent(a, b) {
if (
typeof a !== "object" ||
typeof b !== "object" ||
a == null ||
b == null
) {
return a === b;
}
if (a.type !== b.type) {
return false;
}
const fields = Object.keys(t.NODE_FIELDS[a.type] || a.type);
for (const field of fields) {
if (typeof a[field] !== typeof b[field]) {
return false;
}
if (Array.isArray(a[field])) {
if (!Array.isArray(b[field])) {
return false;
}
if (a[field].length !== b[field].length) {
return false;
}
for (let i = 0; i < a[field].length; i++) {
if (!isNodesEquivalent(a[field][i], b[field][i])) {
return false;
}
}
continue;
}
if (!isNodesEquivalent(a[field], b[field])) {
return false;
}
}
return true;
}

View File

@ -0,0 +1,18 @@
import matchesPattern from "./matchesPattern";
/**
* Build a function that when called will return whether or not the
* input `node` `MemberExpression` matches the input `match`.
*
* For example, given the match `React.createClass` it would match the
* parsed nodes of `React.createClass` and `React["createClass"]`.
*/
export default function buildMatchMemberExpression(
match: string,
allowPartial?: boolean,
): Object => boolean {
const parts = match.split(".");
return (member: Object): boolean =>
matchesPattern(member, parts, allowPartial);
}

View File

@ -0,0 +1,828 @@
// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import is from "../is";
export function isArrayExpression(node: Object, opts?: Object): boolean {
return is("ArrayExpression", node, opts);
}
export function isAssignmentExpression(node: Object, opts?: Object): boolean {
return is("AssignmentExpression", node, opts);
}
export function isBinaryExpression(node: Object, opts?: Object): boolean {
return is("BinaryExpression", node, opts);
}
export function isDirective(node: Object, opts?: Object): boolean {
return is("Directive", node, opts);
}
export function isDirectiveLiteral(node: Object, opts?: Object): boolean {
return is("DirectiveLiteral", node, opts);
}
export function isBlockStatement(node: Object, opts?: Object): boolean {
return is("BlockStatement", node, opts);
}
export function isBreakStatement(node: Object, opts?: Object): boolean {
return is("BreakStatement", node, opts);
}
export function isCallExpression(node: Object, opts?: Object): boolean {
return is("CallExpression", node, opts);
}
export function isCatchClause(node: Object, opts?: Object): boolean {
return is("CatchClause", node, opts);
}
export function isConditionalExpression(node: Object, opts?: Object): boolean {
return is("ConditionalExpression", node, opts);
}
export function isContinueStatement(node: Object, opts?: Object): boolean {
return is("ContinueStatement", node, opts);
}
export function isDebuggerStatement(node: Object, opts?: Object): boolean {
return is("DebuggerStatement", node, opts);
}
export function isDoWhileStatement(node: Object, opts?: Object): boolean {
return is("DoWhileStatement", node, opts);
}
export function isEmptyStatement(node: Object, opts?: Object): boolean {
return is("EmptyStatement", node, opts);
}
export function isExpressionStatement(node: Object, opts?: Object): boolean {
return is("ExpressionStatement", node, opts);
}
export function isFile(node: Object, opts?: Object): boolean {
return is("File", node, opts);
}
export function isForInStatement(node: Object, opts?: Object): boolean {
return is("ForInStatement", node, opts);
}
export function isForStatement(node: Object, opts?: Object): boolean {
return is("ForStatement", node, opts);
}
export function isFunctionDeclaration(node: Object, opts?: Object): boolean {
return is("FunctionDeclaration", node, opts);
}
export function isFunctionExpression(node: Object, opts?: Object): boolean {
return is("FunctionExpression", node, opts);
}
export function isIdentifier(node: Object, opts?: Object): boolean {
return is("Identifier", node, opts);
}
export function isIfStatement(node: Object, opts?: Object): boolean {
return is("IfStatement", node, opts);
}
export function isLabeledStatement(node: Object, opts?: Object): boolean {
return is("LabeledStatement", node, opts);
}
export function isStringLiteral(node: Object, opts?: Object): boolean {
return is("StringLiteral", node, opts);
}
export function isNumericLiteral(node: Object, opts?: Object): boolean {
return is("NumericLiteral", node, opts);
}
export function isNullLiteral(node: Object, opts?: Object): boolean {
return is("NullLiteral", node, opts);
}
export function isBooleanLiteral(node: Object, opts?: Object): boolean {
return is("BooleanLiteral", node, opts);
}
export function isRegExpLiteral(node: Object, opts?: Object): boolean {
return is("RegExpLiteral", node, opts);
}
export function isLogicalExpression(node: Object, opts?: Object): boolean {
return is("LogicalExpression", node, opts);
}
export function isMemberExpression(node: Object, opts?: Object): boolean {
return is("MemberExpression", node, opts);
}
export function isNewExpression(node: Object, opts?: Object): boolean {
return is("NewExpression", node, opts);
}
export function isProgram(node: Object, opts?: Object): boolean {
return is("Program", node, opts);
}
export function isObjectExpression(node: Object, opts?: Object): boolean {
return is("ObjectExpression", node, opts);
}
export function isObjectMethod(node: Object, opts?: Object): boolean {
return is("ObjectMethod", node, opts);
}
export function isObjectProperty(node: Object, opts?: Object): boolean {
return is("ObjectProperty", node, opts);
}
export function isRestElement(node: Object, opts?: Object): boolean {
return is("RestElement", node, opts);
}
export function isReturnStatement(node: Object, opts?: Object): boolean {
return is("ReturnStatement", node, opts);
}
export function isSequenceExpression(node: Object, opts?: Object): boolean {
return is("SequenceExpression", node, opts);
}
export function isSwitchCase(node: Object, opts?: Object): boolean {
return is("SwitchCase", node, opts);
}
export function isSwitchStatement(node: Object, opts?: Object): boolean {
return is("SwitchStatement", node, opts);
}
export function isThisExpression(node: Object, opts?: Object): boolean {
return is("ThisExpression", node, opts);
}
export function isThrowStatement(node: Object, opts?: Object): boolean {
return is("ThrowStatement", node, opts);
}
export function isTryStatement(node: Object, opts?: Object): boolean {
return is("TryStatement", node, opts);
}
export function isUnaryExpression(node: Object, opts?: Object): boolean {
return is("UnaryExpression", node, opts);
}
export function isUpdateExpression(node: Object, opts?: Object): boolean {
return is("UpdateExpression", node, opts);
}
export function isVariableDeclaration(node: Object, opts?: Object): boolean {
return is("VariableDeclaration", node, opts);
}
export function isVariableDeclarator(node: Object, opts?: Object): boolean {
return is("VariableDeclarator", node, opts);
}
export function isWhileStatement(node: Object, opts?: Object): boolean {
return is("WhileStatement", node, opts);
}
export function isWithStatement(node: Object, opts?: Object): boolean {
return is("WithStatement", node, opts);
}
export function isAssignmentPattern(node: Object, opts?: Object): boolean {
return is("AssignmentPattern", node, opts);
}
export function isArrayPattern(node: Object, opts?: Object): boolean {
return is("ArrayPattern", node, opts);
}
export function isArrowFunctionExpression(
node: Object,
opts?: Object,
): boolean {
return is("ArrowFunctionExpression", node, opts);
}
export function isClassBody(node: Object, opts?: Object): boolean {
return is("ClassBody", node, opts);
}
export function isClassDeclaration(node: Object, opts?: Object): boolean {
return is("ClassDeclaration", node, opts);
}
export function isClassExpression(node: Object, opts?: Object): boolean {
return is("ClassExpression", node, opts);
}
export function isExportAllDeclaration(node: Object, opts?: Object): boolean {
return is("ExportAllDeclaration", node, opts);
}
export function isExportDefaultDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("ExportDefaultDeclaration", node, opts);
}
export function isExportNamedDeclaration(node: Object, opts?: Object): boolean {
return is("ExportNamedDeclaration", node, opts);
}
export function isExportSpecifier(node: Object, opts?: Object): boolean {
return is("ExportSpecifier", node, opts);
}
export function isForOfStatement(node: Object, opts?: Object): boolean {
return is("ForOfStatement", node, opts);
}
export function isImportDeclaration(node: Object, opts?: Object): boolean {
return is("ImportDeclaration", node, opts);
}
export function isImportDefaultSpecifier(node: Object, opts?: Object): boolean {
return is("ImportDefaultSpecifier", node, opts);
}
export function isImportNamespaceSpecifier(
node: Object,
opts?: Object,
): boolean {
return is("ImportNamespaceSpecifier", node, opts);
}
export function isImportSpecifier(node: Object, opts?: Object): boolean {
return is("ImportSpecifier", node, opts);
}
export function isMetaProperty(node: Object, opts?: Object): boolean {
return is("MetaProperty", node, opts);
}
export function isClassMethod(node: Object, opts?: Object): boolean {
return is("ClassMethod", node, opts);
}
export function isObjectPattern(node: Object, opts?: Object): boolean {
return is("ObjectPattern", node, opts);
}
export function isSpreadElement(node: Object, opts?: Object): boolean {
return is("SpreadElement", node, opts);
}
export function isSuper(node: Object, opts?: Object): boolean {
return is("Super", node, opts);
}
export function isTaggedTemplateExpression(
node: Object,
opts?: Object,
): boolean {
return is("TaggedTemplateExpression", node, opts);
}
export function isTemplateElement(node: Object, opts?: Object): boolean {
return is("TemplateElement", node, opts);
}
export function isTemplateLiteral(node: Object, opts?: Object): boolean {
return is("TemplateLiteral", node, opts);
}
export function isYieldExpression(node: Object, opts?: Object): boolean {
return is("YieldExpression", node, opts);
}
export function isAnyTypeAnnotation(node: Object, opts?: Object): boolean {
return is("AnyTypeAnnotation", node, opts);
}
export function isArrayTypeAnnotation(node: Object, opts?: Object): boolean {
return is("ArrayTypeAnnotation", node, opts);
}
export function isBooleanTypeAnnotation(node: Object, opts?: Object): boolean {
return is("BooleanTypeAnnotation", node, opts);
}
export function isBooleanLiteralTypeAnnotation(
node: Object,
opts?: Object,
): boolean {
return is("BooleanLiteralTypeAnnotation", node, opts);
}
export function isNullLiteralTypeAnnotation(
node: Object,
opts?: Object,
): boolean {
return is("NullLiteralTypeAnnotation", node, opts);
}
export function isClassImplements(node: Object, opts?: Object): boolean {
return is("ClassImplements", node, opts);
}
export function isDeclareClass(node: Object, opts?: Object): boolean {
return is("DeclareClass", node, opts);
}
export function isDeclareFunction(node: Object, opts?: Object): boolean {
return is("DeclareFunction", node, opts);
}
export function isDeclareInterface(node: Object, opts?: Object): boolean {
return is("DeclareInterface", node, opts);
}
export function isDeclareModule(node: Object, opts?: Object): boolean {
return is("DeclareModule", node, opts);
}
export function isDeclareModuleExports(node: Object, opts?: Object): boolean {
return is("DeclareModuleExports", node, opts);
}
export function isDeclareTypeAlias(node: Object, opts?: Object): boolean {
return is("DeclareTypeAlias", node, opts);
}
export function isDeclareOpaqueType(node: Object, opts?: Object): boolean {
return is("DeclareOpaqueType", node, opts);
}
export function isDeclareVariable(node: Object, opts?: Object): boolean {
return is("DeclareVariable", node, opts);
}
export function isDeclareExportDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("DeclareExportDeclaration", node, opts);
}
export function isDeclareExportAllDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("DeclareExportAllDeclaration", node, opts);
}
export function isDeclaredPredicate(node: Object, opts?: Object): boolean {
return is("DeclaredPredicate", node, opts);
}
export function isExistsTypeAnnotation(node: Object, opts?: Object): boolean {
return is("ExistsTypeAnnotation", node, opts);
}
export function isFunctionTypeAnnotation(node: Object, opts?: Object): boolean {
return is("FunctionTypeAnnotation", node, opts);
}
export function isFunctionTypeParam(node: Object, opts?: Object): boolean {
return is("FunctionTypeParam", node, opts);
}
export function isGenericTypeAnnotation(node: Object, opts?: Object): boolean {
return is("GenericTypeAnnotation", node, opts);
}
export function isInferredPredicate(node: Object, opts?: Object): boolean {
return is("InferredPredicate", node, opts);
}
export function isInterfaceExtends(node: Object, opts?: Object): boolean {
return is("InterfaceExtends", node, opts);
}
export function isInterfaceDeclaration(node: Object, opts?: Object): boolean {
return is("InterfaceDeclaration", node, opts);
}
export function isIntersectionTypeAnnotation(
node: Object,
opts?: Object,
): boolean {
return is("IntersectionTypeAnnotation", node, opts);
}
export function isMixedTypeAnnotation(node: Object, opts?: Object): boolean {
return is("MixedTypeAnnotation", node, opts);
}
export function isEmptyTypeAnnotation(node: Object, opts?: Object): boolean {
return is("EmptyTypeAnnotation", node, opts);
}
export function isNullableTypeAnnotation(node: Object, opts?: Object): boolean {
return is("NullableTypeAnnotation", node, opts);
}
export function isNumberLiteralTypeAnnotation(
node: Object,
opts?: Object,
): boolean {
return is("NumberLiteralTypeAnnotation", node, opts);
}
export function isNumberTypeAnnotation(node: Object, opts?: Object): boolean {
return is("NumberTypeAnnotation", node, opts);
}
export function isObjectTypeAnnotation(node: Object, opts?: Object): boolean {
return is("ObjectTypeAnnotation", node, opts);
}
export function isObjectTypeCallProperty(node: Object, opts?: Object): boolean {
return is("ObjectTypeCallProperty", node, opts);
}
export function isObjectTypeIndexer(node: Object, opts?: Object): boolean {
return is("ObjectTypeIndexer", node, opts);
}
export function isObjectTypeProperty(node: Object, opts?: Object): boolean {
return is("ObjectTypeProperty", node, opts);
}
export function isObjectTypeSpreadProperty(
node: Object,
opts?: Object,
): boolean {
return is("ObjectTypeSpreadProperty", node, opts);
}
export function isOpaqueType(node: Object, opts?: Object): boolean {
return is("OpaqueType", node, opts);
}
export function isQualifiedTypeIdentifier(
node: Object,
opts?: Object,
): boolean {
return is("QualifiedTypeIdentifier", node, opts);
}
export function isStringLiteralTypeAnnotation(
node: Object,
opts?: Object,
): boolean {
return is("StringLiteralTypeAnnotation", node, opts);
}
export function isStringTypeAnnotation(node: Object, opts?: Object): boolean {
return is("StringTypeAnnotation", node, opts);
}
export function isThisTypeAnnotation(node: Object, opts?: Object): boolean {
return is("ThisTypeAnnotation", node, opts);
}
export function isTupleTypeAnnotation(node: Object, opts?: Object): boolean {
return is("TupleTypeAnnotation", node, opts);
}
export function isTypeofTypeAnnotation(node: Object, opts?: Object): boolean {
return is("TypeofTypeAnnotation", node, opts);
}
export function isTypeAlias(node: Object, opts?: Object): boolean {
return is("TypeAlias", node, opts);
}
export function isTypeAnnotation(node: Object, opts?: Object): boolean {
return is("TypeAnnotation", node, opts);
}
export function isTypeCastExpression(node: Object, opts?: Object): boolean {
return is("TypeCastExpression", node, opts);
}
export function isTypeParameter(node: Object, opts?: Object): boolean {
return is("TypeParameter", node, opts);
}
export function isTypeParameterDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("TypeParameterDeclaration", node, opts);
}
export function isTypeParameterInstantiation(
node: Object,
opts?: Object,
): boolean {
return is("TypeParameterInstantiation", node, opts);
}
export function isUnionTypeAnnotation(node: Object, opts?: Object): boolean {
return is("UnionTypeAnnotation", node, opts);
}
export function isVoidTypeAnnotation(node: Object, opts?: Object): boolean {
return is("VoidTypeAnnotation", node, opts);
}
export function isJSXAttribute(node: Object, opts?: Object): boolean {
return is("JSXAttribute", node, opts);
}
export function isJSXClosingElement(node: Object, opts?: Object): boolean {
return is("JSXClosingElement", node, opts);
}
export function isJSXElement(node: Object, opts?: Object): boolean {
return is("JSXElement", node, opts);
}
export function isJSXEmptyExpression(node: Object, opts?: Object): boolean {
return is("JSXEmptyExpression", node, opts);
}
export function isJSXExpressionContainer(node: Object, opts?: Object): boolean {
return is("JSXExpressionContainer", node, opts);
}
export function isJSXSpreadChild(node: Object, opts?: Object): boolean {
return is("JSXSpreadChild", node, opts);
}
export function isJSXIdentifier(node: Object, opts?: Object): boolean {
return is("JSXIdentifier", node, opts);
}
export function isJSXMemberExpression(node: Object, opts?: Object): boolean {
return is("JSXMemberExpression", node, opts);
}
export function isJSXNamespacedName(node: Object, opts?: Object): boolean {
return is("JSXNamespacedName", node, opts);
}
export function isJSXOpeningElement(node: Object, opts?: Object): boolean {
return is("JSXOpeningElement", node, opts);
}
export function isJSXSpreadAttribute(node: Object, opts?: Object): boolean {
return is("JSXSpreadAttribute", node, opts);
}
export function isJSXText(node: Object, opts?: Object): boolean {
return is("JSXText", node, opts);
}
export function isJSXFragment(node: Object, opts?: Object): boolean {
return is("JSXFragment", node, opts);
}
export function isJSXOpeningFragment(node: Object, opts?: Object): boolean {
return is("JSXOpeningFragment", node, opts);
}
export function isJSXClosingFragment(node: Object, opts?: Object): boolean {
return is("JSXClosingFragment", node, opts);
}
export function isNoop(node: Object, opts?: Object): boolean {
return is("Noop", node, opts);
}
export function isParenthesizedExpression(
node: Object,
opts?: Object,
): boolean {
return is("ParenthesizedExpression", node, opts);
}
export function isAwaitExpression(node: Object, opts?: Object): boolean {
return is("AwaitExpression", node, opts);
}
export function isBindExpression(node: Object, opts?: Object): boolean {
return is("BindExpression", node, opts);
}
export function isClassProperty(node: Object, opts?: Object): boolean {
return is("ClassProperty", node, opts);
}
export function isImport(node: Object, opts?: Object): boolean {
return is("Import", node, opts);
}
export function isDecorator(node: Object, opts?: Object): boolean {
return is("Decorator", node, opts);
}
export function isDoExpression(node: Object, opts?: Object): boolean {
return is("DoExpression", node, opts);
}
export function isExportDefaultSpecifier(node: Object, opts?: Object): boolean {
return is("ExportDefaultSpecifier", node, opts);
}
export function isExportNamespaceSpecifier(
node: Object,
opts?: Object,
): boolean {
return is("ExportNamespaceSpecifier", node, opts);
}
export function isTSParameterProperty(node: Object, opts?: Object): boolean {
return is("TSParameterProperty", node, opts);
}
export function isTSDeclareFunction(node: Object, opts?: Object): boolean {
return is("TSDeclareFunction", node, opts);
}
export function isTSDeclareMethod(node: Object, opts?: Object): boolean {
return is("TSDeclareMethod", node, opts);
}
export function isTSQualifiedName(node: Object, opts?: Object): boolean {
return is("TSQualifiedName", node, opts);
}
export function isTSCallSignatureDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("TSCallSignatureDeclaration", node, opts);
}
export function isTSConstructSignatureDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("TSConstructSignatureDeclaration", node, opts);
}
export function isTSPropertySignature(node: Object, opts?: Object): boolean {
return is("TSPropertySignature", node, opts);
}
export function isTSMethodSignature(node: Object, opts?: Object): boolean {
return is("TSMethodSignature", node, opts);
}
export function isTSIndexSignature(node: Object, opts?: Object): boolean {
return is("TSIndexSignature", node, opts);
}
export function isTSAnyKeyword(node: Object, opts?: Object): boolean {
return is("TSAnyKeyword", node, opts);
}
export function isTSNumberKeyword(node: Object, opts?: Object): boolean {
return is("TSNumberKeyword", node, opts);
}
export function isTSObjectKeyword(node: Object, opts?: Object): boolean {
return is("TSObjectKeyword", node, opts);
}
export function isTSBooleanKeyword(node: Object, opts?: Object): boolean {
return is("TSBooleanKeyword", node, opts);
}
export function isTSStringKeyword(node: Object, opts?: Object): boolean {
return is("TSStringKeyword", node, opts);
}
export function isTSSymbolKeyword(node: Object, opts?: Object): boolean {
return is("TSSymbolKeyword", node, opts);
}
export function isTSVoidKeyword(node: Object, opts?: Object): boolean {
return is("TSVoidKeyword", node, opts);
}
export function isTSUndefinedKeyword(node: Object, opts?: Object): boolean {
return is("TSUndefinedKeyword", node, opts);
}
export function isTSNullKeyword(node: Object, opts?: Object): boolean {
return is("TSNullKeyword", node, opts);
}
export function isTSNeverKeyword(node: Object, opts?: Object): boolean {
return is("TSNeverKeyword", node, opts);
}
export function isTSThisType(node: Object, opts?: Object): boolean {
return is("TSThisType", node, opts);
}
export function isTSFunctionType(node: Object, opts?: Object): boolean {
return is("TSFunctionType", node, opts);
}
export function isTSConstructorType(node: Object, opts?: Object): boolean {
return is("TSConstructorType", node, opts);
}
export function isTSTypeReference(node: Object, opts?: Object): boolean {
return is("TSTypeReference", node, opts);
}
export function isTSTypePredicate(node: Object, opts?: Object): boolean {
return is("TSTypePredicate", node, opts);
}
export function isTSTypeQuery(node: Object, opts?: Object): boolean {
return is("TSTypeQuery", node, opts);
}
export function isTSTypeLiteral(node: Object, opts?: Object): boolean {
return is("TSTypeLiteral", node, opts);
}
export function isTSArrayType(node: Object, opts?: Object): boolean {
return is("TSArrayType", node, opts);
}
export function isTSTupleType(node: Object, opts?: Object): boolean {
return is("TSTupleType", node, opts);
}
export function isTSUnionType(node: Object, opts?: Object): boolean {
return is("TSUnionType", node, opts);
}
export function isTSIntersectionType(node: Object, opts?: Object): boolean {
return is("TSIntersectionType", node, opts);
}
export function isTSParenthesizedType(node: Object, opts?: Object): boolean {
return is("TSParenthesizedType", node, opts);
}
export function isTSTypeOperator(node: Object, opts?: Object): boolean {
return is("TSTypeOperator", node, opts);
}
export function isTSIndexedAccessType(node: Object, opts?: Object): boolean {
return is("TSIndexedAccessType", node, opts);
}
export function isTSMappedType(node: Object, opts?: Object): boolean {
return is("TSMappedType", node, opts);
}
export function isTSLiteralType(node: Object, opts?: Object): boolean {
return is("TSLiteralType", node, opts);
}
export function isTSExpressionWithTypeArguments(
node: Object,
opts?: Object,
): boolean {
return is("TSExpressionWithTypeArguments", node, opts);
}
export function isTSInterfaceDeclaration(node: Object, opts?: Object): boolean {
return is("TSInterfaceDeclaration", node, opts);
}
export function isTSInterfaceBody(node: Object, opts?: Object): boolean {
return is("TSInterfaceBody", node, opts);
}
export function isTSTypeAliasDeclaration(node: Object, opts?: Object): boolean {
return is("TSTypeAliasDeclaration", node, opts);
}
export function isTSAsExpression(node: Object, opts?: Object): boolean {
return is("TSAsExpression", node, opts);
}
export function isTSTypeAssertion(node: Object, opts?: Object): boolean {
return is("TSTypeAssertion", node, opts);
}
export function isTSEnumDeclaration(node: Object, opts?: Object): boolean {
return is("TSEnumDeclaration", node, opts);
}
export function isTSEnumMember(node: Object, opts?: Object): boolean {
return is("TSEnumMember", node, opts);
}
export function isTSModuleDeclaration(node: Object, opts?: Object): boolean {
return is("TSModuleDeclaration", node, opts);
}
export function isTSModuleBlock(node: Object, opts?: Object): boolean {
return is("TSModuleBlock", node, opts);
}
export function isTSImportEqualsDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("TSImportEqualsDeclaration", node, opts);
}
export function isTSExternalModuleReference(
node: Object,
opts?: Object,
): boolean {
return is("TSExternalModuleReference", node, opts);
}
export function isTSNonNullExpression(node: Object, opts?: Object): boolean {
return is("TSNonNullExpression", node, opts);
}
export function isTSExportAssignment(node: Object, opts?: Object): boolean {
return is("TSExportAssignment", node, opts);
}
export function isTSNamespaceExportDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("TSNamespaceExportDeclaration", node, opts);
}
export function isTSTypeAnnotation(node: Object, opts?: Object): boolean {
return is("TSTypeAnnotation", node, opts);
}
export function isTSTypeParameterInstantiation(
node: Object,
opts?: Object,
): boolean {
return is("TSTypeParameterInstantiation", node, opts);
}
export function isTSTypeParameterDeclaration(
node: Object,
opts?: Object,
): boolean {
return is("TSTypeParameterDeclaration", node, opts);
}
export function isTSTypeParameter(node: Object, opts?: Object): boolean {
return is("TSTypeParameter", node, opts);
}
export function isExpression(node: Object, opts?: Object): boolean {
return is("Expression", node, opts);
}
export function isBinary(node: Object, opts?: Object): boolean {
return is("Binary", node, opts);
}
export function isScopable(node: Object, opts?: Object): boolean {
return is("Scopable", node, opts);
}
export function isBlockParent(node: Object, opts?: Object): boolean {
return is("BlockParent", node, opts);
}
export function isBlock(node: Object, opts?: Object): boolean {
return is("Block", node, opts);
}
export function isStatement(node: Object, opts?: Object): boolean {
return is("Statement", node, opts);
}
export function isTerminatorless(node: Object, opts?: Object): boolean {
return is("Terminatorless", node, opts);
}
export function isCompletionStatement(node: Object, opts?: Object): boolean {
return is("CompletionStatement", node, opts);
}
export function isConditional(node: Object, opts?: Object): boolean {
return is("Conditional", node, opts);
}
export function isLoop(node: Object, opts?: Object): boolean {
return is("Loop", node, opts);
}
export function isWhile(node: Object, opts?: Object): boolean {
return is("While", node, opts);
}
export function isExpressionWrapper(node: Object, opts?: Object): boolean {
return is("ExpressionWrapper", node, opts);
}
export function isFor(node: Object, opts?: Object): boolean {
return is("For", node, opts);
}
export function isForXStatement(node: Object, opts?: Object): boolean {
return is("ForXStatement", node, opts);
}
export function isFunction(node: Object, opts?: Object): boolean {
return is("Function", node, opts);
}
export function isFunctionParent(node: Object, opts?: Object): boolean {
return is("FunctionParent", node, opts);
}
export function isPureish(node: Object, opts?: Object): boolean {
return is("Pureish", node, opts);
}
export function isDeclaration(node: Object, opts?: Object): boolean {
return is("Declaration", node, opts);
}
export function isPatternLike(node: Object, opts?: Object): boolean {
return is("PatternLike", node, opts);
}
export function isLVal(node: Object, opts?: Object): boolean {
return is("LVal", node, opts);
}
export function isTSEntityName(node: Object, opts?: Object): boolean {
return is("TSEntityName", node, opts);
}
export function isLiteral(node: Object, opts?: Object): boolean {
return is("Literal", node, opts);
}
export function isImmutable(node: Object, opts?: Object): boolean {
return is("Immutable", node, opts);
}
export function isUserWhitespacable(node: Object, opts?: Object): boolean {
return is("UserWhitespacable", node, opts);
}
export function isMethod(node: Object, opts?: Object): boolean {
return is("Method", node, opts);
}
export function isObjectMember(node: Object, opts?: Object): boolean {
return is("ObjectMember", node, opts);
}
export function isProperty(node: Object, opts?: Object): boolean {
return is("Property", node, opts);
}
export function isUnaryLike(node: Object, opts?: Object): boolean {
return is("UnaryLike", node, opts);
}
export function isPattern(node: Object, opts?: Object): boolean {
return is("Pattern", node, opts);
}
export function isClass(node: Object, opts?: Object): boolean {
return is("Class", node, opts);
}
export function isModuleDeclaration(node: Object, opts?: Object): boolean {
return is("ModuleDeclaration", node, opts);
}
export function isExportDeclaration(node: Object, opts?: Object): boolean {
return is("ExportDeclaration", node, opts);
}
export function isModuleSpecifier(node: Object, opts?: Object): boolean {
return is("ModuleSpecifier", node, opts);
}
export function isFlow(node: Object, opts?: Object): boolean {
return is("Flow", node, opts);
}
export function isFlowBaseAnnotation(node: Object, opts?: Object): boolean {
return is("FlowBaseAnnotation", node, opts);
}
export function isFlowDeclaration(node: Object, opts?: Object): boolean {
return is("FlowDeclaration", node, opts);
}
export function isFlowPredicate(node: Object, opts?: Object): boolean {
return is("FlowPredicate", node, opts);
}
export function isJSX(node: Object, opts?: Object): boolean {
return is("JSX", node, opts);
}
export function isTSTypeElement(node: Object, opts?: Object): boolean {
return is("TSTypeElement", node, opts);
}
export function isTSType(node: Object, opts?: Object): boolean {
return is("TSType", node, opts);
}
export function isNumberLiteral(node: Object, opts: Object): boolean {
console.trace(
"The node type NumberLiteral has been renamed to NumericLiteral",
);
return is("NumberLiteral", node, opts);
}
export function isRegexLiteral(node: Object, opts: Object): boolean {
console.trace("The node type RegexLiteral has been renamed to RegExpLiteral");
return is("RegexLiteral", node, opts);
}
export function isRestProperty(node: Object, opts: Object): boolean {
console.trace("The node type RestProperty has been renamed to RestElement");
return is("RestProperty", node, opts);
}
export function isSpreadProperty(node: Object, opts: Object): boolean {
console.trace(
"The node type SpreadProperty has been renamed to SpreadElement",
);
return is("SpreadProperty", node, opts);
}

View File

@ -0,0 +1,22 @@
// @flow
import shallowEqual from "../utils/shallowEqual";
import isType from "./isType";
/**
* Returns whether `node` is of given `type`.
*
* For better performance, use this instead of `is[Type]` when `type` is unknown.
* Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`.
*/
export default function is(type: string, node: Object, opts?: Object): boolean {
if (!node) return false;
const matches = isType(node.type, type);
if (!matches) return false;
if (typeof opts === "undefined") {
return true;
} else {
return shallowEqual(node, opts);
}
}

View File

@ -0,0 +1,21 @@
// @flow
import getBindingIdentifiers from "../retrievers/getBindingIdentifiers";
/**
* Check if the input `node` is a binding identifier.
*/
export default function isBinding(node: Object, parent: Object): boolean {
const keys = getBindingIdentifiers.keys[parent.type];
if (keys) {
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const val = parent[key];
if (Array.isArray(val)) {
if (val.indexOf(node) >= 0) return true;
} else {
if (val === node) return true;
}
}
}
return false;
}

View File

@ -0,0 +1,10 @@
// @flow
import { isClassDeclaration, isFunctionDeclaration } from "./generated";
import isLet from "./isLet";
/**
* Check if the input `node` is block scoped.
*/
export default function isBlockScoped(node: Object): boolean {
return isFunctionDeclaration(node) || isClassDeclaration(node) || isLet(node);
}

View File

@ -0,0 +1,22 @@
// @flow
import isType from "./isType";
import { isIdentifier } from "./generated";
/**
* Check if the input `node` is definitely immutable.
*/
export default function isImmutable(node: Object): boolean {
if (isType(node.type, "Immutable")) return true;
if (isIdentifier(node)) {
if (node.name === "undefined") {
// immutable!
return true;
} else {
// no idea...
return false;
}
}
return false;
}

View File

@ -0,0 +1,13 @@
// @flow
import { isVariableDeclaration } from "./generated";
import { BLOCK_SCOPED_SYMBOL } from "../constants";
/**
* Check if the input `node` is a `let` variable declaration.
*/
export default function isLet(node: Object): boolean {
return (
isVariableDeclaration(node) &&
(node.kind !== "var" || node[BLOCK_SCOPED_SYMBOL])
);
}

View File

@ -0,0 +1,6 @@
// @flow
import { VISITOR_KEYS } from "../definitions";
export default function isNode(node?: Object): boolean {
return !!(node && VISITOR_KEYS[node.type]);
}

View File

@ -0,0 +1,50 @@
// @flow
import { NODE_FIELDS } from "../definitions";
/**
* Check if two nodes are equivalent
*/
export default function isNodesEquivalent(a: any, b: any): boolean {
if (
typeof a !== "object" ||
typeof b !== "object" ||
a == null ||
b == null
) {
return a === b;
}
if (a.type !== b.type) {
return false;
}
const fields = Object.keys(NODE_FIELDS[a.type] || a.type);
for (const field of fields) {
if (typeof a[field] !== typeof b[field]) {
return false;
}
if (Array.isArray(a[field])) {
if (!Array.isArray(b[field])) {
return false;
}
if (a[field].length !== b[field].length) {
return false;
}
for (let i = 0; i < a[field].length; i++) {
if (!isNodesEquivalent(a[field][i], b[field][i])) {
return false;
}
}
continue;
}
if (!isNodesEquivalent(a[field], b[field])) {
return false;
}
}
return true;
}

View File

@ -0,0 +1,134 @@
// @flow
/**
* Check if the input `node` is a reference to a bound variable.
*/
export default function isReferenced(node: Object, parent: Object): boolean {
switch (parent.type) {
// yes: object::NODE
// yes: NODE::callee
case "BindExpression":
return parent.object === node || parent.callee === node;
// yes: PARENT[NODE]
// yes: NODE.child
// no: parent.NODE
case "MemberExpression":
case "JSXMemberExpression":
if (parent.property === node && parent.computed) {
return true;
} else if (parent.object === node) {
return true;
} else {
return false;
}
// no: new.NODE
// no: NODE.target
case "MetaProperty":
return false;
// yes: { [NODE]: "" }
// yes: { NODE }
// no: { NODE: "" }
case "ObjectProperty":
if (parent.key === node) {
return parent.computed;
}
// no: let NODE = init;
// yes: let id = NODE;
case "VariableDeclarator":
return parent.id !== node;
// no: function NODE() {}
// no: function foo(NODE) {}
case "ArrowFunctionExpression":
case "FunctionDeclaration":
case "FunctionExpression":
for (const param of (parent.params: Array<any>)) {
if (param === node) return false;
}
return parent.id !== node;
// no: export { foo as NODE };
// yes: export { NODE as foo };
// no: export { NODE as foo } from "foo";
case "ExportSpecifier":
if (parent.source) {
return false;
} else {
return parent.local === node;
}
// no: export NODE from "foo";
// no: export * as NODE from "foo";
case "ExportNamespaceSpecifier":
case "ExportDefaultSpecifier":
return false;
// no: <div NODE="foo" />
case "JSXAttribute":
return parent.name !== node;
// no: class { NODE = value; }
// yes: class { [NODE] = value; }
// yes: class { key = NODE; }
case "ClassProperty":
if (parent.key === node) {
return parent.computed;
} else {
return parent.value === node;
}
// no: import NODE from "foo";
// no: import * as NODE from "foo";
// no: import { NODE as foo } from "foo";
// no: import { foo as NODE } from "foo";
// no: import NODE from "bar";
case "ImportDefaultSpecifier":
case "ImportNamespaceSpecifier":
case "ImportSpecifier":
return false;
// no: class NODE {}
case "ClassDeclaration":
case "ClassExpression":
return parent.id !== node;
// yes: class { [NODE]() {} }
case "ClassMethod":
case "ObjectMethod":
return parent.key === node && parent.computed;
// no: NODE: for (;;) {}
case "LabeledStatement":
return false;
// no: try {} catch (NODE) {}
case "CatchClause":
return parent.param !== node;
// no: function foo(...NODE) {}
case "RestElement":
return false;
// yes: left = NODE;
// no: NODE = right;
case "AssignmentExpression":
return parent.right === node;
// no: [NODE = foo] = [];
// yes: [foo = NODE] = [];
case "AssignmentPattern":
return parent.right === node;
// no: [NODE] = [];
// no: ({ NODE }) = [];
case "ObjectPattern":
case "ArrayPattern":
return false;
}
return true;
}

View File

@ -0,0 +1,22 @@
// @flow
import {
isFunction,
isCatchClause,
isBlockStatement,
isScopable,
} from "./generated";
/**
* Check if the input `node` is a scope.
*/
export default function isScope(node: Object, parent: Object): boolean {
if (isBlockStatement(node) && isFunction(parent, { body: node })) {
return false;
}
if (isBlockStatement(node) && isCatchClause(parent, { body: node })) {
return false;
}
return isScopable(node);
}

View File

@ -0,0 +1,14 @@
// @flow
import { isIdentifier, isImportDefaultSpecifier } from "./generated";
/**
* Check if the input `specifier` is a `default` import or export.
*/
export default function isSpecifierDefault(specifier: Object): boolean {
return (
isImportDefaultSpecifier(specifier) ||
isIdentifier(specifier.imported || specifier.exported, {
name: "default",
})
);
}

View File

@ -0,0 +1,24 @@
// @flow
import { FLIPPED_ALIAS_KEYS, ALIAS_KEYS } from "../definitions";
/**
* Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`.
*/
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
// targetType was a primary node type, so there's no need to check the aliases.
if (ALIAS_KEYS[targetType]) return false;
const aliases: ?Array<string> = FLIPPED_ALIAS_KEYS[targetType];
if (aliases) {
if (aliases[0] === nodeType) return true;
for (const alias of aliases) {
if (nodeType === alias) return true;
}
}
return false;
}

View File

@ -0,0 +1,38 @@
// @flow
import isValidIdentifier from "./isValidIdentifier";
const RESERVED_WORDS_ES3_ONLY: Set<string> = new Set([
"abstract",
"boolean",
"byte",
"char",
"double",
"enum",
"final",
"float",
"goto",
"implements",
"int",
"interface",
"long",
"native",
"package",
"private",
"protected",
"public",
"short",
"static",
"synchronized",
"throws",
"transient",
"volatile",
]);
/**
* Check if the input `name` is a valid identifier name according to the ES3 specification.
*
* Additional ES3 reserved words are
*/
export default function isValidES3Identifier(name: string): boolean {
return isValidIdentifier(name) && !RESERVED_WORDS_ES3_ONLY.has(name);
}

View File

@ -0,0 +1,20 @@
// @flow
import esutils from "esutils";
/**
* Check if the input `name` is a valid identifier name
* and isn't a reserved word.
*/
export default function isValidIdentifier(name: string): boolean {
if (
typeof name !== "string" ||
esutils.keyword.isReservedWordES6(name, true)
) {
return false;
} else if (name === "await") {
// invalid in module, valid in script; better be safe (see #4952)
return false;
} else {
return esutils.keyword.isIdentifierNameES6(name);
}
}

View File

@ -0,0 +1,12 @@
// @flow
import { isVariableDeclaration } from "./generated";
import { BLOCK_SCOPED_SYMBOL } from "../constants";
/**
* Check if the input `node` is a variable declaration.
*/
export default function isVar(node: Object): boolean {
return (
isVariableDeclaration(node, { kind: "var" }) && !node[BLOCK_SCOPED_SYMBOL]
);
}

View File

@ -0,0 +1,45 @@
import { isIdentifier, isMemberExpression, isStringLiteral } from "./generated";
/**
* Determines whether or not the input node `member` matches the
* input `match`.
*
* For example, given the match `React.createClass` it would match the
* parsed nodes of `React.createClass` and `React["createClass"]`.
*/
export default function matchesPattern(
member: Object,
match: string | Array<string>,
allowPartial?: boolean,
): boolean {
// not a member expression
if (!isMemberExpression(member)) return false;
const parts = Array.isArray(match) ? match : match.split(".");
const nodes = [];
let node;
for (node = member; isMemberExpression(node); node = node.object) {
nodes.push(node.property);
}
nodes.push(node);
if (nodes.length < parts.length) return false;
if (!allowPartial && nodes.length > parts.length) return false;
for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) {
const node = nodes[j];
let value;
if (isIdentifier(node)) {
value = node.name;
} else if (isStringLiteral(node)) {
value = node.value;
} else {
return false;
}
if (parts[i] !== value) return false;
}
return true;
}

View File

@ -0,0 +1,4 @@
// @flow
export default function isCompatTag(tagName?: string): boolean {
return !!tagName && /^[a-z]|-/.test(tagName);
}

View File

@ -0,0 +1,6 @@
// @flow
import buildMatchMemberExpression from "../buildMatchMemberExpression";
const isReactComponent = buildMatchMemberExpression("React.Component");
export default isReactComponent;

View File

@ -0,0 +1,15 @@
// @flow
import { NODE_FIELDS } from "../definitions";
export default function validate(node?: Object, key: string, val: any): void {
if (!node) return;
const fields = NODE_FIELDS[node.type];
if (!fields) return;
const field = fields[key];
if (!field || !field.validate) return;
if (field.optional && val == null) return;
field.validate(node, key, val);
}