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:
parent
c0a8cbd989
commit
1290d215f1
117
Gulpfile.js
117
Gulpfile.js
@ -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(
|
||||
|
||||
45
Makefile
45
Makefile
@ -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
|
||||
|
||||
@ -9,4 +9,4 @@ coverage:
|
||||
patch:
|
||||
enabled: false
|
||||
ignore:
|
||||
- packages/babel-types/src/*/generated/index.js
|
||||
- packages/babel-types/src/*/generated/*
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@ -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`;
|
||||
|
||||
139
packages/babel-types/scripts/generators/ast-types.js
Normal file
139
packages/babel-types/scripts/generators/ast-types.js
Normal 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;
|
||||
});
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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'
|
||||
*/
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;`
|
||||
);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
2518
packages/babel-types/src/ast-types/generated/index.ts
Executable file
2518
packages/babel-types/src/ast-types/generated/index.ts
Executable file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
6
packages/babel-types/src/builders/generated/uppercase.d.ts
vendored
Normal file
6
packages/babel-types/src/builders/generated/uppercase.d.ts
vendored
Normal 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 {};
|
||||
258
packages/babel-types/src/builders/generated/uppercase.js
Executable file
258
packages/babel-types/src/builders/generated/uppercase.js
Executable 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";
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
});
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
/*
|
||||
* This file is auto-generated! Do not modify it directly.
|
||||
* To re-generate run 'make build'
|
||||
|
||||
@ -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"];
|
||||
|
||||
8
packages/babel-types/src/converters/Scope.ts
Normal file
8
packages/babel-types/src/converters/Scope.ts
Normal 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;
|
||||
};
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import toIdentifier from "./toIdentifier";
|
||||
|
||||
export default function toBindingIdentifierName(name: string): string {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import isValidIdentifier from "../validators/isValidIdentifier";
|
||||
|
||||
export default function toIdentifier(name: string): string {
|
||||
|
||||
@ -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}`;
|
||||
}
|
||||
|
||||
@ -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 = [];
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import defineType, {
|
||||
assertEach,
|
||||
assertNodeType,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import defineType, {
|
||||
arrayOfType,
|
||||
assertOneOf,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import toFastProperties from "to-fast-properties";
|
||||
import "./core";
|
||||
import "./flow";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import defineType, {
|
||||
assertNodeType,
|
||||
assertValueType,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import defineType, {
|
||||
assertNodeType,
|
||||
assertOneOf,
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import defineType, {
|
||||
arrayOfType,
|
||||
assertEach,
|
||||
|
||||
@ -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}`);
|
||||
}
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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/);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
@ -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);
|
||||
|
||||
@ -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 &&
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
|
||||
@ -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" ||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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))) {
|
||||
|
||||
@ -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",
|
||||
})
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import isValidIdentifier from "./isValidIdentifier";
|
||||
|
||||
const RESERVED_WORDS_ES3_ONLY: Set<string> = new Set([
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import {
|
||||
isIdentifierName,
|
||||
isStrictReservedWord,
|
||||
|
||||
@ -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]
|
||||
);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import buildMatchMemberExpression from "../buildMatchMemberExpression";
|
||||
|
||||
const isReactComponent = buildMatchMemberExpression("React.Component");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
tsFlags="--strict"
|
||||
|
||||
yarn tsc $tsFlags ./packages/babel-types/lib/index.d.ts
|
||||
28
yarn.lock
28
yarn.lock
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user