namespace ts . SymbolDisplay { const symbolDisplayNodeBuilderFlags = NodeBuilderFlags . OmitParameterModifiers | NodeBuilderFlags . IgnoreErrors | NodeBuilderFlags . UseAliasDefinedOutsideCurrentScope ; export function getSymbolKind ( typeChecker , symbol , location ) { const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar ( typeChecker , symbol , location ) ; if ( result !== ScriptElementKind . unknown ) { return result ; } const flags = getCombinedLocalAndExportSymbolFlags ( symbol ) ; if ( flags & SymbolFlags . Class ) { return getDeclarationOfKind ( symbol , SyntaxKind . ClassExpression ) ? ScriptElementKind . localClassElement : ScriptElementKind . classElement ; } if ( flags & SymbolFlags . Enum ) return ScriptElementKind . enumElement ; if ( flags & SymbolFlags . TypeAlias ) return ScriptElementKind . typeElement ; if ( flags & SymbolFlags . Interface ) return ScriptElementKind . interfaceElement ; if ( flags & SymbolFlags . TypeParameter ) return ScriptElementKind . typeParameterElement ; if ( flags & SymbolFlags . EnumMember ) return ScriptElementKind . enumMemberElement ; if ( flags & SymbolFlags . Alias ) return ScriptElementKind . alias ; if ( flags & SymbolFlags . Module ) return ScriptElementKind . moduleElement ; return result ; } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar ( typeChecker , symbol , location ) { const roots = typeChecker . getRootSymbols ( symbol ) ; if ( roots . length === 1 && first ( roots ) . flags & SymbolFlags . Method && typeChecker . getTypeOfSymbolAtLocation ( symbol , location ) . getNonNullableType ( ) . getCallSignatures ( ) . length !== 0 ) { return ScriptElementKind . memberFunctionElement ; } if ( typeChecker . isUndefinedSymbol ( symbol ) ) { return ScriptElementKind . variableElement ; } if ( typeChecker . isArgumentsSymbol ( symbol ) ) { return ScriptElementKind . localVariableElement ; } if ( location . kind === SyntaxKind . ThisKeyword && isExpression ( location ) ) { return ScriptElementKind . parameterElement ; } const flags = getCombinedLocalAndExportSymbolFlags ( symbol ) ; if ( flags & SymbolFlags . Variable ) { if ( isFirstDeclarationOfSymbolParameter ( symbol ) ) { return ScriptElementKind . parameterElement ; } else if ( symbol . valueDeclaration && isVarConst ( symbol . valueDeclaration as VariableDeclaration ) ) { return ScriptElementKind . constElement ; } else if ( forEach ( symbol . declarations , isLet ) ) { return ScriptElementKind . letElement ; } return isLocalVariableOrFunction ( symbol ) ? ScriptElementKind . localVariableElement : ScriptElementKind . variableElement ; } if ( flags & SymbolFlags . Function ) return isLocalVariableOrFunction ( symbol ) ? ScriptElementKind . localFunctionElement : ScriptElementKind . functionElement ; if ( flags & SymbolFlags . GetAccessor ) return ScriptElementKind . memberGetAccessorElement ; if ( flags & SymbolFlags . SetAccessor ) return ScriptElementKind . memberSetAccessorElement ; if ( flags & SymbolFlags . Method ) return ScriptElementKind . memberFunctionElement ; if ( flags & SymbolFlags . Constructor ) return ScriptElementKind . constructorImplementationElement ; if ( flags & SymbolFlags . Property ) { if ( flags & SymbolFlags . Transient && ( symbol as TransientSymbol ) . checkFlags & CheckFlags . Synthetic ) { const unionPropertyKind = forEach ( typeChecker . getRootSymbols ( symbol ) , rootSymbol => { const rootSymbolFlags = rootSymbol . getFlags ( ) ; if ( rootSymbolFlags & ( SymbolFlags . PropertyOrAccessor | SymbolFlags . Variable ) ) { return ScriptElementKind . memberVariableElement ; } } ) ; if ( ! unionPropertyKind ) { const typeOfUnionProperty = typeChecker . getTypeOfSymbolAtLocation ( symbol , location ) ; if ( typeOfUnionProperty . getCallSignatures ( ) . length ) { return ScriptElementKind . memberFunctionElement ; } return ScriptElementKind . memberVariableElement ; } return unionPropertyKind ; } switch ( location . parent && location . parent . kind ) { case SyntaxKind . JsxOpeningElement : case SyntaxKind . JsxElement : case SyntaxKind . JsxSelfClosingElement : return location . kind === SyntaxKind . Identifier ? ScriptElementKind . memberVariableElement : ScriptElementKind . jsxAttribute ; case SyntaxKind . JsxAttribute : return ScriptElementKind . jsxAttribute ; default : return ScriptElementKind . memberVariableElement ; } } return ScriptElementKind . unknown ; } function getNormalizedSymbolModifiers ( symbol ) { if ( symbol . declarations && symbol . declarations . length ) { const [ declaration , ... declarations ] = symbol . declarations ; const excludeFlags = length ( declarations ) && isDeprecatedDeclaration ( declaration ) && some ( declarations , d => ! isDeprecatedDeclaration ( d ) ) ? ModifierFlags . Deprecated : ModifierFlags . None ; const modifiers = getNodeModifiers ( declaration , excludeFlags ) ; if ( modifiers ) { return modifiers . split ( "," ) ; } } return [ ] ; } export function getSymbolModifiers ( typeChecker , symbol ) { if ( ! symbol ) { return ScriptElementKindModifier . none ; } const modifiers = new Set ( getNormalizedSymbolModifiers ( symbol ) ) ; if ( symbol . flags & SymbolFlags . Alias ) { const resolvedSymbol = typeChecker . getAliasedSymbol ( symbol ) ; if ( resolvedSymbol !== symbol ) { forEach ( getNormalizedSymbolModifiers ( resolvedSymbol ) , modifier => { modifiers . add ( modifier ) ; } ) ; } } if ( symbol . flags & SymbolFlags . Optional ) { modifiers . add ( ScriptElementKindModifier . optionalModifier ) ; } return modifiers . size > 0 ? arrayFrom ( modifiers . values ( ) ) . join ( "," ) : ScriptElementKindModifier . none ; } interface SymbolDisplayPartsDocumentationAndSymbolKind { displayParts : SymbolDisplayPart [ ] ; documentation : SymbolDisplayPart [ ] ; symbolKind : ScriptElementKind ; tags : JSDocTagInfo [ ] | undefined ; } export function getSymbolDisplayPartsDocumentationAndSymbolKind ( typeChecker , symbol , sourceFile , enclosingDeclaration , location , semanticMeaning = getMeaningFromLocation ( location ) , alias ? ) { const displayParts = [ ] ; let documentation = [ ] ; let tags = [ ] ; const symbolFlags = getCombinedLocalAndExportSymbolFlags ( symbol ) ; let symbolKind = semanticMeaning & SemanticMeaning . Value ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar ( typeChecker , symbol , location ) : ScriptElementKind . unknown ; let hasAddedSymbolInfo = false ; const isThisExpression = location . kind === SyntaxKind . ThisKeyword && isInExpressionContext ( location ) ; let type ; let printer ; let documentationFromAlias ; let tagsFromAlias ; let hasMultipleSignatures = false ; if ( location . kind === SyntaxKind . ThisKeyword && ! isThisExpression ) { return { displayParts : [ keywordPart ( SyntaxKind . ThisKeyword ) ] , documentation : [ ] , symbolKind : ScriptElementKind . primitiveType , tags : undefined } ; } if ( symbolKind !== ScriptElementKind . unknown || symbolFlags & SymbolFlags . Class || symbolFlags & SymbolFlags . Alias ) { if ( symbolKind === ScriptElementKind . memberGetAccessorElement || symbolKind === ScriptElementKind . memberSetAccessorElement ) { symbolKind = ScriptElementKind . memberVariableElement ; } let signature ; type = isThisExpression ? typeChecker . getTypeAtLocation ( location ) : typeChecker . getTypeOfSymbolAtLocation ( symbol , location ) ; if ( location . parent && location . parent . kind === SyntaxKind . PropertyAccessExpression ) { const right = ( location . parent as PropertyAccessExpression ) . name ; if ( right === location || ( right && right . getFullWidth ( ) === 0 ) ) { location = location . parent ; } } let callExpressionLike ; if ( isCallOrNewExpression ( location ) ) { callExpressionLike = location ; } else if ( isCallExpressionTarget ( location ) || isNewExpressionTarget ( location ) ) { callExpressionLike = location . parent as CallExpression | NewExpression ; } else if ( location . parent && ( isJsxOpeningLikeElement ( location . parent ) || isTaggedTemplateExpression ( location . parent ) ) && isFunctionLike ( symbol . valueDeclaration ) ) { callExpressionLike = location . parent ; } if ( callExpressionLike ) { signature = typeChecker . getResolvedSignature ( callExpressionLike ) ; const useConstructSignatures = callExpressionLike . kind === SyntaxKind . NewExpression || ( isCallExpression ( callExpressionLike ) && callExpressionLike . expression . kind === SyntaxKind . SuperKeyword ) ; const allSignatures = useConstructSignatures ? type . getConstructSignatures ( ) : type . getCallSignatures ( ) ; if ( signature && ! contains ( allSignatures , signature . target ) && ! contains ( allSignatures , signature ) ) { signature = allSignatures . length ? allSignatures [ 0 ] : undefined ; } if ( signature ) { if ( useConstructSignatures && ( symbolFlags & SymbolFlags . Class ) ) { symbolKind = ScriptElementKind . constructorImplementationElement ; addPrefixForAnyFunctionOrVar ( type . symbol , symbolKind ) ; } else if ( symbolFlags & SymbolFlags . Alias ) { symbolKind = ScriptElementKind . alias ; pushSymbolKind ( symbolKind ) ; displayParts . push ( spacePart ( ) ) ; if ( useConstructSignatures ) { if ( signature . flags & SignatureFlags . Abstract ) { displayParts . push ( keywordPart ( SyntaxKind . AbstractKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } displayParts . push ( keywordPart ( SyntaxKind . NewKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } addFullSymbolName ( symbol ) ; } else { addPrefixForAnyFunctionOrVar ( symbol , symbolKind ) ; } switch ( symbolKind ) { case ScriptElementKind . jsxAttribute : case ScriptElementKind . memberVariableElement : case ScriptElementKind . variableElement : case ScriptElementKind . constElement : case ScriptElementKind . letElement : case ScriptElementKind . parameterElement : case ScriptElementKind . localVariableElement : displayParts . push ( punctuationPart ( SyntaxKind . ColonToken ) ) ; displayParts . push ( spacePart ( ) ) ; if ( ! ( getObjectFlags ( type ) & ObjectFlags . Anonymous ) && type . symbol ) { addRange ( displayParts , symbolToDisplayParts ( typeChecker , type . symbol , enclosingDeclaration , undefined , SymbolFormatFlags . AllowAnyNodeKind | SymbolFormatFlags . WriteTypeParametersOrArguments ) ) ; displayParts . push ( lineBreakPart ( ) ) ; } if ( useConstructSignatures ) { if ( signature . flags & SignatureFlags . Abstract ) { displayParts . push ( keywordPart ( SyntaxKind . AbstractKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } displayParts . push ( keywordPart ( SyntaxKind . NewKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } addSignatureDisplayParts ( signature , allSignatures , TypeFormatFlags . WriteArrowStyleSignature ) ; break ; default : addSignatureDisplayParts ( signature , allSignatures ) ; } hasAddedSymbolInfo = true ; hasMultipleSignatures = allSignatures . length > 1 ; } } else if ( ( isNameOfFunctionDeclaration ( location ) && ! ( symbolFlags & SymbolFlags . Accessor ) ) || ( location . kind === SyntaxKind . ConstructorKeyword && location . parent . kind === SyntaxKind . Constructor ) ) { const functionDeclaration = location . parent as SignatureDeclaration ; const locationIsSymbolDeclaration = symbol . declarations && find ( symbol . declarations , declaration => declaration === ( location . kind === SyntaxKind . ConstructorKeyword ? functionDeclaration . parent : functionDeclaration ) ) ; if ( locationIsSymbolDeclaration ) { const allSignatures = functionDeclaration . kind === SyntaxKind . Constructor ? type . getNonNullableType ( ) . getConstructSignatures ( ) : type . getNonNullableType ( ) . getCallSignatures ( ) ; if ( ! typeChecker . isImplementationOfOverload ( functionDeclaration ) ) { signature = typeChecker . getSignatureFromDeclaration ( functionDeclaration ) ; } else { signature = allSignatures [ 0 ] ; } if ( functionDeclaration . kind === SyntaxKind . Constructor ) { symbolKind = ScriptElementKind . constructorImplementationElement ; addPrefixForAnyFunctionOrVar ( type . symbol , symbolKind ) ; } else { addPrefixForAnyFunctionOrVar ( functionDeclaration . kind === SyntaxKind . CallSignature && ! ( type . symbol . flags & SymbolFlags . TypeLiteral || type . symbol . flags & SymbolFlags . ObjectLiteral ) ? type . symbol : symbol , symbolKind ) ; } if ( signature ) { addSignatureDisplayParts ( signature , allSignatures ) ; } hasAddedSymbolInfo = true ; hasMultipleSignatures = allSignatures . length > 1 ; } } } if ( symbolFlags & SymbolFlags . Class && ! hasAddedSymbolInfo && ! isThisExpression ) { addAliasPrefixIfNecessary ( ) ; if ( getDeclarationOfKind ( symbol , SyntaxKind . ClassExpression ) ) { pushSymbolKind ( ScriptElementKind . localClassElement ) ; } else { displayParts . push ( keywordPart ( SyntaxKind . ClassKeyword ) ) ; } displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; writeTypeParametersOfSymbol ( symbol , sourceFile ) ; } if ( ( symbolFlags & SymbolFlags . Interface ) && ( semanticMeaning & SemanticMeaning . Type ) ) { prefixNextMeaning ( ) ; displayParts . push ( keywordPart ( SyntaxKind . InterfaceKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; writeTypeParametersOfSymbol ( symbol , sourceFile ) ; } if ( ( symbolFlags & SymbolFlags . TypeAlias ) && ( semanticMeaning & SemanticMeaning . Type ) ) { prefixNextMeaning ( ) ; displayParts . push ( keywordPart ( SyntaxKind . TypeKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; writeTypeParametersOfSymbol ( symbol , sourceFile ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( operatorPart ( SyntaxKind . EqualsToken ) ) ; displayParts . push ( spacePart ( ) ) ; addRange ( displayParts , typeToDisplayParts ( typeChecker , isConstTypeReference ( location . parent ) ? typeChecker . getTypeAtLocation ( location . parent ) : typeChecker . getDeclaredTypeOfSymbol ( symbol ) , enclosingDeclaration , TypeFormatFlags . InTypeAlias ) ) ; } if ( symbolFlags & SymbolFlags . Enum ) { prefixNextMeaning ( ) ; if ( some ( symbol . declarations , d => isEnumDeclaration ( d ) && isEnumConst ( d ) ) ) { displayParts . push ( keywordPart ( SyntaxKind . ConstKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } displayParts . push ( keywordPart ( SyntaxKind . EnumKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; } if ( symbolFlags & SymbolFlags . Module && ! isThisExpression ) { prefixNextMeaning ( ) ; const declaration = getDeclarationOfKind < ModuleDeclaration > ( symbol , SyntaxKind . ModuleDeclaration ) ; const isNamespace = declaration && declaration . name && declaration . name . kind === SyntaxKind . Identifier ; displayParts . push ( keywordPart ( isNamespace ? SyntaxKind . NamespaceKeyword : SyntaxKind . ModuleKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; } if ( ( symbolFlags & SymbolFlags . TypeParameter ) && ( semanticMeaning & SemanticMeaning . Type ) ) { prefixNextMeaning ( ) ; displayParts . push ( punctuationPart ( SyntaxKind . OpenParenToken ) ) ; displayParts . push ( textPart ( "type parameter" ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . CloseParenToken ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; if ( symbol . parent ) { addInPrefix ( ) ; addFullSymbolName ( symbol . parent , enclosingDeclaration ) ; writeTypeParametersOfSymbol ( symbol . parent , enclosingDeclaration ) ; } else { const decl = getDeclarationOfKind ( symbol , SyntaxKind . TypeParameter ) ; if ( decl === undefined ) return Debug . fail ( ) ; const declaration = decl . parent ; if ( declaration ) { if ( isFunctionLikeKind ( declaration . kind ) ) { addInPrefix ( ) ; const signature = typeChecker . getSignatureFromDeclaration ( declaration as SignatureDeclaration ) ! ; if ( declaration . kind === SyntaxKind . ConstructSignature ) { displayParts . push ( keywordPart ( SyntaxKind . NewKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } else if ( declaration . kind !== SyntaxKind . CallSignature && ( declaration as SignatureDeclaration ) . name ) { addFullSymbolName ( declaration . symbol ) ; } addRange ( displayParts , signatureToDisplayParts ( typeChecker , signature , sourceFile , TypeFormatFlags . WriteTypeArgumentsOfSignature ) ) ; } else if ( declaration . kind === SyntaxKind . TypeAliasDeclaration ) { addInPrefix ( ) ; displayParts . push ( keywordPart ( SyntaxKind . TypeKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( declaration . symbol ) ; writeTypeParametersOfSymbol ( declaration . symbol , sourceFile ) ; } } } } if ( symbolFlags & SymbolFlags . EnumMember ) { symbolKind = ScriptElementKind . enumMemberElement ; addPrefixForAnyFunctionOrVar ( symbol , "enum member" ) ; const declaration = symbol . declarations ?. [ 0 ] ; if ( declaration ?. kind === SyntaxKind . EnumMember ) { const constantValue = typeChecker . getConstantValue ( declaration as EnumMember ) ; if ( constantValue !== undefined ) { displayParts . push ( spacePart ( ) ) ; displayParts . push ( operatorPart ( SyntaxKind . EqualsToken ) ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( displayPart ( getTextOfConstantValue ( constantValue ) , typeof constantValue === "number" ? SymbolDisplayPartKind . numericLiteral : SymbolDisplayPartKind . stringLiteral ) ) ; } } } if ( symbol . flags & SymbolFlags . Alias ) { prefixNextMeaning ( ) ; if ( ! hasAddedSymbolInfo ) { const resolvedSymbol = typeChecker . getAliasedSymbol ( symbol ) ; if ( resolvedSymbol !== symbol && resolvedSymbol . declarations && resolvedSymbol . declarations . length > 0 ) { const resolvedNode = resolvedSymbol . declarations [ 0 ] ; const declarationName = getNameOfDeclaration ( resolvedNode ) ; if ( declarationName ) { const isExternalModuleDeclaration = isModuleWithStringLiteralName ( resolvedNode ) && hasSyntacticModifier ( resolvedNode , ModifierFlags . Ambient ) ; const shouldUseAliasName = symbol . name !== "default" && ! isExternalModuleDeclaration ; const resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind ( typeChecker , resolvedSymbol , getSourceFileOfNode ( resolvedNode ) , resolvedNode , declarationName , semanticMeaning , shouldUseAliasName ? symbol : resolvedSymbol ) ; displayParts . push ( ... resolvedInfo . displayParts ) ; displayParts . push ( lineBreakPart ( ) ) ; documentationFromAlias = resolvedInfo . documentation ; tagsFromAlias = resolvedInfo . tags ; } else { documentationFromAlias = resolvedSymbol . getContextualDocumentationComment ( resolvedNode , typeChecker ) ; tagsFromAlias = resolvedSymbol . getJsDocTags ( typeChecker ) ; } } } if ( symbol . declarations ) { switch ( symbol . declarations [ 0 ] . kind ) { case SyntaxKind . NamespaceExportDeclaration : displayParts . push ( keywordPart ( SyntaxKind . ExportKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( keywordPart ( SyntaxKind . NamespaceKeyword ) ) ; break ; case SyntaxKind . ExportAssignment : displayParts . push ( keywordPart ( SyntaxKind . ExportKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( keywordPart ( ( symbol . declarations [ 0 ] as ExportAssignment ) . isExportEquals ? SyntaxKind . EqualsToken : SyntaxKind . DefaultKeyword ) ) ; break ; case SyntaxKind . ExportSpecifier : displayParts . push ( keywordPart ( SyntaxKind . ExportKeyword ) ) ; break ; default : displayParts . push ( keywordPart ( SyntaxKind . ImportKeyword ) ) ; } } displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; forEach ( symbol . declarations , declaration => { if ( declaration . kind === SyntaxKind . ImportEqualsDeclaration ) { const importEqualsDeclaration = declaration as ImportEqualsDeclaration ; if ( isExternalModuleImportEqualsDeclaration ( importEqualsDeclaration ) ) { displayParts . push ( spacePart ( ) ) ; displayParts . push ( operatorPart ( SyntaxKind . EqualsToken ) ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( keywordPart ( SyntaxKind . RequireKeyword ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . OpenParenToken ) ) ; displayParts . push ( displayPart ( getTextOfNode ( getExternalModuleImportEqualsDeclarationExpression ( importEqualsDeclaration ) ) , SymbolDisplayPartKind . stringLiteral ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . CloseParenToken ) ) ; } else { const internalAliasSymbol = typeChecker . getSymbolAtLocation ( importEqualsDeclaration . moduleReference ) ; if ( internalAliasSymbol ) { displayParts . push ( spacePart ( ) ) ; displayParts . push ( operatorPart ( SyntaxKind . EqualsToken ) ) ; displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( internalAliasSymbol , enclosingDeclaration ) ; } } return true ; } } ) ; } if ( ! hasAddedSymbolInfo ) { if ( symbolKind !== ScriptElementKind . unknown ) { if ( type ) { if ( isThisExpression ) { prefixNextMeaning ( ) ; displayParts . push ( keywordPart ( SyntaxKind . ThisKeyword ) ) ; } else { addPrefixForAnyFunctionOrVar ( symbol , symbolKind ) ; } if ( symbolKind === ScriptElementKind . memberVariableElement || symbolKind === ScriptElementKind . jsxAttribute || symbolFlags & SymbolFlags . Variable || symbolKind === ScriptElementKind . localVariableElement || isThisExpression ) { displayParts . push ( punctuationPart ( SyntaxKind . ColonToken ) ) ; displayParts . push ( spacePart ( ) ) ; if ( type . symbol && type . symbol . flags & SymbolFlags . TypeParameter ) { const typeParameterParts = mapToDisplayParts ( writer => { const param = typeChecker . typeParameterToDeclaration ( type as TypeParameter , enclosingDeclaration , symbolDisplayNodeBuilderFlags ) ! ; getPrinter ( ) . writeNode ( EmitHint . Unspecified , param , getSourceFileOfNode ( getParseTreeNode ( enclosingDeclaration ) ) , writer ) ; } ) ; addRange ( displayParts , typeParameterParts ) ; } else { addRange ( displayParts , typeToDisplayParts ( typeChecker , type , enclosingDeclaration ) ) ; } if ( ( symbol as TransientSymbol ) . target && ( ( symbol as TransientSymbol ) . target as TransientSymbol ) . tupleLabelDeclaration ) { const labelDecl = ( ( symbol as TransientSymbol ) . target as TransientSymbol ) . tupleLabelDeclaration ! ; Debug . assertNode ( labelDecl . name , isIdentifier ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . OpenParenToken ) ) ; displayParts . push ( textPart ( idText ( labelDecl . name ) ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . CloseParenToken ) ) ; } } else if ( symbolFlags & SymbolFlags . Function || symbolFlags & SymbolFlags . Method || symbolFlags & SymbolFlags . Constructor || symbolFlags & SymbolFlags . Signature || symbolFlags & SymbolFlags . Accessor || symbolKind === ScriptElementKind . memberFunctionElement ) { const allSignatures = type . getNonNullableType ( ) . getCallSignatures ( ) ; if ( allSignatures . length ) { addSignatureDisplayParts ( allSignatures [ 0 ] , allSignatures ) ; hasMultipleSignatures = allSignatures . length > 1 ; } } } } else { symbolKind = getSymbolKind ( typeChecker , symbol , location ) ; } } if ( documentation . length === 0 && ! hasMultipleSignatures ) { documentation = symbol . getContextualDocumentationComment ( enclosingDeclaration , typeChecker ) ; } if ( documentation . length === 0 && symbolFlags & SymbolFlags . Property ) { if ( symbol . parent && symbol . declarations && forEach ( symbol . parent . declarations , declaration => declaration . kind === SyntaxKind . SourceFile ) ) { for ( const declaration of symbol . declarations ) { if ( ! declaration . parent || declaration . parent . kind !== SyntaxKind . BinaryExpression ) { continue ; } const rhsSymbol = typeChecker . getSymbolAtLocation ( ( declaration . parent as BinaryExpression ) . right ) ; if ( ! rhsSymbol ) { continue ; } documentation = rhsSymbol . getDocumentationComment ( typeChecker ) ; tags = rhsSymbol . getJsDocTags ( typeChecker ) ; if ( documentation . length > 0 ) { break ; } } } } if ( tags . length === 0 && ! hasMultipleSignatures ) { tags = symbol . getJsDocTags ( typeChecker ) ; } if ( documentation . length === 0 && documentationFromAlias ) { documentation = documentationFromAlias ; } if ( tags . length === 0 && tagsFromAlias ) { tags = tagsFromAlias ; } return { displayParts , documentation , symbolKind , tags : tags . length === 0 ? undefined : tags } ; function getPrinter ( ) { if ( ! printer ) { printer = createPrinter ( { removeComments : true } ) ; } return printer ; } function prefixNextMeaning ( ) { if ( displayParts . length ) { displayParts . push ( lineBreakPart ( ) ) ; } addAliasPrefixIfNecessary ( ) ; } function addAliasPrefixIfNecessary ( ) { if ( alias ) { pushSymbolKind ( ScriptElementKind . alias ) ; displayParts . push ( spacePart ( ) ) ; } } function addInPrefix ( ) { displayParts . push ( spacePart ( ) ) ; displayParts . push ( keywordPart ( SyntaxKind . InKeyword ) ) ; displayParts . push ( spacePart ( ) ) ; } function addFullSymbolName ( symbolToDisplay , enclosingDeclaration ? ) { if ( alias && symbolToDisplay === symbol ) { symbolToDisplay = alias ; } const fullSymbolDisplayParts = symbolToDisplayParts ( typeChecker , symbolToDisplay , enclosingDeclaration || sourceFile , undefined , SymbolFormatFlags . WriteTypeParametersOrArguments | SymbolFormatFlags . UseOnlyExternalAliasing | SymbolFormatFlags . AllowAnyNodeKind ) ; addRange ( displayParts , fullSymbolDisplayParts ) ; if ( symbol . flags & SymbolFlags . Optional ) { displayParts . push ( punctuationPart ( SyntaxKind . QuestionToken ) ) ; } } function addPrefixForAnyFunctionOrVar ( symbol , symbolKind ) { prefixNextMeaning ( ) ; if ( symbolKind ) { pushSymbolKind ( symbolKind ) ; if ( symbol && ! some ( symbol . declarations , d => isArrowFunction ( d ) || ( isFunctionExpression ( d ) || isClassExpression ( d ) ) && ! d . name ) ) { displayParts . push ( spacePart ( ) ) ; addFullSymbolName ( symbol ) ; } } } function pushSymbolKind ( symbolKind ) { switch ( symbolKind ) { case ScriptElementKind . variableElement : case ScriptElementKind . functionElement : case ScriptElementKind . letElement : case ScriptElementKind . constElement : case ScriptElementKind . constructorImplementationElement : displayParts . push ( textOrKeywordPart ( symbolKind ) ) ; return ; default : displayParts . push ( punctuationPart ( SyntaxKind . OpenParenToken ) ) ; displayParts . push ( textOrKeywordPart ( symbolKind ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . CloseParenToken ) ) ; return ; } } function addSignatureDisplayParts ( signature , allSignatures , flags = TypeFormatFlags . None ) { addRange ( displayParts , signatureToDisplayParts ( typeChecker , signature , enclosingDeclaration , flags | TypeFormatFlags . WriteTypeArgumentsOfSignature ) ) ; if ( allSignatures . length > 1 ) { displayParts . push ( spacePart ( ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . OpenParenToken ) ) ; displayParts . push ( operatorPart ( SyntaxKind . PlusToken ) ) ; displayParts . push ( displayPart ( ( allSignatures . length - 1 ) . toString ( ) , SymbolDisplayPartKind . numericLiteral ) ) ; displayParts . push ( spacePart ( ) ) ; displayParts . push ( textPart ( allSignatures . length === 2 ? "overload" : "overloads" ) ) ; displayParts . push ( punctuationPart ( SyntaxKind . CloseParenToken ) ) ; } documentation = signature . getDocumentationComment ( typeChecker ) ; tags = signature . getJsDocTags ( ) ; if ( allSignatures . length > 1 && documentation . length === 0 && tags . length === 0 ) { documentation = allSignatures [ 0 ] . getDocumentationComment ( typeChecker ) ; tags = allSignatures [ 0 ] . getJsDocTags ( ) ; } } function writeTypeParametersOfSymbol ( symbol , enclosingDeclaration ) { const typeParameterParts = mapToDisplayParts ( writer => { const params = typeChecker . symbolToTypeParameterDeclarations ( symbol , enclosingDeclaration , symbolDisplayNodeBuilderFlags ) ; getPrinter ( ) . writeList ( ListFormat . TypeParameters , params , getSourceFileOfNode ( getParseTreeNode ( enclosingDeclaration ) ) , writer ) ; } ) ; addRange ( displayParts , typeParameterParts ) ; } } function isLocalVariableOrFunction ( symbol ) { if ( symbol . parent ) { return false ; } return forEach ( symbol . declarations , declaration => { if ( declaration . kind === SyntaxKind . FunctionExpression ) { return true ; } if ( declaration . kind !== SyntaxKind . VariableDeclaration && declaration . kind !== SyntaxKind . FunctionDeclaration ) { return false ; } for ( let parent = declaration . parent ; ! isFunctionBlock ( parent ) ; parent = parent . parent ) { if ( parent . kind === SyntaxKind . SourceFile || parent . kind === SyntaxKind . ModuleBlock ) { return false ; } } return true ; } ) ; } }