import * as ts from "typescript" ; import { Context } from "./contexts/Context" ; import { FunctionLikeDeclarationGenericParametersDetail , FunctionLikeDeclarationGenericParametersDetailNode , STATE_PROP } from "./FunctionLikeDeclarationGenericParametersDetail" ; import { hasAnyReflectJsDoc } from "./helpers" ; import { isGetTypeCall } from "./isGetTypeCall" ; param node param context param relatedDeclarations export function getGenericParametersDetails ( node , context , relatedDeclarations ) { if ( ! node . typeParameters ?. length ) { return { } ; } let genericParametersDetail = ( node as unknown as FunctionLikeDeclarationGenericParametersDetailNode ) [ STATE_PROP ] ; if ( genericParametersDetail ) { return genericParametersDetail ; } const symbol = context . typeChecker . getTypeAtLocation ( node ) . getSymbol ( ) ; if ( symbol !== undefined ) { if ( hasAnyReflectJsDoc ( symbol ) ) { const genericParams = node . typeParameters . map ( p => p . name . escapedText . toString ( ) ) ; const state = { usedGenericParameters : genericParams , indexesOfGenericParameters : genericParams . map ( ( _ , index ) => index ) , declaredParametersCount : relatedDeclarations . length != 0 ? Math . max ( node . parameters . length , ... relatedDeclarations . map ( x => x . parameters . length ) ) : node . parameters . length , requestedGenericsReflection : true } ; ( node as unknown as FunctionLikeDeclarationGenericParametersDetailNode ) [ STATE_PROP ] = state ; return state ; } } return context . createNestedContext ( exploreGetTypeCalls , context => { context . visitFunctionLikeDeclaration ( node ) ; if ( context . usedGenericParameters . length ) { const genericParams = node . typeParameters ! . map ( p => p . name . escapedText . toString ( ) ) ; const state = { usedGenericParameters : context . usedGenericParameters , indexesOfGenericParameters : context . usedGenericParameters . map ( p => genericParams . indexOf ( p ) ) , declaredParametersCount : node . parameters . length } ; ( node as unknown as FunctionLikeDeclarationGenericParametersDetailNode ) [ STATE_PROP ] = state ; return state ; } else { ( node as unknown as FunctionLikeDeclarationGenericParametersDetailNode ) [ STATE_PROP ] = { } ; } return { } ; } ) ; } param node param context function exploreGetTypeCalls ( node , context ) { let genericTypeNode ; if ( ( genericTypeNode = isGetTypeCall ( node , context ) ) !== false ) { let genericType = context . typeChecker . getTypeAtLocation ( genericTypeNode ) ; if ( genericType . flags == ts . TypeFlags . TypeParameter && context . usedGenericParameters != undefined && ts . isTypeReferenceNode ( genericTypeNode ) && ts . isIdentifier ( genericTypeNode . typeName ) ) { context . usedGenericParameters . push ( genericTypeNode . typeName . escapedText . toString ( ) ) ; } return node ; } return ts . visitEachChild ( node , context . visitor , context . transformationContext ) ; }