From 6718d466b8ee32a14645fa28e9ee68cd5b67ef68 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 22 Mar 2023 09:18:03 +0800 Subject: [PATCH] Add `isFlowKeywordType` (#14549) --- src/language-js/print/flow.js | 43 ++++-------- src/language-js/print/typescript.js | 1 + src/language-js/utils/index.js | 68 +++---------------- src/language-js/utils/is-flow-keyword-type.js | 20 ++++++ 4 files changed, 45 insertions(+), 87 deletions(-) create mode 100644 src/language-js/utils/is-flow-keyword-type.js diff --git a/src/language-js/print/flow.js b/src/language-js/print/flow.js index b3ffa7851..a4700ede9 100644 --- a/src/language-js/print/flow.js +++ b/src/language-js/print/flow.js @@ -10,6 +10,7 @@ import { isGetterOrSetter, rawText, } from "../utils/index.js"; +import isFlowKeywordType from "../utils/is-flow-keyword-type.js"; import { printClass } from "./class.js"; import { printOpaqueType, @@ -45,6 +46,12 @@ import { function printFlow(path, options, print) { const { node } = path; + + if (isFlowKeywordType(node)) { + // Flow keyword types ends with `TypeAnnotation` + return node.type.slice(0, -14).toLowerCase(); + } + const semi = options.semi ? ";" : ""; switch (node.type) { @@ -117,14 +124,8 @@ function printFlow(path, options, print) { return printTypeQuery(path, print); case "ExistsTypeAnnotation": return "*"; - case "EmptyTypeAnnotation": - return "empty"; - case "MixedTypeAnnotation": - return "mixed"; case "ArrayTypeAnnotation": return printArrayType(print); - case "BooleanLiteralTypeAnnotation": - return String(node.value); case "DeclareEnum": case "EnumDeclaration": @@ -224,6 +225,11 @@ function printFlow(path, options, print) { case "QualifiedTypeofIdentifier": case "QualifiedTypeIdentifier": return [print("qualification"), ".", print("id")]; + + case "NullLiteralTypeAnnotation": + return "null"; + case "BooleanLiteralTypeAnnotation": + return String(node.value); case "StringLiteralTypeAnnotation": return replaceEndOfLine(printString(rawText(node), options)); case "NumberLiteralTypeAnnotation": @@ -246,30 +252,7 @@ function printFlow(path, options, print) { return "%checks"; case "DeclaredPredicate": return ["%checks(", print("value"), ")"]; - case "AnyTypeAnnotation": - return "any"; - case "BooleanTypeAnnotation": - return "boolean"; - case "BigIntTypeAnnotation": - return "bigint"; - case "NullLiteralTypeAnnotation": - return "null"; - case "NumberTypeAnnotation": - return "number"; - case "SymbolTypeAnnotation": - return "symbol"; - case "StringTypeAnnotation": - return "string"; - case "VoidTypeAnnotation": - return "void"; - case "ThisTypeAnnotation": - return "this"; - case "NeverTypeAnnotation": - return "never"; - case "UndefinedTypeAnnotation": - return "undefined"; - case "UnknownTypeAnnotation": - return "unknown"; + // These types are unprintable because they serve as abstract // supertypes for other (printable) types. case "Node": diff --git a/src/language-js/print/typescript.js b/src/language-js/print/typescript.js index e9689a1d3..5aa411cea 100644 --- a/src/language-js/print/typescript.js +++ b/src/language-js/print/typescript.js @@ -67,6 +67,7 @@ function printTypescript(path, options, print) { } if (isTsKeywordType(node)) { + // TS keyword types stars with `TS`, ends with `Keyword` return node.type.slice(2, -7).toLowerCase(); } diff --git a/src/language-js/utils/index.js b/src/language-js/utils/index.js index 2ad20f602..78df2cbef 100644 --- a/src/language-js/utils/index.js +++ b/src/language-js/utils/index.js @@ -9,6 +9,8 @@ import getVisitorKeys from "../traverse/get-visitor-keys.js"; import createTypeCheckFunction from "./create-type-check-function.js"; import isBlockComment from "./is-block-comment.js"; import isNodeMatches from "./is-node-matches.js"; +import isFlowKeywordType from "./is-flow-keyword-type.js"; +import isTsKeywordType from "./is-ts-keyword-type.js"; /** * @typedef {import("../types/estree.js").Node} Node @@ -318,78 +320,30 @@ function isMemberish(node) { ); } -const simpleTypeAnnotations = new Set([ - // `any` - "AnyTypeAnnotation", - "TSAnyKeyword", - // `null` - "NullLiteralTypeAnnotation", - "TSNullKeyword", - // `this` - "ThisTypeAnnotation", +const isSimpleTypeAnnotation = createTypeCheckFunction([ "TSThisType", - // `number` - "NumberTypeAnnotation", - "TSNumberKeyword", - // `void` - "VoidTypeAnnotation", - "TSVoidKeyword", - // `boolean` - "BooleanTypeAnnotation", - "TSBooleanKeyword", - // `bigint` - "BigIntTypeAnnotation", - "TSBigIntKeyword", - // `symbol` - "SymbolTypeAnnotation", - "TSSymbolKeyword", - // `string` - "StringTypeAnnotation", - "TSStringKeyword", - // `never` - "NeverTypeAnnotation", - "TSNeverKeyword", - // `undefined` - "UndefinedTypeAnnotation", - "TSUndefinedKeyword", - // `unknown` - "UnknownTypeAnnotation", - "TSUnknownKeyword", // literals + "NullLiteralTypeAnnotation", "BooleanLiteralTypeAnnotation", "StringLiteralTypeAnnotation", "BigIntLiteralTypeAnnotation", "NumberLiteralTypeAnnotation", "TSLiteralType", "TSTemplateLiteralType", - // flow only, `empty`, `mixed` - "EmptyTypeAnnotation", - "MixedTypeAnnotation", - // typescript only `object` - "TSObjectKeyword", ]); /** * @param {Node} node * @returns {boolean} */ function isSimpleType(node) { - if (!node) { - return false; - } - - if ( - (node.type === "GenericTypeAnnotation" || + return ( + isTsKeywordType(node) || + isFlowKeywordType(node) || + isSimpleTypeAnnotation(node) || + ((node.type === "GenericTypeAnnotation" || node.type === "TSTypeReference") && - !node.typeParameters - ) { - return true; - } - - if (simpleTypeAnnotations.has(node.type)) { - return true; - } - - return false; + !node.typeParameters) + ); } /** diff --git a/src/language-js/utils/is-flow-keyword-type.js b/src/language-js/utils/is-flow-keyword-type.js new file mode 100644 index 000000000..58de9bb52 --- /dev/null +++ b/src/language-js/utils/is-flow-keyword-type.js @@ -0,0 +1,20 @@ +import createTypeCheckFunction from "./create-type-check-function.js"; + +const isFlowKeywordType = createTypeCheckFunction([ + "AnyTypeAnnotation", + "ThisTypeAnnotation", + "NumberTypeAnnotation", + "VoidTypeAnnotation", + "BooleanTypeAnnotation", + "BigIntTypeAnnotation", + "SymbolTypeAnnotation", + "StringTypeAnnotation", + "NeverTypeAnnotation", + "UndefinedTypeAnnotation", + "UnknownTypeAnnotation", + // FLow only + "EmptyTypeAnnotation", + "MixedTypeAnnotation", +]); + +export default isFlowKeywordType;