From 6d316c1b7f7374a147d3451a013f934b46db2dcc Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Tue, 28 Jul 2020 17:20:00 +0200 Subject: [PATCH] =?UTF-8?q?feat(babel=E2=80=91types):=20Add=C2=A0type?= =?UTF-8?q?=C2=A0definitions=20for=C2=A0Node=C2=A0assertion=C2=A0methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/babel-types/package.json | 5 ++ .../babel-types/scripts/generators/flow.js | 29 ++++++-- .../scripts/generators/typescript.js | 66 ++++++++++++++++--- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/packages/babel-types/package.json b/packages/babel-types/package.json index 7876a4c69637..1341e6e0050a 100644 --- a/packages/babel-types/package.json +++ b/packages/babel-types/package.json @@ -15,6 +15,11 @@ }, "main": "lib/index.js", "types": "lib/index.d.ts", + "typesVersions": { + ">=3.7": { + "lib/*.d.ts": ["lib/*.ts37.d.ts"] + } + }, "dependencies": { "@babel/helper-validator-identifier": "^7.10.4", "lodash": "^4.17.19", diff --git a/packages/babel-types/scripts/generators/flow.js b/packages/babel-types/scripts/generators/flow.js index 50f20bc61172..64ca8a8ad85d 100644 --- a/packages/babel-types/scripts/generators/flow.js +++ b/packages/babel-types/scripts/generators/flow.js @@ -112,16 +112,35 @@ for (const type in t.NODE_FIELDS) { } } -for (let i = 0; i < t.TYPES.length; i++) { - let decl = `declare function is${t.TYPES[i]}(node: ?Object, opts?: ?Object): boolean`; +lines.push( + // assert/ + `declare function assertNode(node: ?Object): void` +); + +const typeCheckLineGroups = [[], []]; +for (const typeName of t.TYPES.sort()) { + let decl = `declare function is${typeName}(node: ?Object, opts?: ?Object): boolean`; + const isDeprecated = typeName in t.DEPRECATED_KEYS; + const realName = isDeprecated ? t.DEPRECATED_KEYS[typeName] : typeName; - if (t.NODE_FIELDS[t.TYPES[i]]) { - decl += ` %checks (node instanceof ${NODE_PREFIX}${t.TYPES[i]})`; + if (t.NODE_FIELDS[realName]) { + decl += ` %checks (node instanceof ${NODE_PREFIX}${realName})`; } - lines.push(decl); + if (isDeprecated) { + typeCheckLineGroups[0].push(`/** @deprecated Use \`is${realName}\` */`); + typeCheckLineGroups[1].push(`/** @deprecated Use \`assert${realName}\` */`); + } + + typeCheckLineGroups[0].push(decl); + typeCheckLineGroups[1].push( + `declare function assert${typeName}(node: ?Object, opts?: ?Object): void;` + ); } +lines.push(...typeCheckLineGroups[0]); +lines.push(...typeCheckLineGroups[1]); + lines.push( // builders/ // eslint-disable-next-line max-len diff --git a/packages/babel-types/scripts/generators/typescript.js b/packages/babel-types/scripts/generators/typescript.js index ef460a73456e..1942700e3eac 100644 --- a/packages/babel-types/scripts/generators/typescript.js +++ b/packages/babel-types/scripts/generators/typescript.js @@ -1,9 +1,13 @@ "use strict"; +const fs = require("fs"); +const path = require("path"); const t = require("../../"); const stringifyValidator = require("../utils/stringifyValidator"); const toFunctionName = require("../utils/toFunctionName"); +const outDir = path.join(__dirname, "../../lib"); + let code = `// NOTE: This file is autogenerated. Do not modify. // See packages/babel-types/scripts/generators/typescript.js for script used. @@ -51,6 +55,18 @@ export type Node = ${t.TYPES.sort().join(" | ")};\n\n`; // +let ts37code = `\ +// NOTE: This file is autogenerated. Do not modify. +// See packages/babel-types/scripts/generators/typescript.js for script used. + +export * from "./index"; + +`; + +const ts37lines = [ + // assert/ + `export function assertNode(node: object | null | undefined): asserts node is import("./index").Node;`, +]; const lines = []; for (const type in t.NODE_FIELDS) { @@ -119,27 +135,49 @@ for (const type in t.NODE_FIELDS) { } } +lines.push( + // assert/ + `export function assertNode(node: object | null | undefined): void` +); + +const typeCheckLineGroups = [[], []]; for (const typeName of t.TYPES) { + const isDeprecated = typeName in t.DEPRECATED_KEYS; + const realName = isDeprecated ? t.DEPRECATED_KEYS[typeName] : typeName; + const result = - t.NODE_FIELDS[typeName] || t.FLIPPED_ALIAS_KEYS[typeName] - ? `node is ${typeName}` + t.NODE_FIELDS[realName] || t.FLIPPED_ALIAS_KEYS[realName] + ? `node is import("./index").${realName}` : "boolean"; - lines.push( - `export function is${typeName}(node: object | null | undefined, opts?: object | null): ${result};`, + if (isDeprecated) { + const deprecatedAssert = `/** @deprecated Use \`assert${realName}\` */`; + typeCheckLineGroups[0].push(`/** @deprecated Use \`is${realName}\` */`); + typeCheckLineGroups[1].push(deprecatedAssert); + ts37lines.push(deprecatedAssert); + } + + typeCheckLineGroups[0].push( + `export function is${typeName}(node: object | null | undefined, opts?: object | null): ${result};` + ); + + typeCheckLineGroups[1].push( + `export function assert${typeName}(node: object | null | undefined, opts?: object | null): void;` + ); + + ts37lines.push( // TypeScript 3.7: https://github.com/microsoft/TypeScript/pull/32695 will allow assert declarations // eslint-disable-next-line max-len - `// 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): ${ + result === "boolean" ? "void" : `asserts ${result}` };` ); } -lines.push( - // assert/ - // Commented out as this declaration requires TypeScript 3.7 (what do?) - `// export function assertNode(obj: any): asserts obj is Node`, +lines.push(...typeCheckLineGroups[0]); +lines.push(...typeCheckLineGroups[1]); +lines.push( // builders/ // eslint-disable-next-line max-len `export function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): StringTypeAnnotation | VoidTypeAnnotation | NumberTypeAnnotation | BooleanTypeAnnotation | GenericTypeAnnotation`, @@ -333,10 +371,18 @@ code += "}\n\n"; code += lines.join("\n") + "\n"; +ts37code += ts37lines.join("\n") + "\n"; + // process.stdout.write(code); +// This has to be written to a separate file, which means we can't easily +// use `process.stdout.write` without doing some stream splitting trickery: +fs.writeFileSync(path.join(outDir, "index.ts37.d.ts"), ts37code, { + encoding: "utf8", +}); + // function areAllRemainingFieldsNullable(fieldName, fieldNames, fields) {