Convert @babel/types to TS (#12431)

* babel-types flowts convert
* babel-types code generation updates
* babel-types add more generated types to src (copy logic from scripts/typescript)
* babel-types update generateBuilders to specify exact argument types
* babel-types fix deprecated types generation
* babel-types fixes
* babel-types fix potential bug
* babel-types update generateBuilders, to include proper return types
* babel-types backport types from generated index.d.ts to be included in sources
* babel-types fixes
* babel-types avoid export of builders starting with upper case in ts sources
* babel-types
* babel-types todo updates, small fixes
* babel-types generate helpers
* babel-types remove typescript definitions generation
* babel-types generate files
* babel-types copy d.ts file for deprecated ast node creators into lib folder
* babel-types use t as alias for ast node types namespace
* babel-types update generateBuilders script to use "t" as alias instead of "types"
* babel-types update deprecated builders generation to have more compact file
* babel-types publish the .d.ts file for `@babel/types`
* Publish the .d.ts file for `@babel/types`
* Fix flowcheck
* Prettier
* No need to lint generated .d.ts files (now they are generated by tsc)
* Run prepublish-prepare-dts from prepublish-build
* Fix Babel 8 tests
* Update codecov config
* babel-types more improvements
  - better type for gatherSequenceExpressions
  - mark createUnionTypeAnnotation as deprecated
  - fix createTSUnionType
  - babel-types better type for builder
  - other improvements from PR comments
* babel-types lint fix
* babel-types fix createTSUnionType
* Don't commit .d.ts file in lib, and rename "deprecated"->"uppercase" for builders
* Add back types for TS 3.7
* Update packages/babel-types/package.json
* Cleanup converters types

Co-Authored-By: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Bogdan Savluk 2020-12-01 23:02:07 +01:00 committed by Nicolò Ribaudo
parent c0a8cbd989
commit 1290d215f1
98 changed files with 7509 additions and 2554 deletions

View File

@ -20,10 +20,15 @@ const rollupNodePolyfills = require("rollup-plugin-node-polyfills");
const rollupNodeResolve = require("@rollup/plugin-node-resolve").default;
const rollupReplace = require("@rollup/plugin-replace");
const { terser: rollupTerser } = require("rollup-plugin-terser");
const { default: rollupDts } = require("rollup-plugin-dts");
const defaultPackagesGlob = "./@(codemods|packages|eslint)/*";
const defaultSourcesGlob = `${defaultPackagesGlob}/src/**/{*.js,!(*.d).ts}`;
const defaultDtsGlob = `${defaultPackagesGlob}/lib/**/*.d.ts{,.map}`;
const defaultSourcesGlob = "./@(codemods|packages|eslint)/*/src/**/*.{js,ts}";
const babelStandalonePluginConfigGlob =
"./packages/babel-standalone/scripts/pluginConfig.json";
const buildTypingsWatchGlob = [
"./packages/babel-types/lib/definitions/**/*.js",
"./packages/babel-types/scripts/generators/*.js",
@ -37,11 +42,14 @@ const buildTypingsWatchGlob = [
* @example
* mapSrcToLib("packages/babel-template/src/index.ts")
* // returns "packages/babel-template/lib/index.js"
* @example
* mapSrcToLib("packages/babel-template/src/index.d.ts")
* // returns "packages/babel-template/lib/index.d.ts"
* @param {string} srcPath
* @returns {string}
*/
function mapSrcToLib(srcPath) {
const parts = srcPath.replace(/\.ts$/, ".js").split(path.sep);
const parts = srcPath.replace(/(?<!\.d)\.ts$/, ".js").split(path.sep);
parts[2] = "lib";
return parts.join(path.sep);
}
@ -81,19 +89,22 @@ function rename(fn) {
*
* @typedef {("asserts" | "builders" | "constants" | "validators")} HelperKind
* @param {HelperKind} helperKind
* @param {string} filename
*/
function generateTypeHelpers(helperKind) {
function generateTypeHelpers(helperKind, filename = "index.ts") {
const dest = `./packages/babel-types/src/${helperKind}/generated/`;
const formatCode = require("./scripts/utils/formatCode");
return gulp
const stream = gulp
.src(".", { base: __dirname })
.pipe(errorsLogger())
.pipe(
through.obj(function (file, enc, callback) {
file.path = "index.js";
file.path = filename;
file.contents = Buffer.from(
formatCode(
require(`./packages/babel-types/scripts/generators/${helperKind}`)(),
require(`./packages/babel-types/scripts/generators/${helperKind}`)(
filename
),
dest + file.path
)
);
@ -102,6 +113,8 @@ function generateTypeHelpers(helperKind) {
})
)
.pipe(gulp.dest(dest));
return finish(stream);
}
function generateStandalone() {
@ -139,18 +152,42 @@ export const all = {${allList}};`;
.pipe(gulp.dest(dest));
}
function buildBabel(exclude, sourcesGlob = defaultSourcesGlob) {
const base = __dirname;
function unlink() {
return through.obj(function (file, enc, callback) {
fs.unlink(file.path, () => callback());
});
}
let stream = gulp.src(sourcesGlob, { base: __dirname });
function finish(stream) {
return new Promise((resolve, reject) => {
stream.on("end", resolve);
stream.on("finish", resolve);
stream.on("error", reject);
});
}
function getFiles(glob, { include, exclude }) {
let stream = gulp.src(glob, { base: __dirname });
if (exclude) {
const filters = exclude.map(p => `!**/${p.src}/**`);
const filters = exclude.map(p => `!**/${p}/**`);
filters.unshift("**");
stream = stream.pipe(filter(filters));
}
if (include) {
const filters = include.map(p => `**/${p}/**`);
stream = stream.pipe(filter(filters));
}
return stream
return stream;
}
function buildBabel(exclude) {
const base = __dirname;
return getFiles(defaultSourcesGlob, {
exclude: exclude && exclude.map(p => p.src),
})
.pipe(errorsLogger())
.pipe(newer({ dest: base, map: mapSrcToLib }))
.pipe(compilationLogger())
@ -283,6 +320,41 @@ function buildRollup(packages, targetBrowsers) {
);
}
function buildRollupDts(packages) {
const sourcemap = process.env.NODE_ENV === "production";
return Promise.all(
packages.map(async packageName => {
const input = `${packageName}/lib/index.d.ts`;
fancyLog(`Bundling '${chalk.cyan(input)}' with rollup ...`);
const bundle = await rollup.rollup({
input,
plugins: [rollupDts()],
});
await finish(
gulp.src(`${packageName}/lib/**/*.d.ts{,.map}`).pipe(unlink())
);
await bundle.write({
file: `${packageName}/lib/index.d.ts`,
format: "es",
sourcemap: sourcemap,
exports: "named",
});
})
);
}
function removeDts(exclude) {
return getFiles(defaultDtsGlob, { exclude }).pipe(unlink());
}
function copyDts(packages) {
return getFiles(`${defaultPackagesGlob}/src/**/*.d.ts`, { include: packages })
.pipe(rename(file => path.resolve(file.base, mapSrcToLib(file.relative))))
.pipe(gulp.dest(__dirname));
}
const libBundles = [
"packages/babel-parser",
"packages/babel-plugin-proposal-optional-chaining",
@ -293,6 +365,8 @@ const libBundles = [
dest: "lib",
}));
const dtsBundles = ["packages/babel-types"];
const standaloneBundle = [
{
src: "packages/babel-standalone",
@ -306,11 +380,15 @@ const standaloneBundle = [
gulp.task("generate-type-helpers", () => {
fancyLog("Generating @babel/types dynamic functions");
return Promise.all(
["asserts", "builders", "constants", "validators"].map(helperKind =>
generateTypeHelpers(helperKind)
)
);
return Promise.all([
generateTypeHelpers("asserts"),
generateTypeHelpers("builders"),
generateTypeHelpers("builders", "uppercase.js"),
generateTypeHelpers("constants"),
generateTypeHelpers("validators"),
generateTypeHelpers("ast-types"),
]);
});
gulp.task("generate-standalone", () => generateStandalone());
@ -322,6 +400,13 @@ gulp.task(
gulp.series("generate-standalone", "rollup-babel-standalone")
);
gulp.task("copy-dts", () => copyDts(dtsBundles));
gulp.task(
"bundle-dts",
gulp.series("copy-dts", () => buildRollupDts(dtsBundles))
);
gulp.task("clean-dts", () => removeDts(/* exclude */ dtsBundles));
gulp.task("build-babel", () => buildBabel(/* exclude */ libBundles));
gulp.task(

View File

@ -27,7 +27,7 @@ endif
build-bundle: clean clean-lib
$(YARN) gulp build
$(MAKE) build-typings
$(MAKE) build-flow-typings
$(MAKE) build-dist
build-bundle-ci: bootstrap-only
@ -39,14 +39,11 @@ generate-tsconfig:
generate-type-helpers:
$(YARN) gulp generate-type-helpers
build-typings: build-flow-typings build-typescript-typings
build-flow-typings:
$(NODE) packages/babel-types/scripts/generators/flow.js > packages/babel-types/lib/index.js.flow
build-typescript-typings:
$(NODE) packages/babel-types/scripts/generators/typescript.js > packages/babel-types/lib/index.d.ts
$(NODE) packages/babel-types/scripts/generators/typescript.js --ts3.7 > packages/babel-types/lib/index-ts3.7.d.ts
build-typescript-3.7-typings:
$(NODE) packages/babel-types/scripts/generators/typescript-3.7.js > packages/babel-types/lib/index-ts3.7.d.ts
build-standalone: build-babel-standalone
@ -74,7 +71,7 @@ build-no-bundle: clean clean-lib
# Ensure that build artifacts for types are created during local
# development too.
# Babel-transform-fixture-test-runner requires minified polyfill for performance
$(MAKE) build-typings build-polyfill-dist
$(MAKE) build-flow-typings build-polyfill-dist
watch: build-no-bundle
BABEL_ENV=development $(YARN) gulp watch
@ -85,31 +82,19 @@ flowcheck-ci:
code-quality: tscheck flow lint
tscheck: generate-tsconfig
make build-typescript-typings
$(YARN) tsc -b .
flow:
flow: build-flow-typings
$(YARN) flow check --strip-root
lint-ci: lint-js-ci lint-ts-ci check-compat-data-ci
lint-js-ci:
$(MAKE) lint-js
lint-ts-ci:
$(MAKE) lint-ts
lint-ci: lint check-compat-data-ci
check-compat-data-ci:
$(MAKE) check-compat-data
lint: lint-js lint-ts
lint-js:
lint:
BABEL_ENV=test $(YARN) eslint scripts $(SOURCES) '*.{js,ts}' --format=codeframe --ext .js,.cjs,.mjs,.ts
lint-ts:
scripts/lint-ts-typings.sh
fix: fix-json fix-js
fix-js:
@ -202,19 +187,21 @@ clone-license:
prepublish-build: clean-lib clean-runtime-helpers
NODE_ENV=production BABEL_ENV=production STRIP_BABEL_8_FLAG=true $(MAKE) build-bundle
$(MAKE) prepublish-build-standalone clone-license
$(MAKE) prepublish-build-standalone clone-license prepublish-prepare-dts
prepublish-prepare-dts:
$(MAKE) clean-tsconfig
$(MAKE) tscheck
$(YARN) gulp bundle-dts
$(YARN) gulp clean-dts
$(MAKE) build-typescript-3.7-typings
$(MAKE) clean-tsconfig
prepublish:
$(MAKE) check-yarn-bug-1882
$(MAKE) bootstrap-only
$(MAKE) prepublish-build
IS_PUBLISH=true $(MAKE) test
# We don't want to publish TS-related files yet, except for @babel/types
rm -f packages/*/lib/**/*.d.ts{,.map}
rm -f codemods/*/lib/**/*.d.ts{,.map}
rm -f eslint/*/lib/**/*.d.ts{,.map}
$(MAKE) clean-tsconfig
$(MAKE) build-typescript-typings
new-version:
git pull --rebase

View File

@ -9,4 +9,4 @@ coverage:
patch:
enabled: false
ignore:
- packages/babel-types/src/*/generated/index.js
- packages/babel-types/src/*/generated/*

View File

@ -60,6 +60,7 @@
"mergeiterator": "^1.2.5",
"prettier": "^2.0.5",
"rollup": "^2.26.5",
"rollup-plugin-dts": "^2.0.0",
"rollup-plugin-node-polyfills": "^0.2.1",
"rollup-plugin-terser": "^7.0.0",
"test262-stream": "^1.3.0",

View File

@ -46,7 +46,7 @@ export function skipAllButComputedKey(path: NodePath) {
// Avoid using `path.scope` here
export const environmentVisitor = {
// todo (Babel 8): remove StaticBlock brand checks
[`${t.StaticBlock ? "StaticBlock|" : ""}ClassPrivateProperty|TypeAnnotation`](
[`${t.staticBlock ? "StaticBlock|" : ""}ClassPrivateProperty|TypeAnnotation`](
path: NodePath,
) {
path.skip();

View File

@ -95,7 +95,6 @@ import transformTypeofSymbol from "@babel/plugin-transform-typeof-symbol";
import transformTypescript from "@babel/plugin-transform-typescript";
import transformUnicodeEscapes from "@babel/plugin-transform-unicode-escapes";
import transformUnicodeRegex from "@babel/plugin-transform-unicode-regex";
export {
externalHelpers,
syntaxAsyncGenerators,
@ -191,7 +190,6 @@ export {
transformUnicodeEscapes,
transformUnicodeRegex,
};
export const all = {
"external-helpers": externalHelpers,
"syntax-async-generators": syntaxAsyncGenerators,

View File

@ -14,9 +14,8 @@
"directory": "packages/babel-types"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"typesVersions": {
">=3.7": {
"<3.7": {
"lib/index.d.ts": [
"lib/index-ts3.7.d.ts"
]
@ -29,6 +28,8 @@
},
"devDependencies": {
"@babel/generator": "workspace:*",
"@babel/parser": "workspace:*"
"@babel/parser": "workspace:*",
"@types/lodash": "^4.14.162",
"chalk": "^4.1.0"
}
}

View File

@ -2,23 +2,30 @@
const definitions = require("../../lib/definitions");
function addAssertHelper(type) {
return `export function assert${type}(node: Object, opts?: Object = {}): void {
const result =
definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]
? `node is t.${type}`
: "boolean";
return `export function assert${type}(node: object | null | undefined, opts?: object | null): asserts ${
result === "boolean" ? "node" : result
} {
assert("${type}", node, opts) }
`;
}
module.exports = function generateAsserts() {
let output = `// @flow
/*
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import is from "../../validators/is";
import type * as t from "../..";
function assert(type: string, node: Object, opts?: Object): void {
function assert(type: string, node: any, opts?: any): void {
if (!is(type, node, opts)) {
throw new Error(
\`Expected type "\${type}" with option \${JSON.stringify((opts: any))}, \` +
\`Expected type "\${type}" with option \${JSON.stringify(opts)}, \` +
\`but instead got "\${node.type}".\`,
);
}
@ -34,7 +41,7 @@ function assert(type: string, node: Object, opts?: Object): void {
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const newType = definitions.DEPRECATED_KEYS[type];
output += `export function assert${type}(node: Object, opts: Object): void {
output += `export function assert${type}(node: any, opts: any): void {
console.trace("The node type ${type} has been renamed to ${newType}");
assert("${type}", node, opts);
}\n`;

View File

@ -0,0 +1,139 @@
"use strict";
const t = require("../../");
const stringifyValidator = require("../utils/stringifyValidator");
module.exports = function generateAstTypes() {
let code = `// NOTE: This file is autogenerated. Do not modify.
// See packages/babel-types/scripts/generators/ast-types.js for script used.
interface BaseComment {
value: string;
start: number;
end: number;
loc: SourceLocation;
type: "CommentBlock" | "CommentLine";
}
export interface CommentBlock extends BaseComment {
type: "CommentBlock";
}
export interface CommentLine extends BaseComment {
type: "CommentLine";
}
export type Comment = CommentBlock | CommentLine;
export interface SourceLocation {
start: {
line: number;
column: number;
};
end: {
line: number;
column: number;
};
}
interface BaseNode {
leadingComments: ReadonlyArray<Comment> | null;
innerComments: ReadonlyArray<Comment> | null;
trailingComments: ReadonlyArray<Comment> | null;
start: number | null;
end: number | null;
loc: SourceLocation | null;
type: Node["type"];
extra?: Record<string, unknown>;
}
export type CommentTypeShorthand = "leading" | "inner" | "trailing";
export type Node = ${t.TYPES.sort().join(" | ")};\n\n`;
const deprecatedAlias = {};
for (const type in t.DEPRECATED_KEYS) {
deprecatedAlias[t.DEPRECATED_KEYS[type]] = type;
}
for (const type in t.NODE_FIELDS) {
const fields = t.NODE_FIELDS[type];
const fieldNames = sortFieldNames(Object.keys(t.NODE_FIELDS[type]), type);
const struct = [];
fieldNames.forEach(fieldName => {
const field = fields[fieldName];
// Future / annoying TODO:
// MemberExpression.property, ObjectProperty.key and ObjectMethod.key need special cases; either:
// - convert the declaration to chain() like ClassProperty.key and ClassMethod.key,
// - declare an alias type for valid keys, detect the case and reuse it here,
// - declare a disjoint union with, for example, ObjectPropertyBase,
// ObjectPropertyLiteralKey and ObjectPropertyComputedKey, and declare ObjectProperty
// as "ObjectPropertyBase & (ObjectPropertyLiteralKey | ObjectPropertyComputedKey)"
let typeAnnotation = stringifyValidator(field.validate, "");
if (isNullable(field) && !hasDefault(field)) {
typeAnnotation += " | null";
}
const alphaNumeric = /^\w+$/;
if (t.isValidIdentifier(fieldName) || alphaNumeric.test(fieldName)) {
struct.push(`${fieldName}: ${typeAnnotation};`);
} else {
struct.push(`"${fieldName}": ${typeAnnotation};`);
}
});
code += `export interface ${type} extends BaseNode {
type: "${type}";
${struct.join("\n ").trim()}
}\n\n`;
if (deprecatedAlias[type]) {
code += `/**
* @deprecated Use \`${type}\`
*/
export interface ${deprecatedAlias[type]} extends BaseNode {
type: "${deprecatedAlias[type]}";
${struct.join("\n ").trim()}
}\n\n
`;
}
}
for (const type in t.FLIPPED_ALIAS_KEYS) {
const types = t.FLIPPED_ALIAS_KEYS[type];
code += `export type ${type} = ${types
.map(type => `${type}`)
.join(" | ")};\n`;
}
code += "\n";
code += "export interface Aliases {\n";
for (const type in t.FLIPPED_ALIAS_KEYS) {
code += ` ${type}: ${type};\n`;
}
code += "}\n\n";
return code;
};
function hasDefault(field) {
return field.default != null;
}
function isNullable(field) {
return field.optional || hasDefault(field);
}
function sortFieldNames(fields, type) {
return fields.sort((fieldA, fieldB) => {
const indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
const indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
});
}

View File

@ -3,26 +3,106 @@ const definitions = require("../../lib/definitions");
const formatBuilderName = require("../utils/formatBuilderName");
const lowerFirst = require("../utils/lowerFirst");
module.exports = function generateBuilders() {
let output = `// @flow
/*
const t = require("../../");
const stringifyValidator = require("../utils/stringifyValidator");
function areAllRemainingFieldsNullable(fieldName, fieldNames, fields) {
const index = fieldNames.indexOf(fieldName);
return fieldNames.slice(index).every(_ => isNullable(fields[_]));
}
function hasDefault(field) {
return field.default != null;
}
function isNullable(field) {
return field.optional || hasDefault(field);
}
function sortFieldNames(fields, type) {
return fields.sort((fieldA, fieldB) => {
const indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
const indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
});
}
function generateBuilderArgs(type) {
const fields = t.NODE_FIELDS[type];
const fieldNames = sortFieldNames(Object.keys(t.NODE_FIELDS[type]), type);
const builderNames = t.BUILDER_KEYS[type];
const args = [];
fieldNames.forEach(fieldName => {
const field = fields[fieldName];
// Future / annoying TODO:
// MemberExpression.property, ObjectProperty.key and ObjectMethod.key need special cases; either:
// - convert the declaration to chain() like ClassProperty.key and ClassMethod.key,
// - declare an alias type for valid keys, detect the case and reuse it here,
// - declare a disjoint union with, for example, ObjectPropertyBase,
// ObjectPropertyLiteralKey and ObjectPropertyComputedKey, and declare ObjectProperty
// as "ObjectPropertyBase & (ObjectPropertyLiteralKey | ObjectPropertyComputedKey)"
let typeAnnotation = stringifyValidator(field.validate, "t.");
if (isNullable(field) && !hasDefault(field)) {
typeAnnotation += " | null";
}
if (builderNames.includes(fieldName)) {
const bindingIdentifierName = t.toBindingIdentifierName(fieldName);
if (areAllRemainingFieldsNullable(fieldName, builderNames, fields)) {
args.push(
`${bindingIdentifierName}${
isNullable(field) ? "?:" : ":"
} ${typeAnnotation}`
);
} else {
args.push(
`${bindingIdentifierName}: ${typeAnnotation}${
isNullable(field) ? " | undefined" : ""
}`
);
}
}
});
return args;
}
module.exports = function generateBuilders(kind) {
return kind === "uppercase.js"
? generateUppercaseBuilders()
: generateLowercaseBuilders();
};
function generateLowercaseBuilders() {
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import builder from "../builder";\n\n`;
import builder from "../builder";
import type * as t from "../..";
/* eslint-disable @typescript-eslint/no-unused-vars */
`;
const reservedNames = new Set(["super", "import"]);
Object.keys(definitions.BUILDER_KEYS).forEach(type => {
const defArgs = generateBuilderArgs(type);
const formatedBuilderName = formatBuilderName(type);
const formatedBuilderNameLocal = reservedNames.has(formatedBuilderName)
? `_${formatedBuilderName}`
: formatedBuilderName;
output += `${
formatedBuilderNameLocal === formatedBuilderName ? "export " : ""
}function ${formatedBuilderNameLocal}(...args: Array<any>): Object { return builder("${type}", ...args); }\n`;
// This is needed for backwards compatibility.
// arrayExpression -> ArrayExpression
output += `export { ${formatedBuilderNameLocal} as ${type} };\n`;
}function ${formatedBuilderNameLocal}(${defArgs.join(
", "
)}): t.${type} { return builder("${type}", ...arguments); }\n`;
if (formatedBuilderNameLocal !== formatedBuilderName) {
output += `export { ${formatedBuilderNameLocal} as ${formatedBuilderName} };\n`;
}
@ -39,12 +119,13 @@ import builder from "../builder";\n\n`;
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const newType = definitions.DEPRECATED_KEYS[type];
output += `export function ${type}(...args: Array<any>): Object {
const formatedBuilderName = formatBuilderName(type);
output += `/** @deprecated */
function ${type}(...args: Array<any>): any {
console.trace("The node type ${type} has been renamed to ${newType}");
return builder("${type}", ...args);
}
export { ${type} as ${formatBuilderName(type)} };\n`;
export { ${type} as ${formatedBuilderName} };\n`;
// This is needed for backwards compatibility.
// It should be removed in the next major version.
// JSXIdentifier -> jSXIdentifier
@ -54,4 +135,31 @@ export { ${type} as ${formatBuilderName(type)} };\n`;
});
return output;
};
}
function generateUppercaseBuilders() {
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
/**
* This file is written in JavaScript and not TypeScript because uppercase builders
* conflict with AST types. TypeScript reads the uppercase.d.ts file instead.
*/
export {\n`;
Object.keys(definitions.BUILDER_KEYS).forEach(type => {
const formatedBuilderName = formatBuilderName(type);
output += ` ${formatedBuilderName} as ${type},\n`;
});
Object.keys(definitions.DEPRECATED_KEYS).forEach(type => {
const formatedBuilderName = formatBuilderName(type);
output += ` ${formatedBuilderName} as ${type},\n`;
});
output += ` } from './index';\n`;
return output;
}

View File

@ -2,8 +2,7 @@
const definitions = require("../../lib/definitions");
module.exports = function generateConstants() {
let output = `// @flow
/*
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/

View File

@ -98,7 +98,7 @@ for (const type in t.NODE_FIELDS) {
// Flow chokes on super() and import() :/
if (type !== "Super" && type !== "Import") {
lines.push(
`declare function ${toFunctionName(type)}(${args.join(
`declare export function ${toFunctionName(type)}(${args.join(
", "
)}): ${NODE_PREFIX}${type};`
);
@ -117,85 +117,90 @@ for (const typeName of t.TYPES) {
const isDeprecated = !!t.DEPRECATED_KEYS[typeName];
const realName = isDeprecated ? t.DEPRECATED_KEYS[typeName] : typeName;
let decl = `declare function is${typeName}(node: ?Object, opts?: ?Object): boolean`;
let decl = `declare export function is${typeName}(node: ?Object, opts?: ?Object): boolean`;
if (t.NODE_FIELDS[realName]) {
decl += ` %checks (node instanceof ${NODE_PREFIX}${realName})`;
}
lines.push(decl);
lines.push(
`declare function assert${typeName}(node: ?Object, opts?: ?Object): void`
`declare export function assert${typeName}(node: ?Object, opts?: ?Object): void`
);
}
lines.push(
`declare export var VISITOR_KEYS: { [type: string]: string[] }`,
// assert/
`declare function assertNode(obj: any): void`,
`declare export function assertNode(obj: any): void`,
// builders/
// eslint-disable-next-line max-len
`declare function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): ${NODE_PREFIX}TypeAnnotation`,
`declare export function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): ${NODE_PREFIX}TypeAnnotation`,
// eslint-disable-next-line max-len
`declare function createUnionTypeAnnotation(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`,
`declare export function createUnionTypeAnnotation(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`,
// eslint-disable-next-line max-len
`declare function createFlowUnionType(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`,
`declare export function createFlowUnionType(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`,
// this smells like "internal API"
// eslint-disable-next-line max-len
`declare function buildChildren(node: { children: Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment | ${NODE_PREFIX}JSXEmptyExpression> }): Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment>`,
`declare export function buildChildren(node: { children: Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment | ${NODE_PREFIX}JSXEmptyExpression> }): Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment>`,
// clone/
`declare function clone<T>(n: T): T;`,
`declare function cloneDeep<T>(n: T): T;`,
`declare function cloneDeepWithoutLoc<T>(n: T): T;`,
`declare function cloneNode<T>(n: T, deep?: boolean, withoutLoc?: boolean): T;`,
`declare function cloneWithoutLoc<T>(n: T): T;`,
`declare export function clone<T>(n: T): T;`,
`declare export function cloneDeep<T>(n: T): T;`,
`declare export function cloneDeepWithoutLoc<T>(n: T): T;`,
`declare export function cloneNode<T>(n: T, deep?: boolean, withoutLoc?: boolean): T;`,
`declare export function cloneWithoutLoc<T>(n: T): T;`,
// comments/
`declare type CommentTypeShorthand = 'leading' | 'inner' | 'trailing'`,
// eslint-disable-next-line max-len
`declare function addComment<T: Node>(node: T, type: CommentTypeShorthand, content: string, line?: boolean): T`,
`declare export function addComment<T: BabelNode>(node: T, type: CommentTypeShorthand, content: string, line?: boolean): T`,
// eslint-disable-next-line max-len
`declare function addComments<T: Node>(node: T, type: CommentTypeShorthand, comments: Array<Comment>): T`,
`declare function inheritInnerComments(node: Node, parent: Node): void`,
`declare function inheritLeadingComments(node: Node, parent: Node): void`,
`declare function inheritsComments<T: Node>(node: T, parent: Node): void`,
`declare function inheritTrailingComments(node: Node, parent: Node): void`,
`declare function removeComments<T: Node>(node: T): T`,
`declare export function addComments<T: BabelNode>(node: T, type: CommentTypeShorthand, comments: Array<Comment>): T`,
`declare export function inheritInnerComments(node: BabelNode, parent: BabelNode): void`,
`declare export function inheritLeadingComments(node: BabelNode, parent: BabelNode): void`,
`declare export function inheritsComments<T: BabelNode>(node: T, parent: BabelNode): void`,
`declare export function inheritTrailingComments(node: BabelNode, parent: BabelNode): void`,
`declare export function removeComments<T: BabelNode>(node: T): T`,
// converters/
`declare function ensureBlock(node: ${NODE_PREFIX}, key: string): ${NODE_PREFIX}BlockStatement`,
`declare function toBindingIdentifierName(name?: ?string): string`,
`declare export function ensureBlock(node: ${NODE_PREFIX}, key: string): ${NODE_PREFIX}BlockStatement`,
`declare export function toBindingIdentifierName(name?: ?string): string`,
// eslint-disable-next-line max-len
`declare function toBlock(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Expression, parent?: ${NODE_PREFIX}Function | null): ${NODE_PREFIX}BlockStatement`,
`declare export function toBlock(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Expression, parent?: ${NODE_PREFIX}Function | null): ${NODE_PREFIX}BlockStatement`,
// eslint-disable-next-line max-len
`declare function toComputedKey(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}Expression | ${NODE_PREFIX}Identifier): ${NODE_PREFIX}Expression`,
`declare export function toComputedKey(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}Expression | ${NODE_PREFIX}Identifier): ${NODE_PREFIX}Expression`,
// eslint-disable-next-line max-len
`declare function toExpression(node: ${NODE_PREFIX}ExpressionStatement | ${NODE_PREFIX}Expression | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function): ${NODE_PREFIX}Expression`,
`declare function toIdentifier(name?: ?string): string`,
`declare export function toExpression(node: ${NODE_PREFIX}ExpressionStatement | ${NODE_PREFIX}Expression | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function): ${NODE_PREFIX}Expression`,
`declare export function toIdentifier(name?: ?string): string`,
// eslint-disable-next-line max-len
`declare function toKeyAlias(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}): string`,
`declare export function toKeyAlias(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}): string`,
// toSequenceExpression relies on types that aren't declared in flow
// eslint-disable-next-line max-len
`declare function toStatement(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function | ${NODE_PREFIX}AssignmentExpression, ignore?: boolean): ${NODE_PREFIX}Statement | void`,
`declare function valueToNode(value: any): ${NODE_PREFIX}Expression`,
`declare export function toStatement(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function | ${NODE_PREFIX}AssignmentExpression, ignore?: boolean): ${NODE_PREFIX}Statement | void`,
`declare export function valueToNode(value: any): ${NODE_PREFIX}Expression`,
// modifications/
// eslint-disable-next-line max-len
`declare function removeTypeDuplicates(types: Array<${NODE_PREFIX}FlowType>): Array<${NODE_PREFIX}FlowType>`,
`declare export function removeTypeDuplicates(types: Array<${NODE_PREFIX}FlowType>): Array<${NODE_PREFIX}FlowType>`,
// eslint-disable-next-line max-len
`declare function appendToMemberExpression(member: ${NODE_PREFIX}MemberExpression, append: ${NODE_PREFIX}, computed?: boolean): ${NODE_PREFIX}MemberExpression`,
`declare export function appendToMemberExpression(member: ${NODE_PREFIX}MemberExpression, append: ${NODE_PREFIX}, computed?: boolean): ${NODE_PREFIX}MemberExpression`,
// eslint-disable-next-line max-len
`declare function inherits<T: Node>(child: T, parent: ${NODE_PREFIX} | null | void): T`,
`declare export function inherits<T: BabelNode>(child: T, parent: ${NODE_PREFIX} | null | void): T`,
// eslint-disable-next-line max-len
`declare function prependToMemberExpression(member: ${NODE_PREFIX}MemberExpression, prepend: ${NODE_PREFIX}Expression): ${NODE_PREFIX}MemberExpression`,
`declare function removeProperties<T>(n: T, opts: ?{}): void;`,
`declare function removePropertiesDeep<T>(n: T, opts: ?{}): T;`,
`declare export function prependToMemberExpression(member: ${NODE_PREFIX}MemberExpression, prepend: ${NODE_PREFIX}Expression): ${NODE_PREFIX}MemberExpression`,
`declare export function removeProperties<T>(n: T, opts: ?{}): void;`,
`declare export function removePropertiesDeep<T>(n: T, opts: ?{}): T;`,
// retrievers/
// eslint-disable-next-line max-len
`declare function getBindingIdentifiers(node: ${NODE_PREFIX}, duplicates: boolean, outerOnly?: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`,
`declare export var getBindingIdentifiers: {
(node: ${NODE_PREFIX}, duplicates?: boolean, outerOnly?: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> },
keys: { [type: string]: string[] }
}`,
// eslint-disable-next-line max-len
`declare function getOuterBindingIdentifiers(node: Node, duplicates: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`,
`declare export function getOuterBindingIdentifiers(node: BabelNode, duplicates?: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`,
// traverse/
`declare type TraversalAncestors = Array<{
@ -209,36 +214,36 @@ lines.push(
exit?: TraversalHandler<T>,
};`.replace(/(^|\n) {2}/g, "$1"),
// eslint-disable-next-line
`declare function traverse<T>(n: BabelNode, TraversalHandler<T> | TraversalHandlers<T>, state?: T): void;`,
`declare function traverseFast<T>(n: Node, h: TraversalHandler<T>, state?: T): void;`,
`declare export function traverse<T>(n: BabelNode, TraversalHandler<T> | TraversalHandlers<T>, state?: T): void;`,
`declare export function traverseFast<T>(n: BabelNode, h: TraversalHandler<T>, state?: T): void;`,
// utils/
// cleanJSXElementLiteralChild is not exported
// inherit is not exported
`declare function shallowEqual(actual: Object, expected: Object): boolean`,
`declare export function shallowEqual(actual: Object, expected: Object): boolean`,
// validators/
// eslint-disable-next-line max-len
`declare function buildMatchMemberExpression(match: string, allowPartial?: boolean): (?BabelNode) => boolean`,
`declare function is(type: string, n: BabelNode, opts: Object): boolean;`,
`declare function isBinding(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`,
`declare function isBlockScoped(node: BabelNode): boolean`,
`declare function isImmutable(node: BabelNode): boolean`,
`declare function isLet(node: BabelNode): boolean`,
`declare function isNode(node: ?Object): boolean`,
`declare function isNodesEquivalent(a: any, b: any): boolean`,
`declare function isPlaceholderType(placeholderType: string, targetType: string): boolean`,
`declare function isReferenced(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`,
`declare function isScope(node: BabelNode, parent: BabelNode): boolean`,
`declare function isSpecifierDefault(specifier: BabelNodeModuleSpecifier): boolean`,
`declare function isType(nodetype: ?string, targetType: string): boolean`,
`declare function isValidES3Identifier(name: string): boolean`,
`declare function isValidES3Identifier(name: string): boolean`,
`declare function isValidIdentifier(name: string): boolean`,
`declare function isVar(node: BabelNode): boolean`,
`declare export function buildMatchMemberExpression(match: string, allowPartial?: boolean): (?BabelNode) => boolean`,
`declare export function is(type: string, n: BabelNode, opts: Object): boolean;`,
`declare export function isBinding(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`,
`declare export function isBlockScoped(node: BabelNode): boolean`,
`declare export function isImmutable(node: BabelNode): boolean`,
`declare export function isLet(node: BabelNode): boolean`,
`declare export function isNode(node: ?Object): boolean`,
`declare export function isNodesEquivalent(a: any, b: any): boolean`,
`declare export function isPlaceholderType(placeholderType: string, targetType: string): boolean`,
`declare export function isReferenced(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`,
`declare export function isScope(node: BabelNode, parent: BabelNode): boolean`,
`declare export function isSpecifierDefault(specifier: BabelNodeModuleSpecifier): boolean`,
`declare export function isType(nodetype: ?string, targetType: string): boolean`,
`declare export function isValidES3Identifier(name: string): boolean`,
`declare export function isValidES3Identifier(name: string): boolean`,
`declare export function isValidIdentifier(name: string): boolean`,
`declare export function isVar(node: BabelNode): boolean`,
// eslint-disable-next-line max-len
`declare function matchesPattern(node: ?BabelNode, match: string | Array<string>, allowPartial?: boolean): boolean`,
`declare function validate(n: BabelNode, key: string, value: mixed): void;`
`declare export function matchesPattern(node: ?BabelNode, match: string | Array<string>, allowPartial?: boolean): boolean`,
`declare export function validate(n: BabelNode, key: string, value: mixed): void;`
);
for (const type in t.FLIPPED_ALIAS_KEYS) {

View File

@ -1,17 +1,11 @@
"use strict";
const t = require("../../");
const t = require("../../lib");
const stringifyValidator = require("../utils/stringifyValidator");
const toFunctionName = require("../utils/toFunctionName");
// For backward compat, we cannot use TS 3.7 syntax in published packages
const ts3_7 = process.argv.includes("--ts3.7");
// TypeScript 3.7: https://github.com/microsoft/TypeScript/pull/32695 will allow assert declarations
const asserts = ts3_7 ? assertion => `asserts ${assertion}` : () => `void`;
let code = `// NOTE: This file is autogenerated. Do not modify.
// See packages/babel-types/scripts/generators/typescript.js for script used.
// See packages/babel-types/scripts/generators/typescript-3.7.js for script used.
interface BaseComment {
value: string;
@ -146,15 +140,13 @@ for (const typeName of t.TYPES) {
lines.push(`/** @deprecated Use \`assert${realName}\` */`);
}
lines.push(
`export function assert${typeName}(node: object | null | undefined, opts?: object | null): ${asserts(
result === "boolean" ? "node" : result
)};`
`export function assert${typeName}(node: object | null | undefined, opts?: object | null): void;`
);
}
lines.push(
// assert/
`export function assertNode(obj: any): ${asserts("obj is Node")}`,
`export function assertNode(obj: any): void`,
// builders/
// eslint-disable-next-line max-len
@ -320,9 +312,7 @@ lines.push(
// eslint-disable-next-line max-len
`export function matchesPattern(node: Node | null | undefined, match: string | ReadonlyArray<string>, allowPartial?: boolean): node is MemberExpression`,
// eslint-disable-next-line max-len
`export function validate<T extends Node, K extends keyof T>(n: Node | null | undefined, key: K, value: T[K]): ${asserts(
"n is T"
)}`,
`export function validate<T extends Node, K extends keyof T>(n: Node | null | undefined, key: K, value: T[K]): void;`,
`export function validate(n: Node, key: string, value: any): void;`
);

View File

@ -13,7 +13,7 @@ function addIsHelper(type, aliasKeys, deprecated) {
const targetType = JSON.stringify(type);
let aliasSource = "";
if (aliasKeys) {
aliasSource = " || " + joinComparisons(aliasKeys, "nodeType");
aliasSource = joinComparisons(aliasKeys, "nodeType");
}
let placeholderSource = "";
@ -30,16 +30,26 @@ function addIsHelper(type, aliasKeys, deprecated) {
if (placeholderTypes.length > 0) {
placeholderSource =
' || nodeType === "Placeholder" && (' +
joinComparisons(placeholderTypes, "node.expectedNode") +
joinComparisons(
placeholderTypes,
"(node as t.Placeholder).expectedNode"
) +
")";
}
return `export function is${type}(node: ?Object, opts?: Object): boolean {
const result =
definitions.NODE_FIELDS[type] || definitions.FLIPPED_ALIAS_KEYS[type]
? `node is t.${type}`
: "boolean";
return `export function is${type}(node: object | null | undefined, opts?: object | null): ${result} {
${deprecated || ""}
if (!node) return false;
const nodeType = node.type;
if (nodeType === ${targetType}${aliasSource}${placeholderSource}) {
const nodeType = (node as t.Node).type;
if (${
aliasSource ? aliasSource : `nodeType === ${targetType}`
}${placeholderSource}) {
if (typeof opts === "undefined") {
return true;
} else {
@ -53,12 +63,12 @@ function addIsHelper(type, aliasKeys, deprecated) {
}
module.exports = function generateValidators() {
let output = `// @flow
/*
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import shallowEqual from "../../utils/shallowEqual";\n\n`;
import shallowEqual from "../../utils/shallowEqual";
import type * as t from "../..";\n\n`;
Object.keys(definitions.VISITOR_KEYS).forEach(type => {
output += addIsHelper(type);

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,12 @@
// @flow
import loClone from "lodash/clone";
import { NODE_FIELDS, BUILDER_KEYS } from "../definitions";
import validate from "../validators/validate";
import type * as t from "..";
export default function builder(type: string, ...args: Array<any>): Object {
export default function builder<T extends t.Node>(
type: T["type"],
...args: Array<any>
): T {
const keys = BUILDER_KEYS[type];
const countArgs = args.length;
if (countArgs > keys.length) {
@ -27,8 +30,8 @@ export default function builder(type: string, ...args: Array<any>): Object {
});
for (const key of Object.keys(node)) {
validate(node, key, node[key]);
validate(node as t.Node, key, node[key]);
}
return node;
return node as T;
}

View File

@ -1,16 +1,18 @@
// @flow
import { unionTypeAnnotation } from "../generated";
import removeTypeDuplicates from "../../modifications/flow/removeTypeDuplicates";
import type * as t from "../..";
/**
* Takes an array of `types` and flattens them, removing duplicates and
* returns a `UnionTypeAnnotation` node containing them.
*/
export default function createFlowUnionType(types: Array<Object>): Object {
export default function createFlowUnionType<T extends t.FlowType>(
types: [T] | Array<T>,
): T | t.UnionTypeAnnotation {
const flattened = removeTypeDuplicates(types);
if (flattened.length === 1) {
return flattened[0];
return flattened[0] as T;
} else {
return unionTypeAnnotation(flattened);
}

View File

@ -1,4 +1,3 @@
// @flow
import {
stringTypeAnnotation,
numberTypeAnnotation,
@ -7,13 +6,26 @@ import {
genericTypeAnnotation,
identifier,
} from "../generated";
import type * as t from "../..";
/**
* Create a type annotation based on typeof expression.
*/
export default function createTypeAnnotationBasedOnTypeof(
type: string,
): Object {
type:
| "string"
| "number"
| "undefined"
| "boolean"
| "function"
| "object"
| "symbol",
):
| t.StringTypeAnnotation
| t.VoidTypeAnnotation
| t.NumberTypeAnnotation
| t.BooleanTypeAnnotation
| t.GenericTypeAnnotation {
if (type === "string") {
return stringTypeAnnotation();
} else if (type === "number") {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
/**
* uppercase.js file is written in JavaScript and not TypeScript because uppercase
* builders conflict with AST types. TypeScript reads the this file instead.
*/
export {};

View File

@ -0,0 +1,258 @@
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
/**
* This file is written in JavaScript and not TypeScript because uppercase builders
* conflict with AST types. TypeScript reads the uppercase.d.ts file instead.
*/
export {
arrayExpression as ArrayExpression,
assignmentExpression as AssignmentExpression,
binaryExpression as BinaryExpression,
interpreterDirective as InterpreterDirective,
directive as Directive,
directiveLiteral as DirectiveLiteral,
blockStatement as BlockStatement,
breakStatement as BreakStatement,
callExpression as CallExpression,
catchClause as CatchClause,
conditionalExpression as ConditionalExpression,
continueStatement as ContinueStatement,
debuggerStatement as DebuggerStatement,
doWhileStatement as DoWhileStatement,
emptyStatement as EmptyStatement,
expressionStatement as ExpressionStatement,
file as File,
forInStatement as ForInStatement,
forStatement as ForStatement,
functionDeclaration as FunctionDeclaration,
functionExpression as FunctionExpression,
identifier as Identifier,
ifStatement as IfStatement,
labeledStatement as LabeledStatement,
stringLiteral as StringLiteral,
numericLiteral as NumericLiteral,
nullLiteral as NullLiteral,
booleanLiteral as BooleanLiteral,
regExpLiteral as RegExpLiteral,
logicalExpression as LogicalExpression,
memberExpression as MemberExpression,
newExpression as NewExpression,
program as Program,
objectExpression as ObjectExpression,
objectMethod as ObjectMethod,
objectProperty as ObjectProperty,
restElement as RestElement,
returnStatement as ReturnStatement,
sequenceExpression as SequenceExpression,
parenthesizedExpression as ParenthesizedExpression,
switchCase as SwitchCase,
switchStatement as SwitchStatement,
thisExpression as ThisExpression,
throwStatement as ThrowStatement,
tryStatement as TryStatement,
unaryExpression as UnaryExpression,
updateExpression as UpdateExpression,
variableDeclaration as VariableDeclaration,
variableDeclarator as VariableDeclarator,
whileStatement as WhileStatement,
withStatement as WithStatement,
assignmentPattern as AssignmentPattern,
arrayPattern as ArrayPattern,
arrowFunctionExpression as ArrowFunctionExpression,
classBody as ClassBody,
classExpression as ClassExpression,
classDeclaration as ClassDeclaration,
exportAllDeclaration as ExportAllDeclaration,
exportDefaultDeclaration as ExportDefaultDeclaration,
exportNamedDeclaration as ExportNamedDeclaration,
exportSpecifier as ExportSpecifier,
forOfStatement as ForOfStatement,
importDeclaration as ImportDeclaration,
importDefaultSpecifier as ImportDefaultSpecifier,
importNamespaceSpecifier as ImportNamespaceSpecifier,
importSpecifier as ImportSpecifier,
metaProperty as MetaProperty,
classMethod as ClassMethod,
objectPattern as ObjectPattern,
spreadElement as SpreadElement,
super as Super,
taggedTemplateExpression as TaggedTemplateExpression,
templateElement as TemplateElement,
templateLiteral as TemplateLiteral,
yieldExpression as YieldExpression,
awaitExpression as AwaitExpression,
import as Import,
bigIntLiteral as BigIntLiteral,
exportNamespaceSpecifier as ExportNamespaceSpecifier,
optionalMemberExpression as OptionalMemberExpression,
optionalCallExpression as OptionalCallExpression,
anyTypeAnnotation as AnyTypeAnnotation,
arrayTypeAnnotation as ArrayTypeAnnotation,
booleanTypeAnnotation as BooleanTypeAnnotation,
booleanLiteralTypeAnnotation as BooleanLiteralTypeAnnotation,
nullLiteralTypeAnnotation as NullLiteralTypeAnnotation,
classImplements as ClassImplements,
declareClass as DeclareClass,
declareFunction as DeclareFunction,
declareInterface as DeclareInterface,
declareModule as DeclareModule,
declareModuleExports as DeclareModuleExports,
declareTypeAlias as DeclareTypeAlias,
declareOpaqueType as DeclareOpaqueType,
declareVariable as DeclareVariable,
declareExportDeclaration as DeclareExportDeclaration,
declareExportAllDeclaration as DeclareExportAllDeclaration,
declaredPredicate as DeclaredPredicate,
existsTypeAnnotation as ExistsTypeAnnotation,
functionTypeAnnotation as FunctionTypeAnnotation,
functionTypeParam as FunctionTypeParam,
genericTypeAnnotation as GenericTypeAnnotation,
inferredPredicate as InferredPredicate,
interfaceExtends as InterfaceExtends,
interfaceDeclaration as InterfaceDeclaration,
interfaceTypeAnnotation as InterfaceTypeAnnotation,
intersectionTypeAnnotation as IntersectionTypeAnnotation,
mixedTypeAnnotation as MixedTypeAnnotation,
emptyTypeAnnotation as EmptyTypeAnnotation,
nullableTypeAnnotation as NullableTypeAnnotation,
numberLiteralTypeAnnotation as NumberLiteralTypeAnnotation,
numberTypeAnnotation as NumberTypeAnnotation,
objectTypeAnnotation as ObjectTypeAnnotation,
objectTypeInternalSlot as ObjectTypeInternalSlot,
objectTypeCallProperty as ObjectTypeCallProperty,
objectTypeIndexer as ObjectTypeIndexer,
objectTypeProperty as ObjectTypeProperty,
objectTypeSpreadProperty as ObjectTypeSpreadProperty,
opaqueType as OpaqueType,
qualifiedTypeIdentifier as QualifiedTypeIdentifier,
stringLiteralTypeAnnotation as StringLiteralTypeAnnotation,
stringTypeAnnotation as StringTypeAnnotation,
symbolTypeAnnotation as SymbolTypeAnnotation,
thisTypeAnnotation as ThisTypeAnnotation,
tupleTypeAnnotation as TupleTypeAnnotation,
typeofTypeAnnotation as TypeofTypeAnnotation,
typeAlias as TypeAlias,
typeAnnotation as TypeAnnotation,
typeCastExpression as TypeCastExpression,
typeParameter as TypeParameter,
typeParameterDeclaration as TypeParameterDeclaration,
typeParameterInstantiation as TypeParameterInstantiation,
unionTypeAnnotation as UnionTypeAnnotation,
variance as Variance,
voidTypeAnnotation as VoidTypeAnnotation,
enumDeclaration as EnumDeclaration,
enumBooleanBody as EnumBooleanBody,
enumNumberBody as EnumNumberBody,
enumStringBody as EnumStringBody,
enumSymbolBody as EnumSymbolBody,
enumBooleanMember as EnumBooleanMember,
enumNumberMember as EnumNumberMember,
enumStringMember as EnumStringMember,
enumDefaultedMember as EnumDefaultedMember,
jsxAttribute as JSXAttribute,
jsxClosingElement as JSXClosingElement,
jsxElement as JSXElement,
jsxEmptyExpression as JSXEmptyExpression,
jsxExpressionContainer as JSXExpressionContainer,
jsxSpreadChild as JSXSpreadChild,
jsxIdentifier as JSXIdentifier,
jsxMemberExpression as JSXMemberExpression,
jsxNamespacedName as JSXNamespacedName,
jsxOpeningElement as JSXOpeningElement,
jsxSpreadAttribute as JSXSpreadAttribute,
jsxText as JSXText,
jsxFragment as JSXFragment,
jsxOpeningFragment as JSXOpeningFragment,
jsxClosingFragment as JSXClosingFragment,
noop as Noop,
placeholder as Placeholder,
v8IntrinsicIdentifier as V8IntrinsicIdentifier,
argumentPlaceholder as ArgumentPlaceholder,
bindExpression as BindExpression,
classProperty as ClassProperty,
pipelineTopicExpression as PipelineTopicExpression,
pipelineBareFunction as PipelineBareFunction,
pipelinePrimaryTopicReference as PipelinePrimaryTopicReference,
classPrivateProperty as ClassPrivateProperty,
classPrivateMethod as ClassPrivateMethod,
importAttribute as ImportAttribute,
decorator as Decorator,
doExpression as DoExpression,
exportDefaultSpecifier as ExportDefaultSpecifier,
privateName as PrivateName,
recordExpression as RecordExpression,
tupleExpression as TupleExpression,
decimalLiteral as DecimalLiteral,
staticBlock as StaticBlock,
tsParameterProperty as TSParameterProperty,
tsDeclareFunction as TSDeclareFunction,
tsDeclareMethod as TSDeclareMethod,
tsQualifiedName as TSQualifiedName,
tsCallSignatureDeclaration as TSCallSignatureDeclaration,
tsConstructSignatureDeclaration as TSConstructSignatureDeclaration,
tsPropertySignature as TSPropertySignature,
tsMethodSignature as TSMethodSignature,
tsIndexSignature as TSIndexSignature,
tsAnyKeyword as TSAnyKeyword,
tsBooleanKeyword as TSBooleanKeyword,
tsBigIntKeyword as TSBigIntKeyword,
tsIntrinsicKeyword as TSIntrinsicKeyword,
tsNeverKeyword as TSNeverKeyword,
tsNullKeyword as TSNullKeyword,
tsNumberKeyword as TSNumberKeyword,
tsObjectKeyword as TSObjectKeyword,
tsStringKeyword as TSStringKeyword,
tsSymbolKeyword as TSSymbolKeyword,
tsUndefinedKeyword as TSUndefinedKeyword,
tsUnknownKeyword as TSUnknownKeyword,
tsVoidKeyword as TSVoidKeyword,
tsThisType as TSThisType,
tsFunctionType as TSFunctionType,
tsConstructorType as TSConstructorType,
tsTypeReference as TSTypeReference,
tsTypePredicate as TSTypePredicate,
tsTypeQuery as TSTypeQuery,
tsTypeLiteral as TSTypeLiteral,
tsArrayType as TSArrayType,
tsTupleType as TSTupleType,
tsOptionalType as TSOptionalType,
tsRestType as TSRestType,
tsNamedTupleMember as TSNamedTupleMember,
tsUnionType as TSUnionType,
tsIntersectionType as TSIntersectionType,
tsConditionalType as TSConditionalType,
tsInferType as TSInferType,
tsParenthesizedType as TSParenthesizedType,
tsTypeOperator as TSTypeOperator,
tsIndexedAccessType as TSIndexedAccessType,
tsMappedType as TSMappedType,
tsLiteralType as TSLiteralType,
tsExpressionWithTypeArguments as TSExpressionWithTypeArguments,
tsInterfaceDeclaration as TSInterfaceDeclaration,
tsInterfaceBody as TSInterfaceBody,
tsTypeAliasDeclaration as TSTypeAliasDeclaration,
tsAsExpression as TSAsExpression,
tsTypeAssertion as TSTypeAssertion,
tsEnumDeclaration as TSEnumDeclaration,
tsEnumMember as TSEnumMember,
tsModuleDeclaration as TSModuleDeclaration,
tsModuleBlock as TSModuleBlock,
tsImportType as TSImportType,
tsImportEqualsDeclaration as TSImportEqualsDeclaration,
tsExternalModuleReference as TSExternalModuleReference,
tsNonNullExpression as TSNonNullExpression,
tsExportAssignment as TSExportAssignment,
tsNamespaceExportDeclaration as TSNamespaceExportDeclaration,
tsTypeAnnotation as TSTypeAnnotation,
tsTypeParameterInstantiation as TSTypeParameterInstantiation,
tsTypeParameterDeclaration as TSTypeParameterDeclaration,
tsTypeParameter as TSTypeParameter,
numberLiteral as NumberLiteral,
regexLiteral as RegexLiteral,
restProperty as RestProperty,
spreadProperty as SpreadProperty,
} from "./index";

View File

@ -1,16 +1,32 @@
// @flow
import {
isJSXText,
isJSXExpressionContainer,
isJSXEmptyExpression,
} from "../../validators/generated";
import cleanJSXElementLiteralChild from "../../utils/react/cleanJSXElementLiteralChild";
import type * as t from "../..";
export default function buildChildren(node: Object): Array<Object> {
type ReturnedChild =
| t.JSXExpressionContainer
| t.JSXSpreadChild
| t.JSXElement
| t.JSXFragment
| t.Expression;
export default function buildChildren(node: {
children: ReadonlyArray<
| t.JSXText
| t.JSXExpressionContainer
| t.JSXSpreadChild
| t.JSXElement
| t.JSXFragment
| t.JSXEmptyExpression
>;
}): ReturnedChild[] {
const elements = [];
for (let i = 0; i < node.children.length; i++) {
let child = node.children[i];
let child: any = node.children[i];
if (isJSXText(child)) {
cleanJSXElementLiteralChild(child, elements);

View File

@ -1,14 +1,15 @@
import { tsUnionType } from "../generated";
import removeTypeDuplicates from "../../modifications/typescript/removeTypeDuplicates";
import type * as t from "../..";
/**
* Takes an array of `types` and flattens them, removing duplicates and
* returns a `UnionTypeAnnotation` node containing them.
*/
export default function createTSUnionType(
typeAnnotations: Array<Object>,
): Object {
const types = typeAnnotations.map(type => type.typeAnnotations);
typeAnnotations: Array<t.TSTypeAnnotation>,
): t.TSType {
const types = typeAnnotations.map(type => type.typeAnnotation);
const flattened = removeTypeDuplicates(types);
if (flattened.length === 1) {

View File

@ -1,12 +1,11 @@
// @flow
import cloneNode from "./cloneNode";
import type * as t from "..";
/**
* Create a shallow clone of a `node`, including only
* properties belonging to the node.
* @deprecated Use t.cloneNode instead.
*/
export default function clone<T: Object>(node: T): T {
export default function clone<T extends t.Node>(node: T): T {
return cloneNode(node, /* deep */ false);
}

View File

@ -1,12 +1,11 @@
// @flow
import cloneNode from "./cloneNode";
import type * as t from "..";
/**
* Create a deep clone of a `node` and all of it's child nodes
* including only properties belonging to the node.
* @deprecated Use t.cloneNode instead.
*/
export default function cloneDeep<T: Object>(node: T): T {
export default function cloneDeep<T extends t.Node>(node: T): T {
return cloneNode(node);
}

View File

@ -1,10 +1,10 @@
// @flow
import cloneNode from "./cloneNode";
import type * as t from "..";
/**
* Create a deep clone of a `node` and all of it's child nodes
* including only properties belonging to the node.
* excluding `_private` and location properties.
*/
export default function cloneDeepWithoutLoc<T: Object>(node: T): T {
export default function cloneDeepWithoutLoc<T extends t.Node>(node: T): T {
return cloneNode(node, /* deep */ true, /* withoutLoc */ true);
}

View File

@ -1,4 +1,6 @@
import { NODE_FIELDS } from "../definitions";
import type * as t from "..";
import { isFile, isIdentifier } from "../validators/generated";
const has = Function.call.bind(Object.prototype.hasOwnProperty);
@ -23,7 +25,7 @@ function cloneIfNodeOrArray(obj, deep, withoutLoc) {
* If the second parameter is `false`, cloneNode performs a shallow clone.
* If the third parameter is true, the cloned nodes exclude location properties.
*/
export default function cloneNode<T: Object>(
export default function cloneNode<T extends t.Node>(
node: T,
deep: boolean = true,
withoutLoc: boolean = false,
@ -31,10 +33,10 @@ export default function cloneNode<T: Object>(
if (!node) return node;
const { type } = node;
const newNode = (({ type }: any): T);
const newNode: any = { type: node.type };
// Special-case identifiers since they are the most cloned nodes.
if (type === "Identifier") {
if (isIdentifier(node)) {
newNode.name = node.name;
if (has(node, "optional") && typeof node.optional === "boolean") {
@ -53,7 +55,7 @@ export default function cloneNode<T: Object>(
if (has(node, field)) {
if (deep) {
newNode[field] =
type === "File" && field === "comments"
isFile(node) && field === "comments"
? maybeCloneComments(node.comments, deep, withoutLoc)
: cloneIfNodeOrArray(node[field], true, withoutLoc);
} else {
@ -100,8 +102,15 @@ export default function cloneNode<T: Object>(
return newNode;
}
function cloneCommentsWithoutLoc<T: Object>(comments: T[]): T {
return comments.map(({ type, value }) => ({ type, value, loc: null }));
function cloneCommentsWithoutLoc<T extends t.Comment>(comments: T[]): T[] {
return comments.map(
({ type, value }) =>
({
type,
value,
loc: null,
} as T),
);
}
function maybeCloneComments(comments, deep, withoutLoc) {

View File

@ -1,8 +1,9 @@
// @flow
import cloneNode from "./cloneNode";
import type * as t from "..";
/**
* Create a shallow clone of a `node` excluding `_private` and location properties.
*/
export default function cloneWithoutLoc<T: Object>(node: T): T {
export default function cloneWithoutLoc<T extends t.Node>(node: T): T {
return cloneNode(node, /* deep */ false, /* withoutLoc */ true);
}

View File

@ -1,12 +1,12 @@
// @flow
import addComments from "./addComments";
import type * as t from "..";
/**
* Add comment of certain type to a node.
*/
export default function addComment<T: Object>(
export default function addComment<T extends t.Node>(
node: T,
type: string,
type: t.CommentTypeShorthand,
content: string,
line?: boolean,
): T {
@ -14,6 +14,6 @@ export default function addComment<T: Object>(
{
type: line ? "CommentLine" : "CommentBlock",
value: content,
},
} as t.Comment,
]);
}

View File

@ -1,12 +1,12 @@
// @flow
import type * as t from "..";
/**
* Add comments of certain type to a node.
*/
export default function addComments<T: Object>(
export default function addComments<T extends t.Node>(
node: T,
type: string,
comments: Array<Object>,
type: t.CommentTypeShorthand,
comments: ReadonlyArray<t.Comment>,
): T {
if (!comments || !node) return node;

View File

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

View File

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

View File

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

View File

@ -1,14 +1,14 @@
// @flow
import inheritTrailingComments from "./inheritTrailingComments";
import inheritLeadingComments from "./inheritLeadingComments";
import inheritInnerComments from "./inheritInnerComments";
import type * as t from "..";
/**
* Inherit all unique comments from `parent` node to `child` node.
*/
export default function inheritsComments<T: Object>(
export default function inheritsComments<T extends t.Node>(
child: T,
parent: Object,
parent: t.Node,
): T {
inheritTrailingComments(child, parent);
inheritLeadingComments(child, parent);

View File

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

View File

@ -1,4 +1,3 @@
// @flow
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'

View File

@ -1,4 +1,3 @@
// @flow
export const STATEMENT_OR_BLOCK_KEYS = ["consequent", "body", "alternate"];
export const FLATTENABLE_KEYS = ["body", "expressions"];
export const FOR_INIT_KEYS = ["left", "init"];

View File

@ -0,0 +1,8 @@
// NOTE: this actually uses Scope from @babel/traverse, but we can't add a dependency on its types,
// because this would be cyclic dependency. Declare the structural subset that is required.
import type * as t from "..";
export type Scope = {
push(value: { id: t.LVal; kind: "var"; init?: t.Expression }): void;
buildUndefinedNode(): t.Node;
};

View File

@ -1,5 +1,5 @@
// @flow
import toBlock from "./toBlock";
import type * as t from "..";
/**
* Ensure the `key` (defaults to "body") of a `node` is a block.
@ -8,8 +8,8 @@ import toBlock from "./toBlock";
* Returns the BlockStatement
*/
export default function ensureBlock(
node: Object,
node: t.Node,
key: string = "body",
): Object {
): t.BlockStatement {
return (node[key] = toBlock(node[key], node));
}

View File

@ -1,5 +1,3 @@
// @flow
import type { Scope } from "@babel/traverse";
import getBindingIdentifiers from "../retrievers/getBindingIdentifiers";
import {
isExpression,
@ -15,12 +13,14 @@ import {
conditionalExpression,
} from "../builders/generated";
import cloneNode from "../clone/cloneNode";
import type * as t from "..";
import type { Scope } from "./Scope";
export default function gatherSequenceExpressions(
nodes: Array<Object>,
nodes: ReadonlyArray<t.Node>,
scope: Scope,
declars: Array<Object>,
): ?Object {
declars: Array<any>,
): t.SequenceExpression {
const exprs = [];
let ensureLastUndefined = true;
@ -38,7 +38,7 @@ export default function gatherSequenceExpressions(
} else if (isVariableDeclaration(node)) {
if (node.kind !== "var") return; // bailed
for (const declar of (node.declarations: Array<any>)) {
for (const declar of node.declarations) {
const bindings = getBindingIdentifiers(declar);
for (const key of Object.keys(bindings)) {
declars.push({
@ -62,6 +62,7 @@ export default function gatherSequenceExpressions(
: scope.buildUndefinedNode();
if (!consequent || !alternate) return; // bailed
// @ts-expect-error todo(flow->ts) consequent - Argument of type 'Node' is not assignable to parameter of type 'Expression'
exprs.push(conditionalExpression(node.test, consequent, alternate));
} else if (isBlockStatement(node)) {
const body = gatherSequenceExpressions(node.body, scope, declars);

View File

@ -1,4 +1,3 @@
// @flow
import toIdentifier from "./toIdentifier";
export default function toBindingIdentifierName(name: string): string {

View File

@ -1,4 +1,3 @@
// @flow
import {
isBlockStatement,
isFunction,
@ -10,8 +9,12 @@ import {
expressionStatement,
blockStatement,
} from "../builders/generated";
import type * as t from "..";
export default function toBlock(node: Object, parent: Object): Object {
export default function toBlock(
node: t.Statement | t.Expression,
parent?: t.Node,
): t.BlockStatement {
if (isBlockStatement(node)) {
return node;
}

View File

@ -1,11 +1,18 @@
// @flow
import { isIdentifier } from "../validators/generated";
import { stringLiteral } from "../builders/generated";
import type * as t from "..";
export default function toComputedKey(
node: Object,
key: Object = node.key || node.property,
): Object {
node:
| t.ObjectMember
| t.ObjectProperty
| t.ClassMethod
| t.ClassProperty
| t.MemberExpression
| t.OptionalMemberExpression,
// @ts-expect-error todo(flow->ts): maybe check the type of node before accessing .key and .property
key: t.Expression = node.key || node.property,
) {
if (!node.computed && isIdentifier(key)) key = stringLiteral(key.name);
return key;

View File

@ -1,12 +1,22 @@
// @flow
import {
isExpression,
isFunction,
isClass,
isExpressionStatement,
} from "../validators/generated";
import type * as t from "..";
export default function toExpression(node: Object): Object {
export default toExpression as {
(node: t.Function): t.FunctionExpression;
(node: t.Class): t.ClassExpression;
(
node: t.ExpressionStatement | t.Expression | t.Class | t.Function,
): t.Expression;
};
function toExpression(
node: t.ExpressionStatement | t.Expression | t.Class | t.Function,
): t.Expression {
if (isExpressionStatement(node)) {
node = node.expression;
}
@ -25,8 +35,10 @@ export default function toExpression(node: Object): Object {
// ClassDeclaration -> ClassExpression
// FunctionDeclaration, ObjectMethod, ClassMethod -> FunctionExpression
if (isClass(node)) {
// @ts-expect-error todo(flow->ts): avoid type unsafe mutations
node.type = "ClassExpression";
} else if (isFunction(node)) {
// @ts-expect-error todo(flow->ts): avoid type unsafe mutations
node.type = "FunctionExpression";
}

View File

@ -1,4 +1,3 @@
// @flow
import isValidIdentifier from "../validators/isValidIdentifier";
export default function toIdentifier(name: string): string {

View File

@ -1,14 +1,15 @@
// @flow
import { isIdentifier, isStringLiteral } from "../validators/generated";
import cloneNode from "../clone/cloneNode";
import removePropertiesDeep from "../modifications/removePropertiesDeep";
import type * as t from "..";
export default function toKeyAlias(
node: Object,
key: Object = node.key,
node: t.Method | t.Property,
key: t.Node = node.key,
): string {
let alias;
// @ts-expect-error todo(flow->ts): maybe add node type check before checking `.kind`
if (node.kind === "method") {
return toKeyAlias.increment() + "";
} else if (isIdentifier(key)) {
@ -19,10 +20,12 @@ export default function toKeyAlias(
alias = JSON.stringify(removePropertiesDeep(cloneNode(key)));
}
// @ts-expect-error todo(flow->ts): maybe add node type check before checking `.computed`
if (node.computed) {
alias = `[${alias}]`;
}
// @ts-expect-error todo(flow->ts): maybe add node type check before checking `.static`
if (node.static) {
alias = `static:${alias}`;
}

View File

@ -1,6 +1,6 @@
// @flow
import type { Scope } from "@babel/traverse";
import gatherSequenceExpressions from "./gatherSequenceExpressions";
import type * as t from "..";
import type { Scope } from "./Scope";
/**
* Turn an array of statement `nodes` into a `SequenceExpression`.
@ -11,9 +11,9 @@ import gatherSequenceExpressions from "./gatherSequenceExpressions";
* Expression statements are just resolved to their expression.
*/
export default function toSequenceExpression(
nodes: Array<Object>,
nodes: ReadonlyArray<t.Node>,
scope: Scope,
): ?Object {
): t.SequenceExpression | undefined {
if (!nodes?.length) return;
const declars = [];

View File

@ -1,4 +1,3 @@
// @flow
import {
isStatement,
isFunction,
@ -6,8 +5,25 @@ import {
isAssignmentExpression,
} from "../validators/generated";
import { expressionStatement } from "../builders/generated";
import type * as t from "..";
export default function toStatement(node: Object, ignore?: boolean) {
export default toStatement as {
(node: t.AssignmentExpression, ignore?: boolean): t.ExpressionStatement;
<T extends t.Statement>(node: T, ignore: false): T;
<T extends t.Statement>(node: T, ignore?: boolean): T | false;
(node: t.Class, ignore: false): t.ClassDeclaration;
(node: t.Class, ignore?: boolean): t.ClassDeclaration | false;
(node: t.Function, ignore: false): t.FunctionDeclaration;
(node: t.Function, ignore?: boolean): t.FunctionDeclaration | false;
(node: t.Node, ignore: false): t.Statement;
(node: t.Node, ignore?: boolean): t.Statement | false;
};
function toStatement(node: t.Node, ignore?: boolean): t.Statement | false {
if (isStatement(node)) {
return node;
}
@ -25,6 +41,7 @@ export default function toStatement(node: Object, ignore?: boolean) {
return expressionStatement(node);
}
// @ts-expect-error todo(flow->ts): node.id might be missing
if (mustHaveId && !node.id) {
newType = false;
}
@ -39,5 +56,6 @@ export default function toStatement(node: Object, ignore?: boolean) {
node.type = newType;
// @ts-expect-error todo(flow->ts) refactor to avoid type unsafe mutations like reassigning node type above
return node;
}

View File

@ -1,4 +1,3 @@
// @flow
import isPlainObject from "lodash/isPlainObject";
import isRegExp from "lodash/isRegExp";
import isValidIdentifier from "../validators/isValidIdentifier";
@ -15,8 +14,26 @@ import {
unaryExpression,
binaryExpression,
} from "../builders/generated";
import type * as t from "..";
export default function valueToNode(value: any): Object {
export default valueToNode as {
(value: undefined): t.Identifier; // TODO: This should return "void 0"
(value: boolean): t.BooleanLiteral;
(value: null): t.NullLiteral;
(value: string): t.StringLiteral;
// Infinities and NaN need to use a BinaryExpression; negative values must be wrapped in UnaryExpression
(value: number): t.NumericLiteral | t.BinaryExpression | t.UnaryExpression;
(value: RegExp): t.RegExpLiteral;
(value: ReadonlyArray<unknown>): t.ArrayExpression;
// this throws with objects that are not PlainObject according to lodash,
// or if there are non-valueToNode-able values
(value: object): t.ObjectExpression;
(value: unknown): t.Expression;
};
function valueToNode(value: unknown): t.Expression {
// undefined
if (value === undefined) {
return identifier("undefined");

View File

@ -1,5 +1,3 @@
// @flow
import is from "../validators/is";
import isValidIdentifier from "../validators/isValidIdentifier";
import { isKeyword, isReservedWord } from "@babel/helper-validator-identifier";
@ -1708,7 +1706,7 @@ export const classMethodOrPropertyCommon = {
);
const computed = assertNodeType("Expression");
return function (node: Object, key: string, val: any) {
return function (node: any, key: string, val: any) {
const validator = node.computed ? computed : normal;
validator(node, key, val);
};

View File

@ -1,4 +1,3 @@
// @flow
import defineType, {
assertEach,
assertNodeType,

View File

@ -1,4 +1,3 @@
// @flow
import defineType, {
arrayOfType,
assertOneOf,

View File

@ -1,4 +1,3 @@
// @flow
import toFastProperties from "to-fast-properties";
import "./core";
import "./flow";

View File

@ -1,4 +1,3 @@
// @flow
import defineType, {
assertNodeType,
assertValueType,

View File

@ -1,4 +1,3 @@
// @flow
import defineType, {
assertNodeType,
assertOneOf,

View File

@ -11,7 +11,7 @@ export const PLACEHOLDERS = [
"Pattern",
];
export const PLACEHOLDERS_ALIAS: { [string]: Array<string> } = {
export const PLACEHOLDERS_ALIAS: Record<string, string[]> = {
Declaration: ["Statement"],
Pattern: ["PatternLike", "LVal"],
};
@ -21,7 +21,7 @@ for (const type of PLACEHOLDERS) {
if (alias?.length) PLACEHOLDERS_ALIAS[type] = alias;
}
export const PLACEHOLDERS_FLIPPED_ALIAS: { [string]: Array<string> } = {};
export const PLACEHOLDERS_FLIPPED_ALIAS: Record<string, string[]> = {};
Object.keys(PLACEHOLDERS_ALIAS).forEach(type => {
PLACEHOLDERS_ALIAS[type].forEach(alias => {

View File

@ -1,4 +1,3 @@
// @flow
import defineType, {
arrayOfType,
assertEach,

View File

@ -1,13 +1,12 @@
// @flow
import is from "../validators/is";
import { validateField, validateChild } from "../validators/validate";
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 } = {};
export const VISITOR_KEYS: Record<string, string[]> = {};
export const ALIAS_KEYS: Record<string, string[]> = {};
export const FLIPPED_ALIAS_KEYS: Record<string, string[]> = {};
export const NODE_FIELDS: Record<string, {}> = {};
export const BUILDER_KEYS: Record<string, string[]> = {};
export const DEPRECATED_KEYS: Record<string, string> = {};
export const NODE_PARENT_VALIDATIONS = {};
function getType(val) {
@ -21,12 +20,16 @@ function getType(val) {
}
// TODO: Import and use Node instead of any
type Validator = (any, string, any) => void;
type Validator = { chainOf?: Validator[] } & ((
parent: any,
key: string,
node: any,
) => void);
type FieldOptions = {
default?: any,
optional?: boolean,
validate?: Validator,
default?: any;
optional?: boolean;
validate?: Validator;
};
export function validate(validate: Validator): FieldOptions {
@ -81,7 +84,7 @@ export function assertEach(callback: Validator): Validator {
}
export function assertOneOf(...values: Array<any>): Validator {
function validate(node: Object, key: string, val: any) {
function validate(node: any, key: string, val: any) {
if (values.indexOf(val) < 0) {
throw new TypeError(
`Property ${key} expected value to be one of ${JSON.stringify(
@ -158,7 +161,7 @@ export function assertValueType(type: string): Validator {
return validate;
}
export function assertShape(shape: { [string]: FieldOptions }): Validator {
export function assertShape(shape: { [x: string]: FieldOptions }): Validator {
function validate(node, key, val) {
const errors = [];
for (const property of Object.keys(shape)) {
@ -215,11 +218,11 @@ export function assertOptionalChainStart(): Validator {
}
export function chain(...fns: Array<Validator>): Validator {
function validate(...args) {
const validate: Validator = function (...args) {
for (const fn of fns) {
fn(...args);
}
}
};
validate.chainOf = fns;
return validate;
}
@ -239,14 +242,14 @@ export default function defineType(
type: string,
opts: {
fields?: {
[string]: FieldOptions,
},
visitor?: Array<string>,
aliases?: Array<string>,
builder?: Array<string>,
inherits?: string,
deprecatedAlias?: string,
validate?: Validator,
[x: string]: FieldOptions;
};
visitor?: Array<string>;
aliases?: Array<string>;
builder?: Array<string>;
inherits?: string;
deprecatedAlias?: string;
validate?: Validator;
} = {},
) {
const inherits = (opts.inherits && store[opts.inherits]) || {};
@ -256,7 +259,7 @@ export default function defineType(
fields = {};
if (inherits.fields) {
const keys = Object.getOwnPropertyNames(inherits.fields);
for (const key of (keys: Array<string>)) {
for (const key of keys) {
const field = inherits.fields[key];
fields[key] = {
default: field.default,
@ -272,7 +275,7 @@ export default function defineType(
const builder: Array<string> =
opts.builder || inherits.builder || opts.visitor || [];
for (const k of (Object.keys(opts): Array<string>)) {
for (const k of Object.keys(opts)) {
if (validTypeOpts.indexOf(k) === -1) {
throw new Error(`Unknown type option "${k}" on ${type}`);
}
@ -283,7 +286,7 @@ export default function defineType(
}
// ensure all field keys are represented in `fields`
for (const key of (visitor.concat(builder): Array<string>)) {
for (const key of visitor.concat(builder)) {
fields[key] = fields[key] || {};
}
@ -299,7 +302,7 @@ export default function defineType(
field.validate = assertValueType(getType(field.default));
}
for (const k of (Object.keys(field): Array<string>)) {
for (const k of Object.keys(field)) {
if (validFieldKeys.indexOf(k) === -1) {
throw new Error(`Unknown field key "${k}" on ${type}.${key}`);
}

View File

@ -1,4 +1,3 @@
// @flow
import isReactComponent from "./validators/react/isReactComponent";
import isCompatTag from "./validators/react/isCompatTag";
import buildChildren from "./builders/react/buildChildren";
@ -9,10 +8,12 @@ export * from "./asserts/generated";
// builders
export { default as createTypeAnnotationBasedOnTypeof } from "./builders/flow/createTypeAnnotationBasedOnTypeof";
/** @deprecated use createFlowUnionType instead */
export { default as createUnionTypeAnnotation } from "./builders/flow/createFlowUnionType";
export { default as createFlowUnionType } from "./builders/flow/createFlowUnionType";
export { default as createTSUnionType } from "./builders/typescript/createTSUnionType";
export * from "./builders/generated";
export * from "./builders/generated/uppercase";
// clone
export { default as cloneNode } from "./clone/cloneNode";
@ -63,7 +64,7 @@ export { default as getOuterBindingIdentifiers } from "./retrievers/getOuterBind
// traverse
export { default as traverse } from "./traverse/traverse";
export type * from "./traverse/traverse";
export * from "./traverse/traverse";
export { default as traverseFast } from "./traverse/traverseFast";
// utils
@ -96,3 +97,5 @@ export const react = {
isCompatTag,
buildChildren,
};
export * from "./ast-types/generated";

View File

@ -1,14 +1,14 @@
// @flow
import { memberExpression } from "../builders/generated";
import type * as t from "..";
/**
* Append a node to a member expression.
*/
export default function appendToMemberExpression<T: Object>(
member: T,
append: Object,
computed?: boolean = false,
): T {
export default function appendToMemberExpression(
member: t.MemberExpression,
append: t.MemberExpression["property"],
computed: boolean = false,
): t.MemberExpression {
member.object = memberExpression(
member.object,
member.property,

View File

@ -1,17 +1,24 @@
// @flow
import {
isAnyTypeAnnotation,
isGenericTypeAnnotation,
isUnionTypeAnnotation,
isFlowBaseAnnotation,
isIdentifier,
} from "../../validators/generated";
import type * as t from "../..";
function getQualifiedName(node: t.GenericTypeAnnotation["id"]) {
return isIdentifier(node)
? node.name
: `${node.id.name}.${getQualifiedName(node.qualification)}`;
}
/**
* Dedupe type annotations.
*/
export default function removeTypeDuplicates(
nodes: Array<Object>,
): Array<Object> {
nodes: ReadonlyArray<t.FlowType | false | null | undefined>,
): t.FlowType[] {
const generics = {};
const bases = {};
@ -49,7 +56,7 @@ export default function removeTypeDuplicates(
// find a matching generic type and merge and deduplicate the type parameters
if (isGenericTypeAnnotation(node)) {
const name = node.id.name;
const name = getQualifiedName(node.id);
if (generics[name]) {
let existing = generics[name];

View File

@ -1,15 +1,18 @@
// @flow
import { INHERIT_KEYS } from "../constants";
import inheritsComments from "../comments/inheritsComments";
import type * as t from "..";
/**
* Inherit all contextual properties from `parent` node to `child` node.
*/
export default function inherits<T: Object>(child: T, parent: Object): T {
export default function inherits<T extends t.Node | null | undefined>(
child: T,
parent: t.Node | null | undefined,
): T {
if (!child || !parent) return child;
// optionally inherit specific properties if not null
for (const key of (INHERIT_KEYS.optional: Array<string>)) {
for (const key of INHERIT_KEYS.optional) {
if (child[key] == null) {
child[key] = parent[key];
}
@ -21,7 +24,7 @@ export default function inherits<T: Object>(child: T, parent: Object): T {
}
// force inherit select properties
for (const key of (INHERIT_KEYS.force: Array<string>)) {
for (const key of INHERIT_KEYS.force) {
child[key] = parent[key];
}

View File

@ -1,13 +1,12 @@
// @flow
import { memberExpression } from "../builders/generated";
import type * as t from "..";
/**
* Prepend a node to a member expression.
*/
export default function prependToMemberExpression<T: Object>(
member: T,
prepend: Object,
): T {
export default function prependToMemberExpression<
T extends Pick<t.MemberExpression, "object" | "property">
>(member: T, prepend: t.MemberExpression["object"]): T {
member.object = memberExpression(prepend, member.object);
return member;

View File

@ -1,5 +1,5 @@
// @flow
import { COMMENT_KEYS } from "../constants";
import type * as t from "..";
const CLEAR_KEYS = ["tokens", "start", "end", "loc", "raw", "rawValue"];
@ -12,8 +12,8 @@ const CLEAR_KEYS_PLUS_COMMENTS = COMMENT_KEYS.concat(["comments"]).concat(
* properties like location data and raw token data.
*/
export default function removeProperties(
node: Object,
opts?: Object = {},
node: t.Node,
opts: { preserveComments?: boolean } = {},
): void {
const map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS;
for (const key of map) {

View File

@ -1,10 +1,10 @@
// @flow
import traverseFast from "../traverse/traverseFast";
import removeProperties from "./removeProperties";
import type * as t from "..";
export default function removePropertiesDeep<T: Object>(
export default function removePropertiesDeep<T extends t.Node>(
tree: T,
opts?: Object,
opts?: { preserveComments: boolean } | null,
): T {
traverseFast(tree, removeProperties, opts);

View File

@ -3,13 +3,14 @@ import {
isTSUnionType,
isTSBaseType,
} from "../../validators/generated";
import type * as t from "../..";
/**
* Dedupe type annotations.
*/
export default function removeTypeDuplicates(
nodes: Array<Object>,
): Array<Object> {
nodes: Array<t.TSType>,
): Array<t.TSType> {
const generics = {};
const bases = {};
@ -28,7 +29,7 @@ export default function removeTypeDuplicates(
}
// this type matches anything
if (isTSAnyKeyword(node.type)) {
if (isTSAnyKeyword(node)) {
return [node];
}

View File

@ -1,20 +1,41 @@
// @flow
import {
isExportDeclaration,
isIdentifier,
isDeclaration,
isFunctionDeclaration,
isFunctionExpression,
isExportAllDeclaration,
} from "../validators/generated";
import type * as t from "..";
export { getBindingIdentifiers as default };
function getBindingIdentifiers(
node: t.Node,
duplicates: true,
outerOnly?: boolean,
): Record<string, Array<t.Identifier>>;
function getBindingIdentifiers(
node: t.Node,
duplicates?: false,
outerOnly?: boolean,
): Record<string, t.Identifier>;
function getBindingIdentifiers(
node: t.Node,
duplicates?: boolean,
outerOnly?: boolean,
): Record<string, t.Identifier> | Record<string, Array<t.Identifier>>;
/**
* Return a list of binding identifiers associated with the input `node`.
*/
export default function getBindingIdentifiers(
node: Object,
function getBindingIdentifiers(
node: t.Node,
duplicates?: boolean,
outerOnly?: boolean,
): { [string]: Object | Array<Object> } {
): Record<string, t.Identifier> | Record<string, Array<t.Identifier>> {
let search = [].concat(node);
const ids = Object.create(null);
@ -34,7 +55,7 @@ export default function getBindingIdentifiers(
continue;
}
if (isExportDeclaration(id)) {
if (isExportDeclaration(id) && !isExportAllDeclaration(id)) {
if (isDeclaration(id.declaration)) {
search.push(id.declaration);
}

View File

@ -1,9 +1,17 @@
// @flow
import getBindingIdentifiers from "./getBindingIdentifiers";
import type * as t from "..";
export default function getOuterBindingIdentifiers(
node: Object,
duplicates?: boolean,
): { [string]: Object | Array<Object> } {
export default getOuterBindingIdentifiers as {
(node: t.Node, duplicates: true): Record<string, Array<t.Identifier>>;
(node: t.Node, duplicates?: false): Record<string, t.Identifier>;
(node: t.Node, duplicates?: boolean):
| Record<string, t.Identifier>
| Record<string, Array<t.Identifier>>;
};
function getOuterBindingIdentifiers(
node: t.Node,
duplicates: boolean,
): Record<string, t.Identifier> | Record<string, Array<t.Identifier>> {
return getBindingIdentifiers(node, duplicates, true);
}

View File

@ -1,15 +1,22 @@
// @flow
import { VISITOR_KEYS } from "../definitions";
import type * as t from "..";
export type TraversalAncestors = Array<{
node: BabelNode,
key: string,
index?: number,
node: t.Node;
key: string;
index?: number;
}>;
export type TraversalHandler<T> = (BabelNode, TraversalAncestors, T) => void;
export type TraversalHandler<T> = (
this: undefined,
node: t.Node,
parent: TraversalAncestors,
state: T,
) => void;
export type TraversalHandlers<T> = {
enter?: TraversalHandler<T>,
exit?: TraversalHandler<T>,
enter?: TraversalHandler<T>;
exit?: TraversalHandler<T>;
};
/**
@ -18,7 +25,7 @@ export type TraversalHandlers<T> = {
* AST data can be taken into account.
*/
export default function traverse<T>(
node: BabelNode,
node: t.Node,
handlers: TraversalHandler<T> | TraversalHandlers<T>,
state?: T,
): void {
@ -26,16 +33,16 @@ export default function traverse<T>(
handlers = { enter: handlers };
}
const { enter, exit } = (handlers: TraversalHandlers<T>);
const { enter, exit } = handlers as TraversalHandlers<T>;
traverseSimpleImpl(node, enter, exit, state, []);
}
function traverseSimpleImpl<T>(
node: Object,
enter: ?Function,
exit: ?Function,
state: ?T,
node: any,
enter: Function | undefined | null,
exit: Function | undefined | null,
state: T | undefined | null,
ancestors: TraversalAncestors,
) {
const keys = VISITOR_KEYS[node.type];

View File

@ -1,14 +1,15 @@
// @flow
import { VISITOR_KEYS } from "../definitions";
import type * as t from "..";
/**
* A prefix AST traversal implementation meant for simple searching
* and processing.
*/
export default function traverseFast(
node: Object,
enter: (node: BabelNode, opts?: Object) => void,
opts?: Object,
node: t.Node | null | undefined,
enter: (node: t.Node, opts?: any) => void,
// todo(flow->ts) We could parametrize opts to T rather than any, so that the type is "forwarded" to the callback.
opts?: any,
): void {
if (!node) return;

View File

@ -1,8 +1,9 @@
// @flow
import type * as t from "..";
export default function inherit(
key: string,
child: Object,
parent: Object,
child: t.Node,
parent: t.Node,
): void {
if (child && parent) {
child[key] = Array.from(

View File

@ -1,9 +1,11 @@
// @flow
import { stringLiteral } from "../../builders/generated";
import type * as t from "../..";
export default function cleanJSXElementLiteralChild(
child: { value: string },
args: Array<Object>,
child: {
value: string;
},
args: Array<t.Node>,
) {
const lines = child.value.split(/\r\n|\n|\r/);

View File

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

View File

@ -1,4 +1,5 @@
import matchesPattern from "./matchesPattern";
import type * as t from "..";
/**
* Build a function that when called will return whether or not the
@ -10,9 +11,8 @@ import matchesPattern from "./matchesPattern";
export default function buildMatchMemberExpression(
match: string,
allowPartial?: boolean,
): Object => boolean {
) {
const parts = match.split(".");
return (member: Object): boolean =>
matchesPattern(member, parts, allowPartial);
return (member: t.Node) => matchesPattern(member, parts, allowPartial);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,41 @@
// @flow
import shallowEqual from "../utils/shallowEqual";
import isType from "./isType";
import isPlaceholderType from "./isPlaceholderType";
import { FLIPPED_ALIAS_KEYS } from "../definitions";
import type * as t from "..";
export default function is<T extends t.Node["type"]>(
type: T,
node: t.Node | null | undefined,
opts?: undefined,
): node is Extract<t.Node, { type: T }>;
export default function is<
T extends t.Node["type"],
P extends Extract<t.Node, { type: T }>
>(type: T, n: t.Node | null | undefined, required: Partial<P>): n is P;
export default function is<P extends t.Node>(
type: string,
node: t.Node | null | undefined,
opts: Partial<P>,
): node is P;
export default function is(
type: string,
node: t.Node | null | undefined,
opts?: Partial<t.Node>,
): node is t.Node;
/**
* Returns whether `node` is of given `type`.
*
* For better performance, use this instead of `is[Type]` when `type` is unknown.
*/
export default function is(type: string, node: Object, opts?: Object): boolean {
export default function is(
type: string,
node: t.Node | null | undefined,
opts?: Partial<t.Node>,
): node is t.Node {
if (!node) return false;
const matches = isType(node.type, type);

View File

@ -1,12 +1,12 @@
// @flow
import getBindingIdentifiers from "../retrievers/getBindingIdentifiers";
import type * as t from "..";
/**
* Check if the input `node` is a binding identifier.
*/
export default function isBinding(
node: Object,
parent: Object,
grandparent?: Object,
node: t.Node,
parent: t.Node,
grandparent?: t.Node,
): boolean {
if (
grandparent &&

View File

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

View File

@ -1,11 +1,11 @@
// @flow
import isType from "./isType";
import { isIdentifier } from "./generated";
import type * as t from "..";
/**
* Check if the input `node` is definitely immutable.
*/
export default function isImmutable(node: Object): boolean {
export default function isImmutable(node: t.Node): boolean {
if (isType(node.type, "Immutable")) return true;
if (isIdentifier(node)) {

View File

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

View File

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

View File

@ -1,10 +1,13 @@
// @flow
import { NODE_FIELDS, VISITOR_KEYS } from "../definitions";
import type * as t from "..";
/**
* Check if two nodes are equivalent
*/
export default function isNodesEquivalent(a: any, b: any): boolean {
export default function isNodesEquivalent<T extends Partial<t.Node>>(
a: T,
b: any,
): b is T {
if (
typeof a !== "object" ||
typeof b !== "object" ||

View File

@ -1,4 +1,3 @@
// @flow
import { PLACEHOLDERS_ALIAS } from "../definitions";
/**
@ -10,7 +9,8 @@ export default function isPlaceholderType(
): boolean {
if (placeholderType === targetType) return true;
const aliases: ?Array<string> = PLACEHOLDERS_ALIAS[placeholderType];
const aliases: Array<string> | undefined =
PLACEHOLDERS_ALIAS[placeholderType];
if (aliases) {
for (const alias of aliases) {
if (targetType === alias) return true;

View File

@ -1,11 +1,12 @@
// @flow
import type * as t from "..";
/**
* Check if the input `node` is a reference to a bound variable.
*/
export default function isReferenced(
node: Object,
parent: Object,
grandparent?: Object,
node: t.Node,
parent: t.Node,
grandparent?: t.Node,
): boolean {
switch (parent.type) {
// yes: PARENT[NODE]
@ -15,6 +16,7 @@ export default function isReferenced(
case "JSXMemberExpression":
case "OptionalMemberExpression":
if (parent.property === node) {
// @ts-expect-error todo(flow->ts): computed is missing on JSXMemberExpression
return !!parent.computed;
}
return parent.object === node;
@ -42,6 +44,7 @@ export default function isReferenced(
case "ClassMethod":
case "ClassPrivateMethod":
case "ObjectMethod":
// @ts-expect-error todo(flow->ts) params have more specific type comparing to node
if (parent.params.includes(node)) {
return false;
}
@ -60,8 +63,10 @@ export default function isReferenced(
case "ClassProperty":
case "ClassPrivateProperty":
if (parent.key === node) {
// @ts-expect-error todo(flow->ts): computed might not exist
return !!parent.computed;
}
// @ts-expect-error todo(flow->ts): ObjectMethod does not have value property
if (parent.value === node) {
return !grandparent || grandparent.type !== "ObjectPattern";
}
@ -115,6 +120,7 @@ export default function isReferenced(
// yes: export { NODE as foo };
// no: export { NODE as foo } from "foo";
case "ExportSpecifier":
// @ts-expect-error todo(flow->ts): Property 'source' does not exist on type 'AnyTypeAnnotation'.
if (grandparent?.source) {
return false;
}

View File

@ -1,4 +1,3 @@
// @flow
import {
isFunction,
isCatchClause,
@ -6,11 +5,12 @@ import {
isScopable,
isPattern,
} from "./generated";
import type * as t from "..";
/**
* Check if the input `node` is a scope.
*/
export default function isScope(node: Object, parent: Object): boolean {
export default function isScope(node: t.Node, parent: t.Node): boolean {
// If a BlockStatement is an immediate descendent of a Function/CatchClause, it must be in the body.
// Hence we skipped the parentKey === "params" check
if (isBlockStatement(node) && (isFunction(parent) || isCatchClause(parent))) {

View File

@ -1,12 +1,15 @@
// @flow
import { isIdentifier, isImportDefaultSpecifier } from "./generated";
import type * as t from "..";
/**
* Check if the input `specifier` is a `default` import or export.
*/
export default function isSpecifierDefault(specifier: Object): boolean {
export default function isSpecifierDefault(
specifier: t.ModuleSpecifier,
): boolean {
return (
isImportDefaultSpecifier(specifier) ||
// @ts-expect-error todo(flow->ts): stricter type for specifier
isIdentifier(specifier.imported || specifier.exported, {
name: "default",
})

View File

@ -1,17 +1,30 @@
// @flow
import { FLIPPED_ALIAS_KEYS, ALIAS_KEYS } from "../definitions";
import type * as t from "..";
export default function isType<T extends t.Node["type"]>(
nodeType: string,
targetType: T,
): nodeType is T;
export default function isType(
nodeType: string | null | undefined,
targetType: string,
): boolean;
/**
* Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`.
*/
export default function isType(nodeType: ?string, targetType: string): boolean {
export default function isType(
nodeType: string | undefined | null,
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];
const aliases: Array<string> | undefined = FLIPPED_ALIAS_KEYS[targetType];
if (aliases) {
if (aliases[0] === nodeType) return true;

View File

@ -1,4 +1,3 @@
// @flow
import isValidIdentifier from "./isValidIdentifier";
const RESERVED_WORDS_ES3_ONLY: Set<string> = new Set([

View File

@ -1,4 +1,3 @@
// @flow
import {
isIdentifierName,
isStrictReservedWord,

View File

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

View File

@ -1,4 +1,5 @@
import { isIdentifier, isMemberExpression, isStringLiteral } from "./generated";
import type * as t from "..";
/**
* Determines whether or not the input node `member` matches the
@ -8,8 +9,8 @@ import { isIdentifier, isMemberExpression, isStringLiteral } from "./generated";
* parsed nodes of `React.createClass` and `React["createClass"]`.
*/
export default function matchesPattern(
member: Object,
match: string | Array<string>,
member: t.Node | null | undefined,
match: string | string[],
allowPartial?: boolean,
): boolean {
// not a member expression

View File

@ -1,4 +1,3 @@
// @flow
export default function isCompatTag(tagName?: string): boolean {
// Must start with a lowercase ASCII letter
return !!tagName && /^[a-z]/.test(tagName);

View File

@ -1,4 +1,3 @@
// @flow
import buildMatchMemberExpression from "../buildMatchMemberExpression";
const isReactComponent = buildMatchMemberExpression("React.Component");

View File

@ -1,7 +1,11 @@
// @flow
import { NODE_FIELDS, NODE_PARENT_VALIDATIONS } from "../definitions";
import type * as t from "..";
export default function validate(node?: Object, key: string, val: any): void {
export default function validate(
node: t.Node | undefined | null,
key: string,
val: any,
): void {
if (!node) return;
const fields = NODE_FIELDS[node.type];
@ -13,7 +17,7 @@ export default function validate(node?: Object, key: string, val: any): void {
}
export function validateField(
node?: Object,
node: t.Node | undefined | null,
key: string,
val: any,
field: any,
@ -24,7 +28,11 @@ export function validateField(
field.validate(node, key, val);
}
export function validateChild(node?: Object, key: string, val?: Object) {
export function validateChild(
node: t.Node | undefined | null,
key: string,
val?: any,
) {
if (val == null) return;
const validate = NODE_PARENT_VALIDATIONS[val.type];
if (!validate) return;

View File

@ -1,6 +0,0 @@
#!/bin/bash
set -e
tsFlags="--strict"
yarn tsc $tsFlags ./packages/babel-types/lib/index.d.ts

View File

@ -3381,6 +3381,8 @@ __metadata:
"@babel/generator": "workspace:*"
"@babel/helper-validator-identifier": "workspace:^7.10.4"
"@babel/parser": "workspace:*"
"@types/lodash": ^4.14.162
chalk: ^4.1.0
lodash: ^4.17.19
to-fast-properties: ^2.0.0
languageName: unknown
@ -3899,6 +3901,13 @@ __metadata:
languageName: node
linkType: hard
"@types/lodash@npm:^4.14.162":
version: 4.14.165
resolution: "@types/lodash@npm:4.14.165"
checksum: 525bfc34b0b591cc957125a961c70e63e5ad8b23cbd89b7594a5ea74823285b6d96993a7eec506e26b379ee52dc9dcd3a894ff210be4c97bccb536e62361dbc8
languageName: node
linkType: hard
"@types/minimatch@npm:*":
version: 3.0.3
resolution: "@types/minimatch@npm:3.0.3"
@ -4835,6 +4844,7 @@ __metadata:
mergeiterator: ^1.2.5
prettier: ^2.0.5
rollup: ^2.26.5
rollup-plugin-dts: ^2.0.0
rollup-plugin-node-polyfills: ^0.2.1
rollup-plugin-terser: ^7.0.0
test262-stream: ^1.3.0
@ -9709,7 +9719,7 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"magic-string@npm:^0.25.2, magic-string@npm:^0.25.3, magic-string@npm:^0.25.5":
"magic-string@npm:^0.25.2, magic-string@npm:^0.25.3, magic-string@npm:^0.25.5, magic-string@npm:^0.25.7":
version: 0.25.7
resolution: "magic-string@npm:0.25.7"
dependencies:
@ -11705,6 +11715,22 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"rollup-plugin-dts@npm:^2.0.0":
version: 2.0.0
resolution: "rollup-plugin-dts@npm:2.0.0"
dependencies:
"@babel/code-frame": ^7.10.4
magic-string: ^0.25.7
peerDependencies:
rollup: ^2.33.3
typescript: ^4.1.2
dependenciesMeta:
"@babel/code-frame":
optional: true
checksum: 858dea6359da9fd3926311f22591b51f4cd29669ab63a8556ff25eede91f2461107eec74b1d25447f9343243e21cc9091f924941baa4c9e1700ecbe4bdbe3d43
languageName: node
linkType: hard
"rollup-plugin-inject@npm:^3.0.0":
version: 3.0.2
resolution: "rollup-plugin-inject@npm:3.0.2"