import * as tsModule from "typescript" ; import { BigIntLiteralType , Declaration , GenericType , LiteralType , Node , ObjectType , Program , Symbol , TupleTypeReference , Type , TypeChecker , TypeFlags , TypeReference , UniqueESSymbolType } from "typescript" ; import { SimpleTypeModifierKind } from "../simple-type" ; import { and , or } from "./list-util" ; export function isTypeChecker ( obj ) { return obj != null && typeof obj === "object" && "getSymbolAtLocation" in obj ! ; } export function isProgram ( obj ) { return obj != null && typeof obj === "object" && "getTypeChecker" in obj ! && "getCompilerOptions" in obj ! ; } export function isNode ( obj ) { return obj != null && typeof obj === "object" && "kind" in obj ! && "flags" in obj ! && "pos" in obj ! && "end" in obj ! ; } function typeHasFlag ( type , flag , op = "and" ) { return hasFlag ( type . flags , flag , op ) ; } function hasFlag ( flags , flag , op = "and" ) { if ( Array . isArray ( flag ) ) { return ( op === "and" ? and : or ) ( flag , f => hasFlag ( flags , f ) ) ; } return ( flags & flag ) !== 0 ; } export function isBoolean ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . BooleanLike ) || type . symbol ?. name === "Boolean" ; } export function isBooleanLiteral ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . BooleanLiteral ) ; } export function isBigIntLiteral ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . BigIntLiteral ) ; } export function isUniqueESSymbol ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . UniqueESSymbol ) ; } export function isESSymbolLike ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . ESSymbolLike ) || type . symbol ?. name === "Symbol" ; } export function isLiteral ( type , ts ) { return type . isLiteral ( ) || isBooleanLiteral ( type , ts ) || isBigIntLiteral ( type , ts ) || isUniqueESSymbol ( type , ts ) ; } export function isString ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . StringLike ) || type . symbol ?. name === "String" ; } export function isNumber ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . NumberLike ) || type . symbol ?. name === "Number" ; } export function isAny ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . Any ) ; } export function isEnum ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . EnumLike ) ; } export function isBigInt ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . BigIntLike ) || type . symbol ?. name === "BigInt" ; } export function isObject ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . Object ) || type . symbol ?. name === "Object" ; } export function isNonPrimitive ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . NonPrimitive ) || type . symbol ?. name === "object" ; } export function isThisType ( type , ts ) { const kind = type . getSymbol ( ) ?. valueDeclaration ?. kind ; if ( kind == null ) { return false ; } return hasFlag ( kind , ts . SyntaxKind . ThisKeyword ) ; } export function isUnknown ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . Unknown ) ; } export function isNull ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . Null ) ; } export function isUndefined ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . Undefined ) ; } export function isVoid ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . VoidLike ) ; } export function isNever ( type , ts ) { return typeHasFlag ( type , ts . TypeFlags . Never ) ; } export function isObjectTypeReference ( type , ts ) { return hasFlag ( type . objectFlags , ts . ObjectFlags . Reference ) ; } export function isSymbol ( obj ) { return "flags" in obj && "name" in obj && "getDeclarations" in obj ; } export function isType ( obj ) { return "flags" in obj && "getSymbol" in obj ; } export function isMethod ( type , ts ) { if ( ! isObject ( type , ts ) ) return false ; const symbol = type . getSymbol ( ) ; if ( symbol == null ) return false ; return hasFlag ( symbol . flags , ts . SymbolFlags . Method ) ; } export function getDeclaration ( symbol , ts ) { const declarations = symbol . getDeclarations ( ) ; if ( declarations == null || declarations . length === 0 ) return symbol . valueDeclaration ; return declarations [ 0 ] ; } export function isArray ( type , checker , ts ) { if ( ! isObject ( type , ts ) ) return false ; const symbol = type . getSymbol ( ) ; if ( symbol == null ) return false ; return getTypeArguments ( type , checker , ts ) . length === 1 && [ "ArrayLike" , "ReadonlyArray" , "ConcatArray" , "Array" ] . includes ( symbol . getName ( ) ) ; } export function isPromise ( type , checker , ts ) { if ( ! isObject ( type , ts ) ) return false ; const symbol = type . getSymbol ( ) ; if ( symbol == null ) return false ; return getTypeArguments ( type , checker , ts ) . length === 1 && [ "PromiseLike" , "Promise" ] . includes ( symbol . getName ( ) ) ; } export function isDate ( type , ts ) { if ( ! isObject ( type , ts ) ) return false ; const symbol = type . getSymbol ( ) ; if ( symbol == null ) return false ; return symbol . getName ( ) === "Date" ; } export function isTupleTypeReference ( type , ts ) { const target = getTargetType ( type , ts ) ; if ( target == null ) return false ; return ( target . objectFlags & ts . ObjectFlags . Tuple ) !== 0 ; } export function isFunction ( type , ts ) { if ( ! isObject ( type , ts ) ) return false ; const symbol = type . getSymbol ( ) ; if ( symbol == null ) return false ; return ( symbol . flags & ts . SymbolFlags . Function ) !== 0 || symbol . escapedName === "Function" || ( symbol . members != null && symbol . members . has ( "__call" as never ) ) ; } export function getTypeArguments ( type , checker , ts ) { if ( isObject ( type , ts ) ) { if ( isObjectTypeReference ( type , ts ) ) { if ( "getTypeArguments" in checker ) { return Array . from ( checker . getTypeArguments ( type ) || [ ] ) ; } else { return Array . from ( type . typeArguments || [ ] ) ; } } } return [ ] ; } export function getTargetType ( type , ts ) { if ( isObject ( type , ts ) && isObjectTypeReference ( type , ts ) ) { return type . target ; } } export function getModifiersFromDeclaration ( declaration , ts ) { const tsModifiers = ts . getCombinedModifierFlags ( declaration ) ; const modifiers = [ ] ; const map = { [ ts . ModifierFlags . Export ] : "EXPORT" , [ ts . ModifierFlags . Ambient ] : "AMBIENT" , [ ts . ModifierFlags . Public ] : "PUBLIC" , [ ts . ModifierFlags . Private ] : "PRIVATE" , [ ts . ModifierFlags . Protected ] : "PROTECTED" , [ ts . ModifierFlags . Static ] : "STATIC" , [ ts . ModifierFlags . Readonly ] : "READONLY" , [ ts . ModifierFlags . Abstract ] : "ABSTRACT" , [ ts . ModifierFlags . Async ] : "ASYNC" , [ ts . ModifierFlags . Default ] : "DEFAULT" } ; Object . entries ( map ) . forEach ( ( [ tsModifier , modifierKind ] ) => { if ( ( tsModifiers & Number ( tsModifier ) ) !== 0 ) { modifiers . push ( modifierKind ) ; } } ) ; return modifiers ; } export function isImplicitGeneric ( type , checker , ts ) { return isArray ( type , checker , ts ) || isTupleTypeReference ( type , ts ) || isPromise ( type , checker , ts ) ; } export function isMethodSignature ( type , ts ) { const symbol = type . getSymbol ( ) ; if ( symbol == null ) return false ; if ( ! isObject ( type , ts ) ) return false ; if ( type . getCallSignatures ( ) . length === 0 ) return false ; const decl = getDeclaration ( symbol , ts ) ; if ( decl == null ) return false ; return decl . kind === ts . SyntaxKind . MethodSignature ; }