module ts { var nextSymbolId = 1 ; var nextNodeId = 1 ; var nextMergeId = 1 ; export function createTypeChecker ( program , fullTypeCheck ) { var Symbol = objectAllocator . getSymbolConstructor ( ) ; var Type = objectAllocator . getTypeConstructor ( ) ; var Signature = objectAllocator . getSignatureConstructor ( ) ; var typeCount = 0 ; var emptyArray = [ ] ; var emptySymbols = { } ; var compilerOptions = program . getCompilerOptions ( ) ; var checker = { getProgram : ( ) => program , getNodeCount : ( ) => sum ( program . getSourceFiles ( ) , "nodeCount" ) , getIdentifierCount : ( ) => sum ( program . getSourceFiles ( ) , "identifierCount" ) , getSymbolCount : ( ) => sum ( program . getSourceFiles ( ) , "symbolCount" ) , getTypeCount : ( ) => typeCount , isUndefinedSymbol : symbol => symbol === undefinedSymbol , isArgumentsSymbol : symbol => symbol === argumentsSymbol , emitFiles : invokeEmitter , getDiagnostics , getDeclarationDiagnostics , getGlobalDiagnostics , getTypeOfSymbolAtLocation , getDeclaredTypeOfSymbol , getPropertiesOfType , getPropertyOfType , getSignaturesOfType , getIndexTypeOfType , getReturnTypeOfSignature , getSymbolsInScope , getSymbolAtLocation , getShorthandAssignmentValueSymbol , getTypeAtLocation , typeToString , getSymbolDisplayBuilder , symbolToString , getAugmentedPropertiesOfType , getRootSymbols , getContextualType , getFullyQualifiedName , getResolvedSignature , getEnumMemberValue , isValidPropertyAccess , getSignatureFromDeclaration , isImplementationOfOverload , getAliasedSymbol : resolveImport , hasEarlyErrors , isEmitBlocked , checkAndMarkExpression , egretGetResolveSymbol } ; var undefinedSymbol = createSymbol ( SymbolFlags . Property | SymbolFlags . Transient , "undefined" ) ; var argumentsSymbol = createSymbol ( SymbolFlags . Property | SymbolFlags . Transient , "arguments" ) ; var unknownSymbol = createSymbol ( SymbolFlags . Property | SymbolFlags . Transient , "unknown" ) ; var resolvingSymbol = createSymbol ( SymbolFlags . Transient , "__resolving__" ) ; var anyType = createIntrinsicType ( TypeFlags . Any , "any" ) ; var stringType = createIntrinsicType ( TypeFlags . String , "string" ) ; var numberType = createIntrinsicType ( TypeFlags . Number , "number" ) ; var booleanType = createIntrinsicType ( TypeFlags . Boolean , "boolean" ) ; var voidType = createIntrinsicType ( TypeFlags . Void , "void" ) ; var undefinedType = createIntrinsicType ( TypeFlags . Undefined , "undefined" ) ; var nullType = createIntrinsicType ( TypeFlags . Null , "null" ) ; var unknownType = createIntrinsicType ( TypeFlags . Any , "unknown" ) ; var resolvingType = createIntrinsicType ( TypeFlags . Any , "__resolving__" ) ; var emptyObjectType = createAnonymousType ( undefined , emptySymbols , emptyArray , emptyArray , undefined , undefined ) ; var anyFunctionType = createAnonymousType ( undefined , emptySymbols , emptyArray , emptyArray , undefined , undefined ) ; var noConstraintType = createAnonymousType ( undefined , emptySymbols , emptyArray , emptyArray , undefined , undefined ) ; var inferenceFailureType = createAnonymousType ( undefined , emptySymbols , emptyArray , emptyArray , undefined , undefined ) ; var anySignature = createSignature ( undefined , undefined , emptyArray , anyType , 0 , false , false ) ; var unknownSignature = createSignature ( undefined , undefined , emptyArray , unknownType , 0 , false , false ) ; var globals = { } ; var globalArraySymbol ; var globalObjectType ; var globalFunctionType ; var globalArrayType ; var globalStringType ; var globalNumberType ; var globalBooleanType ; var globalRegExpType ; var globalTemplateStringsArrayType ; var tupleTypes = { } ; var unionTypes = { } ; var stringLiteralTypes = { } ; var emitExtends = false ; var mergedSymbols = [ ] ; var symbolLinks = [ ] ; var nodeLinks = [ ] ; var potentialThisCollisions = [ ] ; var diagnostics = [ ] ; var diagnosticsModified = false ; function addDiagnostic ( diagnostic ) { diagnostics . push ( diagnostic ) ; diagnosticsModified = true ; } function error ( location , message , arg0 ? , arg1 ? , arg2 ? ) { var diagnostic = location ? createDiagnosticForNode ( location , message , arg0 , arg1 , arg2 ) : createCompilerDiagnostic ( message , arg0 , arg1 , arg2 ) ; addDiagnostic ( diagnostic ) ; } function createSymbol ( flags , name ) { return new Symbol ( flags , name ) ; } function getExcludedSymbolFlags ( flags ) { var result = 0 ; if ( flags & SymbolFlags . BlockScopedVariable ) result |= SymbolFlags . BlockScopedVariableExcludes ; if ( flags & SymbolFlags . FunctionScopedVariable ) result |= SymbolFlags . FunctionScopedVariableExcludes ; if ( flags & SymbolFlags . Property ) result |= SymbolFlags . PropertyExcludes ; if ( flags & SymbolFlags . EnumMember ) result |= SymbolFlags . EnumMemberExcludes ; if ( flags & SymbolFlags . Function ) result |= SymbolFlags . FunctionExcludes ; if ( flags & SymbolFlags . Class ) result |= SymbolFlags . ClassExcludes ; if ( flags & SymbolFlags . Interface ) result |= SymbolFlags . InterfaceExcludes ; if ( flags & SymbolFlags . RegularEnum ) result |= SymbolFlags . RegularEnumExcludes ; if ( flags & SymbolFlags . ConstEnum ) result |= SymbolFlags . ConstEnumExcludes ; if ( flags & SymbolFlags . ValueModule ) result |= SymbolFlags . ValueModuleExcludes ; if ( flags & SymbolFlags . Method ) result |= SymbolFlags . MethodExcludes ; if ( flags & SymbolFlags . GetAccessor ) result |= SymbolFlags . GetAccessorExcludes ; if ( flags & SymbolFlags . SetAccessor ) result |= SymbolFlags . SetAccessorExcludes ; if ( flags & SymbolFlags . TypeParameter ) result |= SymbolFlags . TypeParameterExcludes ; if ( flags & SymbolFlags . TypeAlias ) result |= SymbolFlags . TypeAliasExcludes ; if ( flags & SymbolFlags . Import ) result |= SymbolFlags . ImportExcludes ; return result ; } function recordMergedSymbol ( target , source ) { if ( ! source . mergeId ) source . mergeId = nextMergeId ++ ; mergedSymbols [ source . mergeId ] = target ; } function cloneSymbol ( symbol ) { var result = createSymbol ( symbol . flags | SymbolFlags . Merged , symbol . name ) ; result . declarations = symbol . declarations . slice ( 0 ) ; result . parent = symbol . parent ; if ( symbol . valueDeclaration ) result . valueDeclaration = symbol . valueDeclaration ; if ( symbol . constEnumOnlyModule ) result . constEnumOnlyModule = true ; if ( symbol . members ) result . members = cloneSymbolTable ( symbol . members ) ; if ( symbol . exports ) result . exports = cloneSymbolTable ( symbol . exports ) ; recordMergedSymbol ( result , symbol ) ; return result ; } function extendSymbol ( target , source ) { if ( ! ( target . flags & getExcludedSymbolFlags ( source . flags ) ) ) { if ( source . flags & SymbolFlags . ValueModule && target . flags & SymbolFlags . ValueModule && target . constEnumOnlyModule && ! source . constEnumOnlyModule ) { target . constEnumOnlyModule = false ; } target . flags |= source . flags ; if ( ! target . valueDeclaration && source . valueDeclaration ) target . valueDeclaration = source . valueDeclaration ; forEach ( source . declarations , node => { target . declarations . push ( node ) ; } ) ; if ( source . members ) { if ( ! target . members ) target . members = { } ; extendSymbolTable ( target . members , source . members ) ; } if ( source . exports ) { if ( ! target . exports ) target . exports = { } ; extendSymbolTable ( target . exports , source . exports ) ; } recordMergedSymbol ( target , source ) ; } else { var message = target . flags & SymbolFlags . BlockScopedVariable || source . flags & SymbolFlags . BlockScopedVariable ? Diagnostics . Cannot_redeclare_block_scoped_variable_0 : Diagnostics . Duplicate_identifier_0 ; forEach ( source . declarations , node => { error ( node . name ? node . name : node , message , symbolToString ( source ) ) ; } ) ; forEach ( target . declarations , node => { error ( node . name ? node . name : node , message , symbolToString ( source ) ) ; } ) ; } } function cloneSymbolTable ( symbolTable ) { var result = { } ; for ( var id in symbolTable ) { if ( hasProperty ( symbolTable , id ) ) { result [ id ] = symbolTable [ id ] ; } } return result ; } function extendSymbolTable ( target , source ) { for ( var id in source ) { if ( hasProperty ( source , id ) ) { if ( ! hasProperty ( target , id ) ) { target [ id ] = source [ id ] ; } else { var symbol = target [ id ] ; if ( ! ( symbol . flags & SymbolFlags . Merged ) ) { target [ id ] = symbol = cloneSymbol ( symbol ) ; } extendSymbol ( symbol , source [ id ] ) ; } } } } function getSymbolLinks ( symbol ) { if ( symbol . flags & SymbolFlags . Transient ) return < TransientSymbol > symbol ; if ( ! symbol . id ) symbol . id = nextSymbolId ++ ; return symbolLinks [ symbol . id ] || ( symbolLinks [ symbol . id ] = { } ) ; } function getNodeLinks ( node ) { if ( ! node . id ) node . id = nextNodeId ++ ; return nodeLinks [ node . id ] || ( nodeLinks [ node . id ] = { } ) ; } function getSourceFile ( node ) { return < SourceFile > getAncestor ( node , SyntaxKind . SourceFile ) ; } function isGlobalSourceFile ( node ) { return node . kind === SyntaxKind . SourceFile && ! isExternalModule ( < SourceFile > node ) ; } function getSymbol ( symbols , name , meaning ) { if ( meaning && hasProperty ( symbols , name ) ) { var symbol = symbols [ name ] ; Debug . assert ( ( symbol . flags & SymbolFlags . Instantiated ) === 0 , "Should never get an instantiated symbol here." ) ; if ( symbol . flags & meaning ) { return symbol ; } if ( symbol . flags & SymbolFlags . Import ) { var target = resolveImport ( symbol ) ; if ( target === unknownSymbol || target . flags & meaning ) { return symbol ; } } } } /** Returns true if node1 is defined before node 2**/ function isDefinedBefore ( node1 , node2 ) { var file1 = getSourceFileOfNode ( node1 ) ; var file2 = getSourceFileOfNode ( node2 ) ; if ( file1 === file2 ) { return node1 . pos <= node2 . pos ; } if ( ! compilerOptions . out ) { return true ; } var sourceFiles = program . getSourceFiles ( ) ; return sourceFiles . indexOf ( file1 ) <= sourceFiles . indexOf ( file2 ) ; } function resolveName ( location , name , meaning , nameNotFoundMessage , nameArg ) { var result ; var lastLocation ; var propertyWithInvalidInitializer ; var errorLocation = location ; loop : while ( location ) { if ( location . locals && ! isGlobalSourceFile ( location ) ) { if ( result = getSymbol ( location . locals , name , meaning ) ) { break loop ; } } switch ( location . kind ) { case SyntaxKind . SourceFile : if ( ! isExternalModule ( < SourceFile > location ) ) break ; case SyntaxKind . ModuleDeclaration : if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . ModuleMember ) ) { break loop ; } break ; case SyntaxKind . EnumDeclaration : if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . EnumMember ) ) { break loop ; } break ; case SyntaxKind . Property : if ( location . parent . kind === SyntaxKind . ClassDeclaration && ! ( location . flags & NodeFlags . Static ) ) { var ctor = findConstructorDeclaration ( < ClassDeclaration > location . parent ) ; if ( ctor && ctor . locals ) { if ( getSymbol ( ctor . locals , name , meaning & SymbolFlags . Value ) ) { propertyWithInvalidInitializer = location ; } } } break ; case SyntaxKind . ClassDeclaration : case SyntaxKind . InterfaceDeclaration : if ( result = getSymbol ( getSymbolOfNode ( location ) . members , name , meaning & SymbolFlags . Type ) ) { if ( lastLocation && lastLocation . flags & NodeFlags . Static ) { error ( errorLocation , Diagnostics . Static_members_cannot_reference_class_type_parameters ) ; return undefined ; } break loop ; } break ; case SyntaxKind . Method : case SyntaxKind . Constructor : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : case SyntaxKind . FunctionDeclaration : case SyntaxKind . ArrowFunction : if ( name === "arguments" ) { result = argumentsSymbol ; break loop ; } break ; case SyntaxKind . FunctionExpression : if ( name === "arguments" ) { result = argumentsSymbol ; break loop ; } var id = ( < FunctionExpression > location ) . name ; if ( id && name === id . text ) { result = location . symbol ; break loop ; } break ; case SyntaxKind . CatchClause : var id = ( < CatchClause > location ) . name ; if ( name === id . text ) { result = location . symbol ; break loop ; } break ; } lastLocation = location ; location = location . parent ; } if ( ! result ) { result = getSymbol ( globals , name , meaning ) ; } if ( ! result ) { if ( nameNotFoundMessage ) { error ( errorLocation , nameNotFoundMessage , typeof nameArg === "string" ? nameArg : declarationNameToString ( nameArg ) ) ; } return undefined ; } if ( nameNotFoundMessage ) { if ( propertyWithInvalidInitializer ) { var propertyName = ( < PropertyDeclaration > propertyWithInvalidInitializer ) . name ; error ( errorLocation , Diagnostics . Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor , declarationNameToString ( propertyName ) , typeof nameArg === "string" ? nameArg : declarationNameToString ( nameArg ) ) ; return undefined ; } if ( result . flags & SymbolFlags . BlockScopedVariable ) { var declaration = forEach ( result . declarations , d => d . flags & NodeFlags . BlockScoped ? d : undefined ) ; Debug . assert ( declaration !== undefined , "Block-scoped variable declaration is undefined" ) ; if ( ! isDefinedBefore ( declaration , errorLocation ) ) { error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , declarationNameToString ( declaration . name ) ) ; } } } if ( result . declarations ) { var sourceFile = getSourceFile ( lastLocation ) ; var dependFile = getSourceFile ( result . declarations [ 0 ] ) ; if ( sourceFile && dependFile ) { ts . UsedFileResolver . mapFile ( sourceFile . filename , dependFile . filename ) ; } } return result ; } var egretNodesLink = [ ] ; /**
        *
        */ function egretGetResolveSymbol ( node ) { var links = getNodeLinks ( node ) ; if ( links . resolvedSymbol ) { return links . resolvedSymbol ; } if ( ! node . id ) node . id = nextNodeId ++ ; links = egretNodesLink [ node . id ] || ( egretNodesLink [ node . id ] = { } ) ; links . resolvedSymbol = ( getFullWidth ( node ) > 0 && resolveName ( node , node . text , SymbolFlags . Class | SymbolFlags . Export , null , node ) ) || unknownSymbol ; if ( links . resolvedSymbol ) { return links . resolvedSymbol ; } } function resolveImport ( symbol ) { Debug . assert ( ( symbol . flags & SymbolFlags . Import ) !== 0 , "Should only get Imports here." ) ; var links = getSymbolLinks ( symbol ) ; if ( ! links . target ) { links . target = resolvingSymbol ; var node = < ImportDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . ImportDeclaration ) ; var target = node . moduleReference . kind === SyntaxKind . ExternalModuleReference ? resolveExternalModuleName ( node , getExternalModuleImportDeclarationExpression ( node ) ) : getSymbolOfPartOfRightHandSideOfImport ( < EntityName > node . moduleReference , node ) ; if ( links . target === resolvingSymbol ) { links . target = target || unknownSymbol ; } else { error ( node , Diagnostics . Circular_definition_of_import_alias_0 , symbolToString ( symbol ) ) ; } } else if ( links . target === resolvingSymbol ) { links . target = unknownSymbol ; } return links . target ; } function getSymbolOfPartOfRightHandSideOfImport ( entityName , importDeclaration ? ) { if ( ! importDeclaration ) { importDeclaration = < ImportDeclaration > getAncestor ( entityName , SyntaxKind . ImportDeclaration ) ; Debug . assert ( importDeclaration !== undefined ) ; } if ( entityName . kind === SyntaxKind . Identifier && isRightSideOfQualifiedNameOrPropertyAccess ( entityName ) ) { entityName = < QualifiedName > entityName . parent ; } if ( entityName . kind === SyntaxKind . Identifier || entityName . parent . kind === SyntaxKind . QualifiedName ) { return resolveEntityName ( importDeclaration , entityName , SymbolFlags . Namespace ) ; } else { Debug . assert ( entityName . parent . kind === SyntaxKind . ImportDeclaration ) ; return resolveEntityName ( importDeclaration , entityName , SymbolFlags . Value | SymbolFlags . Type | SymbolFlags . Namespace ) ; } } function getFullyQualifiedName ( symbol ) { return symbol . parent ? getFullyQualifiedName ( symbol . parent ) + "." + symbolToString ( symbol ) : symbolToString ( symbol ) ; } function resolveEntityName ( location , name , meaning ) { if ( getFullWidth ( name ) === 0 ) { return undefined ; } if ( name . kind === SyntaxKind . Identifier ) { var symbol = resolveName ( location , ( < Identifier > name ) . text , meaning , Diagnostics . Cannot_find_name_0 , < Identifier > name ) ; if ( ! symbol ) { return ; } } else if ( name . kind === SyntaxKind . QualifiedName ) { var namespace = resolveEntityName ( location , ( < QualifiedName > name ) . left , SymbolFlags . Namespace ) ; if ( ! namespace || namespace === unknownSymbol || getFullWidth ( ( < QualifiedName > name ) . right ) === 0 ) return ; var symbol = getSymbol ( namespace . exports , ( < QualifiedName > name ) . right . text , meaning ) ; if ( ! symbol ) { error ( location , Diagnostics . Module_0_has_no_exported_member_1 , getFullyQualifiedName ( namespace ) , declarationNameToString ( ( < QualifiedName > name ) . right ) ) ; return ; } } Debug . assert ( ( symbol . flags & SymbolFlags . Instantiated ) === 0 , "Should never get an instantiated symbol here." ) ; return symbol . flags & meaning ? symbol : resolveImport ( symbol ) ; } function isExternalModuleNameRelative ( moduleName ) { return moduleName . substr ( 0 , 2 ) === "./" || moduleName . substr ( 0 , 3 ) === "../" || moduleName . substr ( 0 , 2 ) === ".\\" || moduleName . substr ( 0 , 3 ) === "..\\" ; } function resolveExternalModuleName ( location , moduleReferenceExpression ) { if ( moduleReferenceExpression . kind !== SyntaxKind . StringLiteral ) { return ; } var moduleReferenceLiteral = < LiteralExpression > moduleReferenceExpression ; var searchPath = getDirectoryPath ( getSourceFile ( location ) . filename ) ; var moduleName = escapeIdentifier ( moduleReferenceLiteral . text ) ; if ( ! moduleName ) return ; var isRelative = isExternalModuleNameRelative ( moduleName ) ; if ( ! isRelative ) { var symbol = getSymbol ( globals , '"' + moduleName + '"' , SymbolFlags . ValueModule ) ; if ( symbol ) { return getResolvedExportSymbol ( symbol ) ; } } while ( true ) { var filename = normalizePath ( combinePaths ( searchPath , moduleName ) ) ; var sourceFile = program . getSourceFile ( filename + ".ts" ) || program . getSourceFile ( filename + ".d.ts" ) ; if ( sourceFile || isRelative ) break ; var parentPath = getDirectoryPath ( searchPath ) ; if ( parentPath === searchPath ) break ; searchPath = parentPath ; } if ( sourceFile ) { if ( sourceFile . symbol ) { return getResolvedExportSymbol ( sourceFile . symbol ) ; } error ( moduleReferenceLiteral , Diagnostics . File_0_is_not_an_external_module , sourceFile . filename ) ; return ; } error ( moduleReferenceLiteral , Diagnostics . Cannot_find_external_module_0 , moduleName ) ; } function getResolvedExportSymbol ( moduleSymbol ) { var symbol = getExportAssignmentSymbol ( moduleSymbol ) ; if ( symbol ) { if ( symbol . flags & ( SymbolFlags . Value | SymbolFlags . Type | SymbolFlags . Namespace ) ) { return symbol ; } if ( symbol . flags & SymbolFlags . Import ) { return resolveImport ( symbol ) ; } } return moduleSymbol ; } function getExportAssignmentSymbol ( symbol ) { checkTypeOfExportAssignmentSymbol ( symbol ) ; var symbolLinks = getSymbolLinks ( symbol ) ; return symbolLinks . exportAssignSymbol === unknownSymbol ? undefined : symbolLinks . exportAssignSymbol ; } function checkTypeOfExportAssignmentSymbol ( containerSymbol ) { var symbolLinks = getSymbolLinks ( containerSymbol ) ; if ( ! symbolLinks . exportAssignSymbol ) { var exportInformation = collectExportInformationForSourceFileOrModule ( containerSymbol ) ; if ( exportInformation . exportAssignments . length ) { if ( exportInformation . exportAssignments . length > 1 ) { forEach ( exportInformation . exportAssignments , node => error ( node , Diagnostics . A_module_cannot_have_more_than_one_export_assignment ) ) ; } var node = exportInformation . exportAssignments [ 0 ] ; if ( exportInformation . hasExportedMember ) { error ( node , Diagnostics . An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements ) ; } if ( node . exportName . text ) { var meaning = SymbolFlags . Value | SymbolFlags . Type | SymbolFlags . Namespace ; var exportSymbol = resolveName ( node , node . exportName . text , meaning , Diagnostics . Cannot_find_name_0 , node . exportName ) ; } } symbolLinks . exportAssignSymbol = exportSymbol || unknownSymbol ; } } function collectExportInformationForSourceFileOrModule ( symbol ) { var seenExportedMember = false ; var result = [ ] ; forEach ( symbol . declarations , declaration => { var block = < Block > ( declaration . kind === SyntaxKind . SourceFile ? declaration : ( < ModuleDeclaration > declaration ) . body ) ; forEach ( block . statements , node => { if ( node . kind === SyntaxKind . ExportAssignment ) { result . push ( < ExportAssignment > node ) ; } else { seenExportedMember = seenExportedMember || ( node . flags & NodeFlags . Export ) !== 0 ; } } ) ; } ) ; return { hasExportedMember : seenExportedMember , exportAssignments : result } ; } function getMergedSymbol ( symbol ) { var merged ; return symbol && symbol . mergeId && ( merged = mergedSymbols [ symbol . mergeId ] ) ? merged : symbol ; } function getSymbolOfNode ( node ) { return getMergedSymbol ( node . symbol ) ; } function getParentOfSymbol ( symbol ) { return getMergedSymbol ( symbol . parent ) ; } function getExportSymbolOfValueSymbolIfExported ( symbol ) { return symbol && ( symbol . flags & SymbolFlags . ExportValue ) !== 0 ? getMergedSymbol ( symbol . exportSymbol ) : symbol ; } function symbolIsValue ( symbol ) { if ( symbol . flags & SymbolFlags . Instantiated ) { return symbolIsValue ( getSymbolLinks ( symbol ) . target ) ; } if ( symbol . flags & SymbolFlags . Value ) { return true ; } if ( symbol . flags & SymbolFlags . Import ) { return ( resolveImport ( symbol ) . flags & SymbolFlags . Value ) !== 0 ; } return false ; } function findConstructorDeclaration ( node ) { var members = node . members ; for ( var i = 0 ; i < members . length ; i ++ ) { var member = members [ i ] ; if ( member . kind === SyntaxKind . Constructor && ( < ConstructorDeclaration > member ) . body ) { return < ConstructorDeclaration > member ; } } } function createType ( flags ) { var result = new Type ( checker , flags ) ; result . id = typeCount ++ ; return result ; } function createIntrinsicType ( kind , intrinsicName ) { var type = < IntrinsicType > createType ( kind ) ; type . intrinsicName = intrinsicName ; return type ; } function createObjectType ( kind , symbol ? ) { var type = < ObjectType > createType ( kind ) ; type . symbol = symbol ; return type ; } function isReservedMemberName ( name ) { return name . charCodeAt ( 0 ) === CharacterCodes . _ && name . charCodeAt ( 1 ) === CharacterCodes . _ && name . charCodeAt ( 2 ) !== CharacterCodes . _ ; } function getNamedMembers ( members ) { var result ; for ( var id in members ) { if ( hasProperty ( members , id ) ) { if ( ! isReservedMemberName ( id ) ) { if ( ! result ) result = [ ] ; var symbol = members [ id ] ; if ( symbolIsValue ( symbol ) ) { result . push ( symbol ) ; } } } } return result || emptyArray ; } function setObjectTypeMembers ( type , members , callSignatures , constructSignatures , stringIndexType , numberIndexType ) { ( < ResolvedType > type ) . members = members ; ( < ResolvedType > type ) . properties = getNamedMembers ( members ) ; ( < ResolvedType > type ) . callSignatures = callSignatures ; ( < ResolvedType > type ) . constructSignatures = constructSignatures ; if ( stringIndexType ) ( < ResolvedType > type ) . stringIndexType = stringIndexType ; if ( numberIndexType ) ( < ResolvedType > type ) . numberIndexType = numberIndexType ; return < ResolvedType > type ; } function createAnonymousType ( symbol , members , callSignatures , constructSignatures , stringIndexType , numberIndexType ) { return setObjectTypeMembers ( createObjectType ( TypeFlags . Anonymous , symbol ) , members , callSignatures , constructSignatures , stringIndexType , numberIndexType ) ; } function isOptionalProperty ( propertySymbol ) { return propertySymbol . valueDeclaration && hasQuestionToken ( propertySymbol . valueDeclaration ) && propertySymbol . valueDeclaration . kind !== SyntaxKind . Parameter ; } function forEachSymbolTableInScope < T > ( enclosingDeclaration , callback ) { var result ; for ( var location = enclosingDeclaration ; location ; location = location . parent ) { if ( location . locals && ! isGlobalSourceFile ( location ) ) { if ( result = callback ( location . locals ) ) { return result ; } } switch ( location . kind ) { case SyntaxKind . SourceFile : if ( ! isExternalModule ( < SourceFile > location ) ) { break ; } case SyntaxKind . ModuleDeclaration : if ( result = callback ( getSymbolOfNode ( location ) . exports ) ) { return result ; } break ; case SyntaxKind . ClassDeclaration : case SyntaxKind . InterfaceDeclaration : if ( result = callback ( getSymbolOfNode ( location ) . members ) ) { return result ; } break ; } } return callback ( globals ) ; } function getQualifiedLeftMeaning ( rightMeaning ) { return rightMeaning === SymbolFlags . Value ? SymbolFlags . Value : SymbolFlags . Namespace ; } function getAccessibleSymbolChain ( symbol , enclosingDeclaration , meaning , useOnlyExternalAliasing ) { function getAccessibleSymbolChainFromSymbolTable ( symbols ) { function canQualifySymbol ( symbolFromSymbolTable , meaning ) { if ( ! needsQualification ( symbolFromSymbolTable , enclosingDeclaration , meaning ) ) { return true ; } var accessibleParent = getAccessibleSymbolChain ( symbolFromSymbolTable . parent , enclosingDeclaration , getQualifiedLeftMeaning ( meaning ) , useOnlyExternalAliasing ) ; return ! ! accessibleParent ; } function isAccessible ( symbolFromSymbolTable , resolvedAliasSymbol ? ) { if ( symbol === ( resolvedAliasSymbol || symbolFromSymbolTable ) ) { return ! forEach ( symbolFromSymbolTable . declarations , declaration => hasExternalModuleSymbol ( declaration ) ) && canQualifySymbol ( symbolFromSymbolTable , meaning ) ; } } if ( isAccessible ( lookUp ( symbols , symbol . name ) ) ) { return [ symbol ] ; } return forEachValue ( symbols , symbolFromSymbolTable => { if ( symbolFromSymbolTable . flags & SymbolFlags . Import ) { if ( ! useOnlyExternalAliasing || ts . forEach ( symbolFromSymbolTable . declarations , isExternalModuleImportDeclaration ) ) { var resolvedImportedSymbol = resolveImport ( symbolFromSymbolTable ) ; if ( isAccessible ( symbolFromSymbolTable , resolveImport ( symbolFromSymbolTable ) ) ) { return [ symbolFromSymbolTable ] ; } var accessibleSymbolsFromExports = resolvedImportedSymbol . exports ? getAccessibleSymbolChainFromSymbolTable ( resolvedImportedSymbol . exports ) : undefined ; if ( accessibleSymbolsFromExports && canQualifySymbol ( symbolFromSymbolTable , getQualifiedLeftMeaning ( meaning ) ) ) { return [ symbolFromSymbolTable ] . concat ( accessibleSymbolsFromExports ) ; } } } } ) ; } if ( symbol ) { return forEachSymbolTableInScope ( enclosingDeclaration , getAccessibleSymbolChainFromSymbolTable ) ; } } function needsQualification ( symbol , enclosingDeclaration , meaning ) { var qualify = false ; forEachSymbolTableInScope ( enclosingDeclaration , symbolTable => { if ( ! hasProperty ( symbolTable , symbol . name ) ) { return false ; } var symbolFromSymbolTable = symbolTable [ symbol . name ] ; if ( symbolFromSymbolTable === symbol ) { return true ; } symbolFromSymbolTable = ( symbolFromSymbolTable . flags & SymbolFlags . Import ) ? resolveImport ( symbolFromSymbolTable ) : symbolFromSymbolTable ; if ( symbolFromSymbolTable . flags & meaning ) { qualify = true ; return true ; } return false ; } ) ; return qualify ; } function isSymbolAccessible ( symbol , enclosingDeclaration , meaning ) { if ( symbol && enclosingDeclaration && ! ( symbol . flags & SymbolFlags . TypeParameter ) ) { var initialSymbol = symbol ; var meaningToLook = meaning ; while ( symbol ) { var accessibleSymbolChain = getAccessibleSymbolChain ( symbol , enclosingDeclaration , meaningToLook , false ) ; if ( accessibleSymbolChain ) { var hasAccessibleDeclarations = hasVisibleDeclarations ( accessibleSymbolChain [ 0 ] ) ; if ( ! hasAccessibleDeclarations ) { return < SymbolAccessiblityResult > { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : symbolToString ( initialSymbol , enclosingDeclaration , meaning ) , errorModuleName : symbol !== initialSymbol ? symbolToString ( symbol , enclosingDeclaration , SymbolFlags . Namespace ) : undefined , } ; } return hasAccessibleDeclarations ; } meaningToLook = getQualifiedLeftMeaning ( meaning ) ; symbol = getParentOfSymbol ( symbol ) ; } var symbolExternalModule = forEach ( initialSymbol . declarations , declaration => getExternalModuleContainer ( declaration ) ) ; if ( symbolExternalModule ) { var enclosingExternalModule = getExternalModuleContainer ( enclosingDeclaration ) ; if ( symbolExternalModule !== enclosingExternalModule ) { return { accessibility : SymbolAccessibility . CannotBeNamed , errorSymbolName : symbolToString ( initialSymbol , enclosingDeclaration , meaning ) , errorModuleName : symbolToString ( symbolExternalModule ) } ; } } return { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : symbolToString ( initialSymbol , enclosingDeclaration , meaning ) , } ; } return { accessibility : SymbolAccessibility . Accessible } ; function getExternalModuleContainer ( declaration ) { for ( ; declaration ; declaration = declaration . parent ) { if ( hasExternalModuleSymbol ( declaration ) ) { return getSymbolOfNode ( declaration ) ; } } } } function hasExternalModuleSymbol ( declaration ) { return ( declaration . kind === SyntaxKind . ModuleDeclaration && ( < ModuleDeclaration > declaration ) . name . kind === SyntaxKind . StringLiteral ) || ( declaration . kind === SyntaxKind . SourceFile && isExternalModule ( < SourceFile > declaration ) ) ; } function hasVisibleDeclarations ( symbol ) { var aliasesToMakeVisible ; if ( forEach ( symbol . declarations , declaration => ! getIsDeclarationVisible ( declaration ) ) ) { return undefined ; } return { accessibility : SymbolAccessibility . Accessible , aliasesToMakeVisible } ; function getIsDeclarationVisible ( declaration ) { if ( ! isDeclarationVisible ( declaration ) ) { if ( declaration . kind === SyntaxKind . ImportDeclaration && ! ( declaration . flags & NodeFlags . Export ) && isDeclarationVisible ( < Declaration > declaration . parent ) ) { getNodeLinks ( declaration ) . isVisible = true ; if ( aliasesToMakeVisible ) { if ( ! contains ( aliasesToMakeVisible , declaration ) ) { aliasesToMakeVisible . push ( < ImportDeclaration > declaration ) ; } } else { aliasesToMakeVisible = [ < ImportDeclaration > declaration ] ; } return true ; } return false ; } return true ; } } function isEntityNameVisible ( entityName , enclosingDeclaration ) { var meaning ; if ( entityName . parent . kind === SyntaxKind . TypeQuery ) { meaning = SymbolFlags . Value | SymbolFlags . ExportValue ; } else if ( entityName . kind === SyntaxKind . QualifiedName || entityName . parent . kind === SyntaxKind . ImportDeclaration ) { meaning = SymbolFlags . Namespace ; } else { meaning = SymbolFlags . Type ; } var firstIdentifier = getFirstIdentifier ( entityName ) ; var symbol = resolveName ( enclosingDeclaration , ( < Identifier > firstIdentifier ) . text , meaning , undefined , undefined ) ; return ( symbol && hasVisibleDeclarations ( symbol ) ) || < SymbolVisibilityResult > { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : getTextOfNode ( firstIdentifier ) , errorNode : firstIdentifier } ; } function writeKeyword ( writer , kind ) { writer . writeKeyword ( tokenToString ( kind ) ) ; } function writePunctuation ( writer , kind ) { writer . writePunctuation ( tokenToString ( kind ) ) ; } function writeSpace ( writer ) { writer . writeSpace ( " " ) ; } function symbolToString ( symbol , enclosingDeclaration ? , meaning ? ) { var writer = getSingleLineStringWriter ( ) ; getSymbolDisplayBuilder ( ) . buildSymbolDisplay ( symbol , writer , enclosingDeclaration , meaning ) ; var result = writer . string ( ) ; releaseStringWriter ( writer ) ; return result ; } function typeToString ( type , enclosingDeclaration ? , flags ? ) { var writer = getSingleLineStringWriter ( ) ; getSymbolDisplayBuilder ( ) . buildTypeDisplay ( type , writer , enclosingDeclaration , flags ) ; var result = writer . string ( ) ; releaseStringWriter ( writer ) ; var maxLength = compilerOptions . noErrorTruncation || flags & TypeFormatFlags . NoTruncation ? undefined : 100 ; if ( maxLength && result . length >= maxLength ) { result = result . substr ( 0 , maxLength - "..." . length ) + "..." ; } return result ; } function getTypeAliasForTypeLiteral ( type ) { if ( type . symbol && type . symbol . flags & SymbolFlags . TypeLiteral ) { var node = type . symbol . declarations [ 0 ] . parent ; while ( node . kind === SyntaxKind . ParenthesizedType ) { node = node . parent ; } if ( node . kind === SyntaxKind . TypeAliasDeclaration ) { return getSymbolOfNode ( node ) ; } } return undefined ; } var _displayBuilder ; function getSymbolDisplayBuilder ( ) { /**
             * Writes only the name of the symbol out to the writer. Uses the original source text
             * for the name of the symbol if it is available to match how the user inputted the name.
             */ function appendSymbolNameOnly ( symbol , writer ) { if ( symbol . declarations && symbol . declarations . length > 0 ) { var declaration = symbol . declarations [ 0 ] ; if ( declaration . name ) { writer . writeSymbol ( declarationNameToString ( declaration . name ) , symbol ) ; return ; } } writer . writeSymbol ( symbol . name , symbol ) ; } /**
             * Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
             * Meaning needs to be specified if the enclosing declaration is given
             */ function buildSymbolDisplay ( symbol , writer , enclosingDeclaration ? , meaning ? , flags ? ) { var parentSymbol ; function appendParentTypeArgumentsAndSymbolName ( symbol ) { if ( parentSymbol ) { if ( flags & SymbolFormatFlags . WriteTypeParametersOrArguments ) { if ( symbol . flags & SymbolFlags . Instantiated ) { buildDisplayForTypeArgumentsAndDelimiters ( getTypeParametersOfClassOrInterface ( parentSymbol ) , ( < TransientSymbol > symbol ) . mapper , writer , enclosingDeclaration ) ; } else { buildTypeParameterDisplayFromSymbol ( parentSymbol , writer , enclosingDeclaration ) ; } } writePunctuation ( writer , SyntaxKind . DotToken ) ; } parentSymbol = symbol ; appendSymbolNameOnly ( symbol , writer ) ; } writer . trackSymbol ( symbol , enclosingDeclaration , meaning ) ; function walkSymbol ( symbol , meaning ) { if ( symbol ) { var accessibleSymbolChain = getAccessibleSymbolChain ( symbol , enclosingDeclaration , meaning , ! ! ( flags & SymbolFormatFlags . UseOnlyExternalAliasing ) ) ; if ( ! accessibleSymbolChain || needsQualification ( accessibleSymbolChain [ 0 ] , enclosingDeclaration , accessibleSymbolChain . length === 1 ? meaning : getQualifiedLeftMeaning ( meaning ) ) ) { walkSymbol ( getParentOfSymbol ( accessibleSymbolChain ? accessibleSymbolChain [ 0 ] : symbol ) , getQualifiedLeftMeaning ( meaning ) ) ; } if ( accessibleSymbolChain ) { for ( var i = 0 , n = accessibleSymbolChain . length ; i < n ; i ++ ) { appendParentTypeArgumentsAndSymbolName ( accessibleSymbolChain [ i ] ) ; } } else { if ( ! parentSymbol && ts . forEach ( symbol . declarations , declaration => hasExternalModuleSymbol ( declaration ) ) ) { return ; } if ( symbol . flags & SymbolFlags . TypeLiteral || symbol . flags & SymbolFlags . ObjectLiteral ) { return ; } appendParentTypeArgumentsAndSymbolName ( symbol ) ; } } } if ( enclosingDeclaration && ! ( symbol . flags & SymbolFlags . TypeParameter ) ) { walkSymbol ( symbol , meaning ) ; return ; } return appendParentTypeArgumentsAndSymbolName ( symbol ) ; } function buildTypeDisplay ( type , writer , enclosingDeclaration ? , globalFlags ? , typeStack ? ) { var globalFlagsToPass = globalFlags & TypeFormatFlags . WriteOwnNameForAnyLike ; return writeType ( type , globalFlags ) ; function writeType ( type , flags ) { if ( type . flags & TypeFlags . Intrinsic ) { writer . writeKeyword ( ! ( globalFlags & TypeFormatFlags . WriteOwnNameForAnyLike ) && ( type . flags & TypeFlags . Any ) ? "any" : ( < IntrinsicType > type ) . intrinsicName ) ; } else if ( type . flags & TypeFlags . Reference ) { writeTypeReference ( < TypeReference > type , flags ) ; } else if ( type . flags & ( TypeFlags . Class | TypeFlags . Interface | TypeFlags . Enum | TypeFlags . TypeParameter ) ) { buildSymbolDisplay ( type . symbol , writer , enclosingDeclaration , SymbolFlags . Type ) ; } else if ( type . flags & TypeFlags . Tuple ) { writeTupleType ( < TupleType > type ) ; } else if ( type . flags & TypeFlags . Union ) { writeUnionType ( < UnionType > type , flags ) ; } else if ( type . flags & TypeFlags . Anonymous ) { writeAnonymousType ( < ObjectType > type , flags ) ; } else if ( type . flags & TypeFlags . StringLiteral ) { writer . writeStringLiteral ( ( < StringLiteralType > type ) . text ) ; } else { writePunctuation ( writer , SyntaxKind . OpenBraceToken ) ; writeSpace ( writer ) ; writePunctuation ( writer , SyntaxKind . DotDotDotToken ) ; writeSpace ( writer ) ; writePunctuation ( writer , SyntaxKind . CloseBraceToken ) ; } } function writeTypeList ( types , union ) { for ( var i = 0 ; i < types . length ; i ++ ) { if ( i > 0 ) { if ( union ) { writeSpace ( writer ) ; } writePunctuation ( writer , union ? SyntaxKind . BarToken : SyntaxKind . CommaToken ) ; writeSpace ( writer ) ; } writeType ( types [ i ] , union ? TypeFormatFlags . InElementType : TypeFormatFlags . None ) ; } } function writeTypeReference ( type , flags ) { if ( type . target === globalArrayType && ! ( flags & TypeFormatFlags . WriteArrayAsGenericType ) ) { writeType ( type . typeArguments [ 0 ] , TypeFormatFlags . InElementType ) ; writePunctuation ( writer , SyntaxKind . OpenBracketToken ) ; writePunctuation ( writer , SyntaxKind . CloseBracketToken ) ; } else { buildSymbolDisplay ( type . target . symbol , writer , enclosingDeclaration , SymbolFlags . Type ) ; writePunctuation ( writer , SyntaxKind . LessThanToken ) ; writeTypeList ( type . typeArguments , false ) ; writePunctuation ( writer , SyntaxKind . GreaterThanToken ) ; } } function writeTupleType ( type ) { writePunctuation ( writer , SyntaxKind . OpenBracketToken ) ; writeTypeList ( type . elementTypes , false ) ; writePunctuation ( writer , SyntaxKind . CloseBracketToken ) ; } function writeUnionType ( type , flags ) { if ( flags & TypeFormatFlags . InElementType ) { writePunctuation ( writer , SyntaxKind . OpenParenToken ) ; } writeTypeList ( type . types , true ) ; if ( flags & TypeFormatFlags . InElementType ) { writePunctuation ( writer , SyntaxKind . CloseParenToken ) ; } } function writeAnonymousType ( type , flags ) { if ( type . symbol && type . symbol . flags & ( SymbolFlags . Class | SymbolFlags . Enum | SymbolFlags . ValueModule ) ) { writeTypeofSymbol ( type ) ; } else if ( shouldWriteTypeOfFunctionSymbol ( ) ) { writeTypeofSymbol ( type ) ; } else if ( typeStack && contains ( typeStack , type ) ) { var typeAlias = getTypeAliasForTypeLiteral ( type ) ; if ( typeAlias ) { buildSymbolDisplay ( typeAlias , writer , enclosingDeclaration , SymbolFlags . Type ) ; } else { writeKeyword ( writer , SyntaxKind . AnyKeyword ) ; } } else { if ( ! typeStack ) { typeStack = [ ] ; } typeStack . push ( type ) ; writeLiteralType ( type , flags ) ; typeStack . pop ( ) ; } function shouldWriteTypeOfFunctionSymbol ( ) { if ( type . symbol ) { var isStaticMethodSymbol = ! ! ( type . symbol . flags & SymbolFlags . Method && ts . forEach ( type . symbol . declarations , declaration => declaration . flags & NodeFlags . Static ) ) ; var isNonLocalFunctionSymbol = ! ! ( type . symbol . flags & SymbolFlags . Function ) && ( type . symbol . parent || ts . forEach ( type . symbol . declarations , declaration => declaration . parent . kind === SyntaxKind . SourceFile || declaration . parent . kind === SyntaxKind . ModuleBlock ) ) ; if ( isStaticMethodSymbol || isNonLocalFunctionSymbol ) { return ! ! ( flags & TypeFormatFlags . UseTypeOfFunction ) || ( typeStack && contains ( typeStack , type ) ) ; } } } } function writeTypeofSymbol ( type ) { writeKeyword ( writer , SyntaxKind . TypeOfKeyword ) ; writeSpace ( writer ) ; buildSymbolDisplay ( type . symbol , writer , enclosingDeclaration , SymbolFlags . Value ) ; } function getIndexerParameterName ( type , indexKind , fallbackName ) { var declaration = < SignatureDeclaration > getIndexDeclarationOfSymbol ( type . symbol , indexKind ) ; if ( ! declaration ) { return fallbackName ; } Debug . assert ( declaration . parameters . length !== 0 ) ; return declarationNameToString ( declaration . parameters [ 0 ] . name ) ; } function writeLiteralType ( type , flags ) { var resolved = resolveObjectOrUnionTypeMembers ( type ) ; if ( ! resolved . properties . length && ! resolved . stringIndexType && ! resolved . numberIndexType ) { if ( ! resolved . callSignatures . length && ! resolved . constructSignatures . length ) { writePunctuation ( writer , SyntaxKind . OpenBraceToken ) ; writePunctuation ( writer , SyntaxKind . CloseBraceToken ) ; return ; } if ( resolved . callSignatures . length === 1 && ! resolved . constructSignatures . length ) { if ( flags & TypeFormatFlags . InElementType ) { writePunctuation ( writer , SyntaxKind . OpenParenToken ) ; } buildSignatureDisplay ( resolved . callSignatures [ 0 ] , writer , enclosingDeclaration , globalFlagsToPass | TypeFormatFlags . WriteArrowStyleSignature , typeStack ) ; if ( flags & TypeFormatFlags . InElementType ) { writePunctuation ( writer , SyntaxKind . CloseParenToken ) ; } return ; } if ( resolved . constructSignatures . length === 1 && ! resolved . callSignatures . length ) { if ( flags & TypeFormatFlags . InElementType ) { writePunctuation ( writer , SyntaxKind . OpenParenToken ) ; } writeKeyword ( writer , SyntaxKind . NewKeyword ) ; writeSpace ( writer ) ; buildSignatureDisplay ( resolved . constructSignatures [ 0 ] , writer , enclosingDeclaration , globalFlagsToPass | TypeFormatFlags . WriteArrowStyleSignature , typeStack ) ; if ( flags & TypeFormatFlags . InElementType ) { writePunctuation ( writer , SyntaxKind . CloseParenToken ) ; } return ; } } writePunctuation ( writer , SyntaxKind . OpenBraceToken ) ; writer . writeLine ( ) ; writer . increaseIndent ( ) ; for ( var i = 0 ; i < resolved . callSignatures . length ; i ++ ) { buildSignatureDisplay ( resolved . callSignatures [ i ] , writer , enclosingDeclaration , globalFlagsToPass , typeStack ) ; writePunctuation ( writer , SyntaxKind . SemicolonToken ) ; writer . writeLine ( ) ; } for ( var i = 0 ; i < resolved . constructSignatures . length ; i ++ ) { writeKeyword ( writer , SyntaxKind . NewKeyword ) ; writeSpace ( writer ) ; buildSignatureDisplay ( resolved . constructSignatures [ i ] , writer , enclosingDeclaration , globalFlagsToPass , typeStack ) ; writePunctuation ( writer , SyntaxKind . SemicolonToken ) ; writer . writeLine ( ) ; } if ( resolved . stringIndexType ) { writePunctuation ( writer , SyntaxKind . OpenBracketToken ) ; writer . writeParameter ( getIndexerParameterName ( resolved , IndexKind . String , "x" ) ) ; writePunctuation ( writer , SyntaxKind . ColonToken ) ; writeSpace ( writer ) ; writeKeyword ( writer , SyntaxKind . StringKeyword ) ; writePunctuation ( writer , SyntaxKind . CloseBracketToken ) ; writePunctuation ( writer , SyntaxKind . ColonToken ) ; writeSpace ( writer ) ; writeType ( resolved . stringIndexType , TypeFormatFlags . None ) ; writePunctuation ( writer , SyntaxKind . SemicolonToken ) ; writer . writeLine ( ) ; } if ( resolved . numberIndexType ) { writePunctuation ( writer , SyntaxKind . OpenBracketToken ) ; writer . writeParameter ( getIndexerParameterName ( resolved , IndexKind . Number , "x" ) ) ; writePunctuation ( writer , SyntaxKind . ColonToken ) ; writeSpace ( writer ) ; writeKeyword ( writer , SyntaxKind . NumberKeyword ) ; writePunctuation ( writer , SyntaxKind . CloseBracketToken ) ; writePunctuation ( writer , SyntaxKind . ColonToken ) ; writeSpace ( writer ) ; writeType ( resolved . numberIndexType , TypeFormatFlags . None ) ; writePunctuation ( writer , SyntaxKind . SemicolonToken ) ; writer . writeLine ( ) ; } for ( var i = 0 ; i < resolved . properties . length ; i ++ ) { var p = resolved . properties [ i ] ; var t = getTypeOfSymbol ( p ) ; if ( p . flags & ( SymbolFlags . Function | SymbolFlags . Method ) && ! getPropertiesOfObjectType ( t ) . length ) { var signatures = getSignaturesOfType ( t , SignatureKind . Call ) ; for ( var j = 0 ; j < signatures . length ; j ++ ) { buildSymbolDisplay ( p , writer ) ; if ( isOptionalProperty ( p ) ) { writePunctuation ( writer , SyntaxKind . QuestionToken ) ; } buildSignatureDisplay ( signatures [ j ] , writer , enclosingDeclaration , globalFlagsToPass , typeStack ) ; writePunctuation ( writer , SyntaxKind . SemicolonToken ) ; writer . writeLine ( ) ; } } else { buildSymbolDisplay ( p , writer ) ; if ( isOptionalProperty ( p ) ) { writePunctuation ( writer , SyntaxKind . QuestionToken ) ; } writePunctuation ( writer , SyntaxKind . ColonToken ) ; writeSpace ( writer ) ; writeType ( t , TypeFormatFlags . None ) ; writePunctuation ( writer , SyntaxKind . SemicolonToken ) ; writer . writeLine ( ) ; } } writer . decreaseIndent ( ) ; writePunctuation ( writer , SyntaxKind . CloseBraceToken ) ; } } function buildTypeParameterDisplayFromSymbol ( symbol , writer , enclosingDeclaraiton ? , flags ? ) { var targetSymbol = getTargetSymbol ( symbol ) ; if ( targetSymbol . flags & SymbolFlags . Class || targetSymbol . flags & SymbolFlags . Interface ) { buildDisplayForTypeParametersAndDelimiters ( getTypeParametersOfClassOrInterface ( symbol ) , writer , enclosingDeclaraiton , flags ) ; } } function buildTypeParameterDisplay ( tp , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { appendSymbolNameOnly ( tp . symbol , writer ) ; var constraint = getConstraintOfTypeParameter ( tp ) ; if ( constraint ) { writeSpace ( writer ) ; writeKeyword ( writer , SyntaxKind . ExtendsKeyword ) ; writeSpace ( writer ) ; buildTypeDisplay ( constraint , writer , enclosingDeclaration , flags , typeStack ) ; } } function buildParameterDisplay ( p , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { if ( hasDotDotDotToken ( p . valueDeclaration ) ) { writePunctuation ( writer , SyntaxKind . DotDotDotToken ) ; } appendSymbolNameOnly ( p , writer ) ; if ( hasQuestionToken ( p . valueDeclaration ) || ( < VariableDeclaration > p . valueDeclaration ) . initializer ) { writePunctuation ( writer , SyntaxKind . QuestionToken ) ; } writePunctuation ( writer , SyntaxKind . ColonToken ) ; writeSpace ( writer ) ; buildTypeDisplay ( getTypeOfSymbol ( p ) , writer , enclosingDeclaration , flags , typeStack ) ; } function buildDisplayForTypeParametersAndDelimiters ( typeParameters , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { if ( typeParameters && typeParameters . length ) { writePunctuation ( writer , SyntaxKind . LessThanToken ) ; for ( var i = 0 ; i < typeParameters . length ; i ++ ) { if ( i > 0 ) { writePunctuation ( writer , SyntaxKind . CommaToken ) ; writeSpace ( writer ) ; } buildTypeParameterDisplay ( typeParameters [ i ] , writer , enclosingDeclaration , flags , typeStack ) ; } writePunctuation ( writer , SyntaxKind . GreaterThanToken ) ; } } function buildDisplayForTypeArgumentsAndDelimiters ( typeParameters , mapper , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { if ( typeParameters && typeParameters . length ) { writePunctuation ( writer , SyntaxKind . LessThanToken ) ; for ( var i = 0 ; i < typeParameters . length ; i ++ ) { if ( i > 0 ) { writePunctuation ( writer , SyntaxKind . CommaToken ) ; writeSpace ( writer ) ; } buildTypeDisplay ( mapper ( typeParameters [ i ] ) , writer , enclosingDeclaration , TypeFormatFlags . None ) ; } writePunctuation ( writer , SyntaxKind . GreaterThanToken ) ; } } function buildDisplayForParametersAndDelimiters ( parameters , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { writePunctuation ( writer , SyntaxKind . OpenParenToken ) ; for ( var i = 0 ; i < parameters . length ; i ++ ) { if ( i > 0 ) { writePunctuation ( writer , SyntaxKind . CommaToken ) ; writeSpace ( writer ) ; } buildParameterDisplay ( parameters [ i ] , writer , enclosingDeclaration , flags , typeStack ) ; } writePunctuation ( writer , SyntaxKind . CloseParenToken ) ; } function buildReturnTypeDisplay ( signature , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { if ( flags & TypeFormatFlags . WriteArrowStyleSignature ) { writeSpace ( writer ) ; writePunctuation ( writer , SyntaxKind . EqualsGreaterThanToken ) ; } else { writePunctuation ( writer , SyntaxKind . ColonToken ) ; } writeSpace ( writer ) ; buildTypeDisplay ( getReturnTypeOfSignature ( signature ) , writer , enclosingDeclaration , flags , typeStack ) ; } function buildSignatureDisplay ( signature , writer , enclosingDeclaration ? , flags ? , typeStack ? ) { if ( signature . target && ( flags & TypeFormatFlags . WriteTypeArgumentsOfSignature ) ) { buildDisplayForTypeArgumentsAndDelimiters ( signature . target . typeParameters , signature . mapper , writer , enclosingDeclaration ) ; } else { buildDisplayForTypeParametersAndDelimiters ( signature . typeParameters , writer , enclosingDeclaration , flags , typeStack ) ; } buildDisplayForParametersAndDelimiters ( signature . parameters , writer , enclosingDeclaration , flags , typeStack ) ; buildReturnTypeDisplay ( signature , writer , enclosingDeclaration , flags , typeStack ) ; } return _displayBuilder || ( _displayBuilder = { symbolToString : symbolToString , typeToString : typeToString , buildSymbolDisplay : buildSymbolDisplay , buildTypeDisplay : buildTypeDisplay , buildTypeParameterDisplay : buildTypeParameterDisplay , buildParameterDisplay : buildParameterDisplay , buildDisplayForParametersAndDelimiters : buildDisplayForParametersAndDelimiters , buildDisplayForTypeParametersAndDelimiters : buildDisplayForTypeParametersAndDelimiters , buildDisplayForTypeArgumentsAndDelimiters : buildDisplayForTypeArgumentsAndDelimiters , buildTypeParameterDisplayFromSymbol : buildTypeParameterDisplayFromSymbol , buildSignatureDisplay : buildSignatureDisplay , buildReturnTypeDisplay : buildReturnTypeDisplay } ) ; } function isDeclarationVisible ( node ) { function getContainingExternalModule ( node ) { for ( ; node ; node = node . parent ) { if ( node . kind === SyntaxKind . ModuleDeclaration ) { if ( ( < ModuleDeclaration > node ) . name . kind === SyntaxKind . StringLiteral ) { return node ; } } else if ( node . kind === SyntaxKind . SourceFile ) { return isExternalModule ( < SourceFile > node ) ? node : undefined ; } } Debug . fail ( "getContainingModule cant reach here" ) ; } function isUsedInExportAssignment ( node ) { var externalModule = getContainingExternalModule ( node ) ; if ( externalModule ) { var externalModuleSymbol = getSymbolOfNode ( externalModule ) ; var exportAssignmentSymbol = getExportAssignmentSymbol ( externalModuleSymbol ) ; var resolvedExportSymbol ; var symbolOfNode = getSymbolOfNode ( node ) ; if ( isSymbolUsedInExportAssignment ( symbolOfNode ) ) { return true ; } if ( symbolOfNode . flags & SymbolFlags . Import ) { return isSymbolUsedInExportAssignment ( resolveImport ( symbolOfNode ) ) ; } } function isSymbolUsedInExportAssignment ( symbol ) { if ( exportAssignmentSymbol === symbol ) { return true ; } if ( exportAssignmentSymbol && ! ! ( exportAssignmentSymbol . flags & SymbolFlags . Import ) ) { resolvedExportSymbol = resolvedExportSymbol || resolveImport ( exportAssignmentSymbol ) ; if ( resolvedExportSymbol === symbol ) { return true ; } return forEach ( resolvedExportSymbol . declarations , ( current ) => { while ( current ) { if ( current === node ) { return true ; } current = current . parent ; } } ) ; } } } function determineIfDeclarationIsVisible ( ) { switch ( node . kind ) { case SyntaxKind . VariableDeclaration : case SyntaxKind . ModuleDeclaration : case SyntaxKind . ClassDeclaration : case SyntaxKind . InterfaceDeclaration : case SyntaxKind . TypeAliasDeclaration : case SyntaxKind . FunctionDeclaration : case SyntaxKind . EnumDeclaration : case SyntaxKind . ImportDeclaration : var parent = node . kind === SyntaxKind . VariableDeclaration ? node . parent . parent : node . parent ; if ( ! ( node . flags & NodeFlags . Export ) && ! ( node . kind !== SyntaxKind . ImportDeclaration && parent . kind !== SyntaxKind . SourceFile && isInAmbientContext ( parent ) ) ) { return isGlobalSourceFile ( parent ) || isUsedInExportAssignment ( node ) ; } return isDeclarationVisible ( < Declaration > parent ) ; case SyntaxKind . Property : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : case SyntaxKind . Method : if ( node . flags & ( NodeFlags . Private | NodeFlags . Protected ) ) { return false ; } case SyntaxKind . Constructor : case SyntaxKind . ConstructSignature : case SyntaxKind . CallSignature : case SyntaxKind . IndexSignature : case SyntaxKind . Parameter : case SyntaxKind . ModuleBlock : case SyntaxKind . FunctionType : case SyntaxKind . ConstructorType : case SyntaxKind . TypeLiteral : case SyntaxKind . TypeReference : case SyntaxKind . ArrayType : case SyntaxKind . TupleType : case SyntaxKind . UnionType : case SyntaxKind . ParenthesizedType : return isDeclarationVisible ( < Declaration > node . parent ) ; case SyntaxKind . TypeParameter : case SyntaxKind . SourceFile : return true ; default : Debug . fail ( "isDeclarationVisible unknown: SyntaxKind: " + node . kind ) ; } } if ( node ) { var links = getNodeLinks ( node ) ; if ( links . isVisible === undefined ) { links . isVisible = ! ! determineIfDeclarationIsVisible ( ) ; } return links . isVisible ; } } function getTypeOfPrototypeProperty ( prototype ) { var classType = < InterfaceType > getDeclaredTypeOfSymbol ( prototype . parent ) ; return classType . typeParameters ? createTypeReference ( < GenericType > classType , map ( classType . typeParameters , _ => anyType ) ) : classType ; } function getTypeOfVariableOrParameterOrPropertyDeclaration ( declaration ) { if ( declaration . parent . kind === SyntaxKind . ForInStatement ) { return anyType ; } if ( declaration . type ) { return getTypeFromTypeNode ( declaration . type ) ; } if ( declaration . kind === SyntaxKind . Parameter ) { var func = < FunctionLikeDeclaration > declaration . parent ; if ( func . kind === SyntaxKind . SetAccessor && ! hasComputedNameButNotSymbol ( func ) ) { var getter = < AccessorDeclaration > getDeclarationOfKind ( declaration . parent . symbol , SyntaxKind . GetAccessor ) ; if ( getter ) { return getReturnTypeOfSignature ( getSignatureFromDeclaration ( getter ) ) ; } } var type = getContextuallyTypedParameterType ( < ParameterDeclaration > declaration ) ; if ( type ) { return type ; } } if ( declaration . initializer ) { var type = checkAndMarkExpression ( declaration . initializer ) ; if ( declaration . kind !== SyntaxKind . PropertyAssignment ) { var unwidenedType = type ; type = getWidenedType ( type ) ; if ( type !== unwidenedType ) { checkImplicitAny ( type ) ; } } return type ; } if ( declaration . kind === SyntaxKind . ShorthandPropertyAssignment ) { var type = checkIdentifier ( < Identifier > declaration . name ) ; return type ; } var type = hasDotDotDotToken ( declaration ) ? createArrayType ( anyType ) : anyType ; checkImplicitAny ( type ) ; return type ; function checkImplicitAny ( type ) { if ( ! fullTypeCheck || ! compilerOptions . noImplicitAny ) { return ; } if ( getInnermostTypeOfNestedArrayTypes ( type ) !== anyType ) { return ; } if ( isPrivateWithinAmbient ( declaration ) || ( declaration . kind === SyntaxKind . Parameter && isPrivateWithinAmbient ( declaration . parent ) ) ) { return ; } switch ( declaration . kind ) { case SyntaxKind . Property : var diagnostic = Diagnostics . Member_0_implicitly_has_an_1_type ; break ; case SyntaxKind . Parameter : var diagnostic = hasDotDotDotToken ( declaration ) ? Diagnostics . Rest_parameter_0_implicitly_has_an_any_type : Diagnostics . Parameter_0_implicitly_has_an_1_type ; break ; default : var diagnostic = Diagnostics . Variable_0_implicitly_has_an_1_type ; } error ( declaration , diagnostic , declarationNameToString ( declaration . name ) , typeToString ( type ) ) ; } } function getTypeOfVariableOrParameterOrProperty ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . type ) { if ( symbol . flags & SymbolFlags . Prototype ) { return links . type = getTypeOfPrototypeProperty ( symbol ) ; } var declaration = symbol . valueDeclaration ; if ( declaration . kind === SyntaxKind . CatchClause ) { return links . type = anyType ; } links . type = resolvingType ; var type = getTypeOfVariableOrParameterOrPropertyDeclaration ( < VariableDeclaration > declaration ) ; if ( links . type === resolvingType ) { links . type = type ; } } else if ( links . type === resolvingType ) { links . type = anyType ; if ( compilerOptions . noImplicitAny ) { var diagnostic = ( < VariableDeclaration > symbol . valueDeclaration ) . type ? Diagnostics . _0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation : Diagnostics . _0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer ; error ( symbol . valueDeclaration , diagnostic , symbolToString ( symbol ) ) ; } } return links . type ; } function getSetAccessorTypeAnnotationNode ( accessor ) { return accessor && accessor . parameters . length > 0 && accessor . parameters [ 0 ] . type ; } function getAnnotatedAccessorType ( accessor ) { if ( accessor ) { if ( accessor . kind === SyntaxKind . GetAccessor ) { return accessor . type && getTypeFromTypeNode ( accessor . type ) ; } else { var setterTypeAnnotation = getSetAccessorTypeAnnotationNode ( accessor ) ; return setterTypeAnnotation && getTypeFromTypeNode ( setterTypeAnnotation ) ; } } return undefined ; } function getTypeOfAccessors ( symbol ) { var links = getSymbolLinks ( symbol ) ; checkAndStoreTypeOfAccessors ( symbol , links ) ; return links . type ; } function checkAndStoreTypeOfAccessors ( symbol , links ? ) { links = links || getSymbolLinks ( symbol ) ; if ( ! links . type ) { links . type = resolvingType ; var getter = < AccessorDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . GetAccessor ) ; var setter = < AccessorDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . SetAccessor ) ; var type ; var getterReturnType = getAnnotatedAccessorType ( getter ) ; if ( getterReturnType ) { type = getterReturnType ; } else { var setterParameterType = getAnnotatedAccessorType ( setter ) ; if ( setterParameterType ) { type = setterParameterType ; } else { if ( getter && getter . body ) { type = getReturnTypeFromBody ( getter ) ; } else { if ( compilerOptions . noImplicitAny ) { error ( setter , Diagnostics . Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation , symbolToString ( symbol ) ) ; } type = anyType ; } } } if ( links . type === resolvingType ) { links . type = type ; } } else if ( links . type === resolvingType ) { links . type = anyType ; if ( compilerOptions . noImplicitAny ) { var getter = < AccessorDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . GetAccessor ) ; error ( getter , Diagnostics . _0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions , symbolToString ( symbol ) ) ; } } } function getTypeOfFuncClassEnumModule ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . type ) { links . type = createObjectType ( TypeFlags . Anonymous , symbol ) ; } return links . type ; } function getTypeOfEnumMember ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . type ) { links . type = getDeclaredTypeOfEnum ( getParentOfSymbol ( symbol ) ) ; } return links . type ; } function getTypeOfImport ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . type ) { links . type = getTypeOfSymbol ( resolveImport ( symbol ) ) ; } return links . type ; } function getTypeOfInstantiatedSymbol ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . type ) { links . type = instantiateType ( getTypeOfSymbol ( links . target ) , links . mapper ) ; } return links . type ; } function getTypeOfSymbol ( symbol ) { if ( symbol . flags & SymbolFlags . Instantiated ) { return getTypeOfInstantiatedSymbol ( symbol ) ; } if ( symbol . flags & ( SymbolFlags . Variable | SymbolFlags . Property ) ) { return getTypeOfVariableOrParameterOrProperty ( symbol ) ; } if ( symbol . flags & ( SymbolFlags . Function | SymbolFlags . Method | SymbolFlags . Class | SymbolFlags . Enum | SymbolFlags . ValueModule ) ) { return getTypeOfFuncClassEnumModule ( symbol ) ; } if ( symbol . flags & SymbolFlags . EnumMember ) { return getTypeOfEnumMember ( symbol ) ; } if ( symbol . flags & SymbolFlags . Accessor ) { return getTypeOfAccessors ( symbol ) ; } if ( symbol . flags & SymbolFlags . Import ) { return getTypeOfImport ( symbol ) ; } return unknownType ; } function getTargetType ( type ) { return type . flags & TypeFlags . Reference ? ( < TypeReference > type ) . target : type ; } function hasBaseType ( type , checkBase ) { return check ( type ) ; function check ( type ) { var target = < InterfaceType > getTargetType ( type ) ; return target === checkBase || forEach ( target . baseTypes , check ) ; } } function getTypeParametersOfClassOrInterface ( symbol ) { var result ; forEach ( symbol . declarations , node => { if ( node . kind === SyntaxKind . InterfaceDeclaration || node . kind === SyntaxKind . ClassDeclaration ) { var declaration = < InterfaceDeclaration > node ; if ( declaration . typeParameters && declaration . typeParameters . length ) { forEach ( declaration . typeParameters , node => { var tp = getDeclaredTypeOfTypeParameter ( getSymbolOfNode ( node ) ) ; if ( ! result ) { result = [ tp ] ; } else if ( ! contains ( result , tp ) ) { result . push ( tp ) ; } } ) ; } } } ) ; return result ; } function getDeclaredTypeOfClass ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . declaredType ) { var type = links . declaredType = < InterfaceType > createObjectType ( TypeFlags . Class , symbol ) ; var typeParameters = getTypeParametersOfClassOrInterface ( symbol ) ; if ( typeParameters ) { type . flags |= TypeFlags . Reference ; type . typeParameters = typeParameters ; ( < GenericType > type ) . instantiations = { } ; ( < GenericType > type ) . instantiations [ getTypeListId ( type . typeParameters ) ] = < GenericType > type ; ( < GenericType > type ) . target = < GenericType > type ; ( < GenericType > type ) . typeArguments = type . typeParameters ; } type . baseTypes = [ ] ; var declaration = < ClassDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . ClassDeclaration ) ; var baseTypeNode = getClassBaseTypeNode ( declaration ) ; if ( baseTypeNode ) { var baseType = getTypeFromTypeReferenceNode ( baseTypeNode ) ; if ( baseType !== unknownType ) { if ( getTargetType ( baseType ) . flags & TypeFlags . Class ) { if ( type !== baseType && ! hasBaseType ( < InterfaceType > baseType , type ) ) { type . baseTypes . push ( baseType ) ; } else { error ( declaration , Diagnostics . Type_0_recursively_references_itself_as_a_base_type , typeToString ( type , undefined , TypeFormatFlags . WriteArrayAsGenericType ) ) ; } } else { error ( baseTypeNode , Diagnostics . A_class_may_only_extend_another_class ) ; } } } type . declaredProperties = getNamedMembers ( symbol . members ) ; type . declaredCallSignatures = emptyArray ; type . declaredConstructSignatures = emptyArray ; type . declaredStringIndexType = getIndexTypeOfSymbol ( symbol , IndexKind . String ) ; type . declaredNumberIndexType = getIndexTypeOfSymbol ( symbol , IndexKind . Number ) ; } return < InterfaceType > links . declaredType ; } function getDeclaredTypeOfInterface ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . declaredType ) { var type = links . declaredType = < InterfaceType > createObjectType ( TypeFlags . Interface , symbol ) ; var typeParameters = getTypeParametersOfClassOrInterface ( symbol ) ; if ( typeParameters ) { type . flags |= TypeFlags . Reference ; type . typeParameters = typeParameters ; ( < GenericType > type ) . instantiations = { } ; ( < GenericType > type ) . instantiations [ getTypeListId ( type . typeParameters ) ] = < GenericType > type ; ( < GenericType > type ) . target = < GenericType > type ; ( < GenericType > type ) . typeArguments = type . typeParameters ; } type . baseTypes = [ ] ; forEach ( symbol . declarations , declaration => { if ( declaration . kind === SyntaxKind . InterfaceDeclaration && getInterfaceBaseTypeNodes ( < InterfaceDeclaration > declaration ) ) { forEach ( getInterfaceBaseTypeNodes ( < InterfaceDeclaration > declaration ) , node => { var baseType = getTypeFromTypeReferenceNode ( node ) ; if ( baseType !== unknownType ) { if ( getTargetType ( baseType ) . flags & ( TypeFlags . Class | TypeFlags . Interface ) ) { if ( type !== baseType && ! hasBaseType ( < InterfaceType > baseType , type ) ) { type . baseTypes . push ( baseType ) ; } else { error ( declaration , Diagnostics . Type_0_recursively_references_itself_as_a_base_type , typeToString ( type , undefined , TypeFormatFlags . WriteArrayAsGenericType ) ) ; } } else { error ( node , Diagnostics . An_interface_may_only_extend_a_class_or_another_interface ) ; } } } ) ; } } ) ; type . declaredProperties = getNamedMembers ( symbol . members ) ; type . declaredCallSignatures = getSignaturesOfSymbol ( symbol . members [ "__call" ] ) ; type . declaredConstructSignatures = getSignaturesOfSymbol ( symbol . members [ "__new" ] ) ; type . declaredStringIndexType = getIndexTypeOfSymbol ( symbol , IndexKind . String ) ; type . declaredNumberIndexType = getIndexTypeOfSymbol ( symbol , IndexKind . Number ) ; } return < InterfaceType > links . declaredType ; } function getDeclaredTypeOfTypeAlias ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . declaredType ) { links . declaredType = resolvingType ; var declaration = < TypeAliasDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . TypeAliasDeclaration ) ; var type = getTypeFromTypeNode ( declaration . type ) ; if ( links . declaredType === resolvingType ) { links . declaredType = type ; } } else if ( links . declaredType === resolvingType ) { links . declaredType = unknownType ; var declaration = < TypeAliasDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . TypeAliasDeclaration ) ; error ( declaration . name , Diagnostics . Type_alias_0_circularly_references_itself , symbolToString ( symbol ) ) ; } return links . declaredType ; } function getDeclaredTypeOfEnum ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . declaredType ) { var type = createType ( TypeFlags . Enum ) ; type . symbol = symbol ; links . declaredType = type ; } return links . declaredType ; } function getDeclaredTypeOfTypeParameter ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . declaredType ) { var type = < TypeParameter > createType ( TypeFlags . TypeParameter ) ; type . symbol = symbol ; if ( ! ( < TypeParameterDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . TypeParameter ) ) . constraint ) { type . constraint = noConstraintType ; } links . declaredType = type ; } return < TypeParameter > links . declaredType ; } function getDeclaredTypeOfImport ( symbol ) { var links = getSymbolLinks ( symbol ) ; if ( ! links . declaredType ) { links . declaredType = getDeclaredTypeOfSymbol ( resolveImport ( symbol ) ) ; } return links . declaredType ; } function getDeclaredTypeOfSymbol ( symbol ) { Debug . assert ( ( symbol . flags & SymbolFlags . Instantiated ) === 0 ) ; if ( symbol . flags & SymbolFlags . Class ) { return getDeclaredTypeOfClass ( symbol ) ; } if ( symbol . flags & SymbolFlags . Interface ) { return getDeclaredTypeOfInterface ( symbol ) ; } if ( symbol . flags & SymbolFlags . TypeAlias ) { return getDeclaredTypeOfTypeAlias ( symbol ) ; } if ( symbol . flags & SymbolFlags . Enum ) { return getDeclaredTypeOfEnum ( symbol ) ; } if ( symbol . flags & SymbolFlags . TypeParameter ) { return getDeclaredTypeOfTypeParameter ( symbol ) ; } if ( symbol . flags & SymbolFlags . Import ) { return getDeclaredTypeOfImport ( symbol ) ; } return unknownType ; } function createSymbolTable ( symbols ) { var result = { } ; for ( var i = 0 ; i < symbols . length ; i ++ ) { var symbol = symbols [ i ] ; result [ symbol . name ] = symbol ; } return result ; } function createInstantiatedSymbolTable ( symbols , mapper ) { var result = { } ; for ( var i = 0 ; i < symbols . length ; i ++ ) { var symbol = symbols [ i ] ; result [ symbol . name ] = instantiateSymbol ( symbol , mapper ) ; } return result ; } function addInheritedMembers ( symbols , baseSymbols ) { for ( var i = 0 ; i < baseSymbols . length ; i ++ ) { var s = baseSymbols [ i ] ; if ( ! hasProperty ( symbols , s . name ) ) { symbols [ s . name ] = s ; } } } function addInheritedSignatures ( signatures , baseSignatures ) { if ( baseSignatures ) { for ( var i = 0 ; i < baseSignatures . length ; i ++ ) { signatures . push ( baseSignatures [ i ] ) ; } } } function resolveClassOrInterfaceMembers ( type ) { var members = type . symbol . members ; var callSignatures = type . declaredCallSignatures ; var constructSignatures = type . declaredConstructSignatures ; var stringIndexType = type . declaredStringIndexType ; var numberIndexType = type . declaredNumberIndexType ; if ( type . baseTypes . length ) { members = createSymbolTable ( type . declaredProperties ) ; forEach ( type . baseTypes , baseType => { addInheritedMembers ( members , getPropertiesOfObjectType ( baseType ) ) ; callSignatures = concatenate ( callSignatures , getSignaturesOfType ( baseType , SignatureKind . Call ) ) ; constructSignatures = concatenate ( constructSignatures , getSignaturesOfType ( baseType , SignatureKind . Construct ) ) ; stringIndexType = stringIndexType || getIndexTypeOfType ( baseType , IndexKind . String ) ; numberIndexType = numberIndexType || getIndexTypeOfType ( baseType , IndexKind . Number ) ; } ) ; } setObjectTypeMembers ( type , members , callSignatures , constructSignatures , stringIndexType , numberIndexType ) ; } function resolveTypeReferenceMembers ( type ) { var target = type . target ; var mapper = createTypeMapper ( target . typeParameters , type . typeArguments ) ; var members = createInstantiatedSymbolTable ( target . declaredProperties , mapper ) ; var callSignatures = instantiateList ( target . declaredCallSignatures , mapper , instantiateSignature ) ; var constructSignatures = instantiateList ( target . declaredConstructSignatures , mapper , instantiateSignature ) ; var stringIndexType = target . declaredStringIndexType ? instantiateType ( target . declaredStringIndexType , mapper ) : undefined ; var numberIndexType = target . declaredNumberIndexType ? instantiateType ( target . declaredNumberIndexType , mapper ) : undefined ; forEach ( target . baseTypes , baseType => { var instantiatedBaseType = instantiateType ( baseType , mapper ) ; addInheritedMembers ( members , getPropertiesOfObjectType ( instantiatedBaseType ) ) ; callSignatures = concatenate ( callSignatures , getSignaturesOfType ( instantiatedBaseType , SignatureKind . Call ) ) ; constructSignatures = concatenate ( constructSignatures , getSignaturesOfType ( instantiatedBaseType , SignatureKind . Construct ) ) ; stringIndexType = stringIndexType || getIndexTypeOfType ( instantiatedBaseType , IndexKind . String ) ; numberIndexType = numberIndexType || getIndexTypeOfType ( instantiatedBaseType , IndexKind . Number ) ; } ) ; setObjectTypeMembers ( type , members , callSignatures , constructSignatures , stringIndexType , numberIndexType ) ; } function createSignature ( declaration , typeParameters , parameters , resolvedReturnType , minArgumentCount , hasRestParameter , hasStringLiterals ) { var sig = new Signature ( checker ) ; sig . declaration = declaration ; sig . typeParameters = typeParameters ; sig . parameters = parameters ; sig . resolvedReturnType = resolvedReturnType ; sig . minArgumentCount = minArgumentCount ; sig . hasRestParameter = hasRestParameter ; sig . hasStringLiterals = hasStringLiterals ; return sig ; } function cloneSignature ( sig ) { return createSignature ( sig . declaration , sig . typeParameters , sig . parameters , sig . resolvedReturnType , sig . minArgumentCount , sig . hasRestParameter , sig . hasStringLiterals ) ; } function getDefaultConstructSignatures ( classType ) { if ( classType . baseTypes . length ) { var baseType = classType . baseTypes [ 0 ] ; var baseSignatures = getSignaturesOfType ( getTypeOfSymbol ( baseType . symbol ) , SignatureKind . Construct ) ; return map ( baseSignatures , baseSignature => { var signature = baseType . flags & TypeFlags . Reference ? getSignatureInstantiation ( baseSignature , ( < TypeReference > baseType ) . typeArguments ) : cloneSignature ( baseSignature ) ; signature . typeParameters = classType . typeParameters ; signature . resolvedReturnType = classType ; return signature ; } ) ; } return [ createSignature ( undefined , classType . typeParameters , emptyArray , classType , 0 , false , false ) ] ; } function createTupleTypeMemberSymbols ( memberTypes ) { var members = { } ; for ( var i = 0 ; i < memberTypes . length ; i ++ ) { var symbol = < TransientSymbol > createSymbol ( SymbolFlags . Property | SymbolFlags . Transient , "" + i ) ; symbol . type = memberTypes [ i ] ; members [ i ] = symbol ; } return members ; } function resolveTupleTypeMembers ( type ) { var arrayType = resolveObjectOrUnionTypeMembers ( createArrayType ( getUnionType ( type . elementTypes ) ) ) ; var members = createTupleTypeMemberSymbols ( type . elementTypes ) ; addInheritedMembers ( members , arrayType . properties ) ; setObjectTypeMembers ( type , members , arrayType . callSignatures , arrayType . constructSignatures , arrayType . stringIndexType , arrayType . numberIndexType ) ; } function signatureListsIdentical ( s , t ) { if ( s . length !== t . length ) { return false ; } for ( var i = 0 ; i < s . length ; i ++ ) { if ( ! compareSignatures ( s [ i ] , t [ i ] , false , compareTypes ) ) { return false ; } } return true ; } function getUnionSignatures ( types , kind ) { var signatureLists = map ( types , t => getSignaturesOfType ( t , kind ) ) ; var signatures = signatureLists [ 0 ] ; for ( var i = 0 ; i < signatures . length ; i ++ ) { if ( signatures [ i ] . typeParameters ) { return emptyArray ; } } for ( var i = 1 ; i < signatureLists . length ; i ++ ) { if ( ! signatureListsIdentical ( signatures , signatureLists [ i ] ) ) { return emptyArray ; } } var result = map ( signatures , cloneSignature ) ; for ( var i = 0 ; i < result . length ; i ++ ) { var s = result [ i ] ; s . resolvedReturnType = undefined ; s . unionSignatures = map ( signatureLists , signatures => signatures [ i ] ) ; } return result ; } function getUnionIndexType ( types , kind ) { var indexTypes = [ ] ; for ( var i = 0 ; i < types . length ; i ++ ) { var indexType = getIndexTypeOfType ( types [ i ] , kind ) ; if ( ! indexType ) { return undefined ; } indexTypes . push ( indexType ) ; } return getUnionType ( indexTypes ) ; } function resolveUnionTypeMembers ( type ) { var callSignatures = getUnionSignatures ( type . types , SignatureKind . Call ) ; var constructSignatures = getUnionSignatures ( type . types , SignatureKind . Construct ) ; var stringIndexType = getUnionIndexType ( type . types , IndexKind . String ) ; var numberIndexType = getUnionIndexType ( type . types , IndexKind . Number ) ; setObjectTypeMembers ( type , emptySymbols , callSignatures , constructSignatures , stringIndexType , numberIndexType ) ; } function resolveAnonymousTypeMembers ( type ) { var symbol = type . symbol ; if ( symbol . flags & SymbolFlags . TypeLiteral ) { var members = symbol . members ; var callSignatures = getSignaturesOfSymbol ( members [ "__call" ] ) ; var constructSignatures = getSignaturesOfSymbol ( members [ "__new" ] ) ; var stringIndexType = getIndexTypeOfSymbol ( symbol , IndexKind . String ) ; var numberIndexType = getIndexTypeOfSymbol ( symbol , IndexKind . Number ) ; } else { var members = emptySymbols ; var callSignatures = emptyArray ; var constructSignatures = emptyArray ; if ( symbol . flags & SymbolFlags . HasExports ) { members = symbol . exports ; } if ( symbol . flags & ( SymbolFlags . Function | SymbolFlags . Method ) ) { callSignatures = getSignaturesOfSymbol ( symbol ) ; } if ( symbol . flags & SymbolFlags . Class ) { var classType = getDeclaredTypeOfClass ( symbol ) ; constructSignatures = getSignaturesOfSymbol ( symbol . members [ "__constructor" ] ) ; if ( ! constructSignatures . length ) { constructSignatures = getDefaultConstructSignatures ( classType ) ; } if ( classType . baseTypes . length ) { members = createSymbolTable ( getNamedMembers ( members ) ) ; addInheritedMembers ( members , getPropertiesOfObjectType ( getTypeOfSymbol ( classType . baseTypes [ 0 ] . symbol ) ) ) ; } } var stringIndexType = undefined ; var numberIndexType = ( symbol . flags & SymbolFlags . Enum ) ? stringType : undefined ; } setObjectTypeMembers ( type , members , callSignatures , constructSignatures , stringIndexType , numberIndexType ) ; } function resolveObjectOrUnionTypeMembers ( type ) { if ( ! ( < ResolvedType > type ) . members ) { if ( type . flags & ( TypeFlags . Class | TypeFlags . Interface ) ) { resolveClassOrInterfaceMembers ( < InterfaceType > type ) ; } else if ( type . flags & TypeFlags . Anonymous ) { resolveAnonymousTypeMembers ( < ObjectType > type ) ; } else if ( type . flags & TypeFlags . Tuple ) { resolveTupleTypeMembers ( < TupleType > type ) ; } else if ( type . flags & TypeFlags . Union ) { resolveUnionTypeMembers ( < UnionType > type ) ; } else { resolveTypeReferenceMembers ( < TypeReference > type ) ; } } return < ResolvedType > type ; } function getPropertiesOfObjectType ( type ) { if ( type . flags & TypeFlags . ObjectType ) { return resolveObjectOrUnionTypeMembers ( < ObjectType > type ) . properties ; } return emptyArray ; } function getPropertyOfObjectType ( type , name ) { if ( type . flags & TypeFlags . ObjectType ) { var resolved = resolveObjectOrUnionTypeMembers ( < ObjectType > type ) ; if ( hasProperty ( resolved . members , name ) ) { var symbol = resolved . members [ name ] ; if ( symbolIsValue ( symbol ) ) { return symbol ; } } } } function getPropertiesOfUnionType ( type ) { var result = [ ] ; forEach ( getPropertiesOfType ( type . types [ 0 ] ) , prop => { var unionProp = getPropertyOfUnionType ( type , prop . name ) ; if ( unionProp ) { result . push ( unionProp ) ; } } ) ; return result ; } function getPropertiesOfType ( type ) { if ( type . flags & TypeFlags . Union ) { return getPropertiesOfUnionType ( < UnionType > type ) ; } return getPropertiesOfObjectType ( getApparentType ( type ) ) ; } function getApparentType ( type ) { if ( type . flags & TypeFlags . TypeParameter ) { do { type = getConstraintOfTypeParameter ( < TypeParameter > type ) ; } while ( type && type . flags & TypeFlags . TypeParameter ) ; if ( ! type ) { type = emptyObjectType ; } } if ( type . flags & TypeFlags . StringLike ) { type = globalStringType ; } else if ( type . flags & TypeFlags . NumberLike ) { type = globalNumberType ; } else if ( type . flags & TypeFlags . Boolean ) { type = globalBooleanType ; } return type ; } function createUnionProperty ( unionType , name ) { var types = unionType . types ; var props ; for ( var i = 0 ; i < types . length ; i ++ ) { var type = getApparentType ( types [ i ] ) ; if ( type !== unknownType ) { var prop = getPropertyOfType ( type , name ) ; if ( ! prop ) { return undefined ; } if ( ! props ) { props = [ prop ] ; } else { props . push ( prop ) ; } } } var propTypes = [ ] ; var declarations = [ ] ; for ( var i = 0 ; i < props . length ; i ++ ) { var prop = props [ i ] ; if ( prop . declarations ) { declarations . push . apply ( declarations , prop . declarations ) ; } propTypes . push ( getTypeOfSymbol ( prop ) ) ; } var result = < TransientSymbol > createSymbol ( SymbolFlags . Property | SymbolFlags . Transient | SymbolFlags . UnionProperty , name ) ; result . unionType = unionType ; result . declarations = declarations ; result . type = getUnionType ( propTypes ) ; return result ; } function getPropertyOfUnionType ( type , name ) { var properties = type . resolvedProperties || ( type . resolvedProperties = { } ) ; if ( hasProperty ( properties , name ) ) { return properties [ name ] ; } var property = createUnionProperty ( type , name ) ; if ( property ) { properties [ name ] = property ; } return property ; } function getPropertyOfType ( type , name ) { if ( type . flags & TypeFlags . Union ) { return getPropertyOfUnionType ( < UnionType > type , name ) ; } if ( ! ( type . flags & TypeFlags . ObjectType ) ) { type = getApparentType ( type ) ; if ( ! ( type . flags & TypeFlags . ObjectType ) ) { return undefined ; } } var resolved = resolveObjectOrUnionTypeMembers ( type ) ; if ( hasProperty ( resolved . members , name ) ) { var symbol = resolved . members [ name ] ; if ( symbolIsValue ( symbol ) ) { return symbol ; } } if ( resolved === anyFunctionType || resolved . callSignatures . length || resolved . constructSignatures . length ) { var symbol = getPropertyOfObjectType ( globalFunctionType , name ) ; if ( symbol ) return symbol ; } return getPropertyOfObjectType ( globalObjectType , name ) ; } function getSignaturesOfObjectOrUnionType ( type , kind ) { if ( type . flags & ( TypeFlags . ObjectType | TypeFlags . Union ) ) { var resolved = resolveObjectOrUnionTypeMembers ( < ObjectType > type ) ; return kind === SignatureKind . Call ? resolved . callSignatures : resolved . constructSignatures ; } return emptyArray ; } function getSignaturesOfType ( type , kind ) { return getSignaturesOfObjectOrUnionType ( getApparentType ( type ) , kind ) ; } function getIndexTypeOfObjectOrUnionType ( type , kind ) { if ( type . flags & ( TypeFlags . ObjectType | TypeFlags . Union ) ) { var resolved = resolveObjectOrUnionTypeMembers ( < ObjectType > type ) ; return kind === IndexKind . String ? resolved . stringIndexType : resolved . numberIndexType ; } } function getIndexTypeOfType ( type , kind ) { return getIndexTypeOfObjectOrUnionType ( getApparentType ( type ) , kind ) ; } function getTypeParametersFromDeclaration ( typeParameterDeclarations ) { var result = [ ] ; forEach ( typeParameterDeclarations , node => { var tp = getDeclaredTypeOfTypeParameter ( node . symbol ) ; if ( ! contains ( result , tp ) ) { result . push ( tp ) ; } } ) ; return result ; } function getSignatureFromDeclaration ( declaration ) { var links = getNodeLinks ( declaration ) ; if ( ! links . resolvedSignature ) { var classType = declaration . kind === SyntaxKind . Constructor ? getDeclaredTypeOfClass ( ( < ClassDeclaration > declaration . parent ) . symbol ) : undefined ; var typeParameters = classType ? classType . typeParameters : declaration . typeParameters ? getTypeParametersFromDeclaration ( declaration . typeParameters ) : undefined ; var parameters = [ ] ; var hasStringLiterals = false ; var minArgumentCount = - 1 ; for ( var i = 0 , n = declaration . parameters . length ; i < n ; i ++ ) { var param = declaration . parameters [ i ] ; parameters . push ( param . symbol ) ; if ( param . type && param . type . kind === SyntaxKind . StringLiteral ) { hasStringLiterals = true ; } if ( minArgumentCount < 0 ) { if ( param . initializer || param . questionToken || param . dotDotDotToken ) { minArgumentCount = i ; } } } if ( minArgumentCount < 0 ) { minArgumentCount = declaration . parameters . length ; } var returnType ; if ( classType ) { returnType = classType ; } else if ( declaration . type ) { returnType = getTypeFromTypeNode ( declaration . type ) ; } else { if ( declaration . kind === SyntaxKind . GetAccessor && ! hasComputedNameButNotSymbol ( declaration ) ) { var setter = < AccessorDeclaration > getDeclarationOfKind ( declaration . symbol , SyntaxKind . SetAccessor ) ; returnType = getAnnotatedAccessorType ( setter ) ; } if ( ! returnType && ! ( < FunctionLikeDeclaration > declaration ) . body ) { returnType = anyType ; } } links . resolvedSignature = createSignature ( declaration , typeParameters , parameters , returnType , minArgumentCount , hasRestParameters ( declaration ) , hasStringLiterals ) ; } return links . resolvedSignature ; } function getSignaturesOfSymbol ( symbol ) { if ( ! symbol ) return emptyArray ; var result = [ ] ; for ( var i = 0 , len = symbol . declarations . length ; i < len ; i ++ ) { var node = symbol . declarations [ i ] ; switch ( node . kind ) { case SyntaxKind . FunctionType : case SyntaxKind . ConstructorType : case SyntaxKind . FunctionDeclaration : case SyntaxKind . Method : case SyntaxKind . Constructor : case SyntaxKind . CallSignature : case SyntaxKind . ConstructSignature : case SyntaxKind . IndexSignature : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : case SyntaxKind . FunctionExpression : case SyntaxKind . ArrowFunction : if ( i > 0 && ( < FunctionLikeDeclaration > node ) . body ) { var previous = symbol . declarations [ i - 1 ] ; if ( node . parent === previous . parent && node . kind === previous . kind && node . pos === previous . end ) { break ; } } result . push ( getSignatureFromDeclaration ( < SignatureDeclaration > node ) ) ; } } return result ; } function getReturnTypeOfSignature ( signature ) { if ( ! signature . resolvedReturnType ) { signature . resolvedReturnType = resolvingType ; if ( signature . target ) { var type = instantiateType ( getReturnTypeOfSignature ( signature . target ) , signature . mapper ) ; } else if ( signature . unionSignatures ) { var type = getUnionType ( map ( signature . unionSignatures , getReturnTypeOfSignature ) ) ; } else { var type = getReturnTypeFromBody ( < FunctionLikeDeclaration > signature . declaration ) ; } if ( signature . resolvedReturnType === resolvingType ) { signature . resolvedReturnType = type ; } } else if ( signature . resolvedReturnType === resolvingType ) { signature . resolvedReturnType = anyType ; if ( compilerOptions . noImplicitAny ) { var declaration = < Declaration > signature . declaration ; if ( declaration . name ) { error ( declaration . name , Diagnostics . _0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions , declarationNameToString ( declaration . name ) ) ; } else { error ( declaration , Diagnostics . Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions ) ; } } } return signature . resolvedReturnType ; } function getRestTypeOfSignature ( signature ) { if ( signature . hasRestParameter ) { var type = getTypeOfSymbol ( signature . parameters [ signature . parameters . length - 1 ] ) ; if ( type . flags & TypeFlags . Reference && ( < TypeReference > type ) . target === globalArrayType ) { return ( < TypeReference > type ) . typeArguments [ 0 ] ; } } return anyType ; } function getSignatureInstantiation ( signature , typeArguments ) { return instantiateSignature ( signature , createTypeMapper ( signature . typeParameters , typeArguments ) , true ) ; } function getErasedSignature ( signature ) { if ( ! signature . typeParameters ) return signature ; if ( ! signature . erasedSignatureCache ) { if ( signature . target ) { signature . erasedSignatureCache = instantiateSignature ( getErasedSignature ( signature . target ) , signature . mapper ) ; } else { signature . erasedSignatureCache = instantiateSignature ( signature , createTypeEraser ( signature . typeParameters ) , true ) ; } } return signature . erasedSignatureCache ; } function getOrCreateTypeFromSignature ( signature ) { if ( ! signature . isolatedSignatureType ) { var isConstructor = signature . declaration . kind === SyntaxKind . Constructor || signature . declaration . kind === SyntaxKind . ConstructSignature ; var type = < ResolvedType > createObjectType ( TypeFlags . Anonymous | TypeFlags . FromSignature ) ; type . members = emptySymbols ; type . properties = emptyArray ; type . callSignatures = ! isConstructor ? [ signature ] : emptyArray ; type . constructSignatures = isConstructor ? [ signature ] : emptyArray ; signature . isolatedSignatureType = type ; } return signature . isolatedSignatureType ; } function getIndexSymbol ( symbol ) { return symbol . members [ "__index" ] ; } function getIndexDeclarationOfSymbol ( symbol , kind ) { var syntaxKind = kind === IndexKind . Number ? SyntaxKind . NumberKeyword : SyntaxKind . StringKeyword ; var indexSymbol = getIndexSymbol ( symbol ) ; if ( indexSymbol ) { var len = indexSymbol . declarations . length ; for ( var i = 0 ; i < len ; i ++ ) { var node = < SignatureDeclaration > indexSymbol . declarations [ i ] ; if ( node . parameters . length === 1 ) { var parameter = node . parameters [ 0 ] ; if ( parameter && parameter . type && parameter . type . kind === syntaxKind ) { return node ; } } } } return undefined ; } function getIndexTypeOfSymbol ( symbol , kind ) { var declaration = getIndexDeclarationOfSymbol ( symbol , kind ) ; return declaration ? declaration . type ? getTypeFromTypeNode ( declaration . type ) : anyType : undefined ; } function getConstraintOfTypeParameter ( type ) { if ( ! type . constraint ) { if ( type . target ) { var targetConstraint = getConstraintOfTypeParameter ( type . target ) ; type . constraint = targetConstraint ? instantiateType ( targetConstraint , type . mapper ) : noConstraintType ; } else { type . constraint = getTypeFromTypeNode ( ( < TypeParameterDeclaration > getDeclarationOfKind ( type . symbol , SyntaxKind . TypeParameter ) ) . constraint ) ; } } return type . constraint === noConstraintType ? undefined : type . constraint ; } function getTypeListId ( types ) { switch ( types . length ) { case 1 : return "" + types [ 0 ] . id ; case 2 : return types [ 0 ] . id + "," + types [ 1 ] . id ; default : var result = "" ; for ( var i = 0 ; i < types . length ; i ++ ) { if ( i > 0 ) result += "," ; result += types [ i ] . id ; } return result ; } } function createTypeReference ( target , typeArguments ) { var id = getTypeListId ( typeArguments ) ; var type = target . instantiations [ id ] ; if ( ! type ) { type = target . instantiations [ id ] = < TypeReference > createObjectType ( TypeFlags . Reference , target . symbol ) ; type . target = target ; type . typeArguments = typeArguments ; } return type ; } function isTypeParameterReferenceIllegalInConstraint ( typeReferenceNode , typeParameterSymbol ) { var links = getNodeLinks ( typeReferenceNode ) ; if ( links . isIllegalTypeReferenceInConstraint !== undefined ) { return links . isIllegalTypeReferenceInConstraint ; } var currentNode = typeReferenceNode ; while ( ! forEach ( typeParameterSymbol . declarations , d => d . parent === currentNode . parent ) ) { currentNode = currentNode . parent ; } links . isIllegalTypeReferenceInConstraint = currentNode . kind === SyntaxKind . TypeParameter ; return links . isIllegalTypeReferenceInConstraint ; } function checkTypeParameterHasIllegalReferencesInConstraint ( typeParameter ) { var typeParameterSymbol ; function check ( n ) { if ( n . kind === SyntaxKind . TypeReference && ( < TypeReferenceNode > n ) . typeName . kind === SyntaxKind . Identifier ) { var links = getNodeLinks ( n ) ; if ( links . isIllegalTypeReferenceInConstraint === undefined ) { var symbol = resolveName ( typeParameter , ( < Identifier > ( < TypeReferenceNode > n ) . typeName ) . text , SymbolFlags . Type , undefined , undefined ) ; if ( symbol && ( symbol . flags & SymbolFlags . TypeParameter ) ) { links . isIllegalTypeReferenceInConstraint = forEach ( symbol . declarations , d => d . parent == typeParameter . parent ) ; } } if ( links . isIllegalTypeReferenceInConstraint ) { error ( typeParameter , Diagnostics . Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list ) ; } } forEachChild ( n , check ) ; } if ( typeParameter . constraint ) { typeParameterSymbol = getSymbolOfNode ( typeParameter ) ; check ( typeParameter . constraint ) ; } } function getTypeFromTypeReferenceNode ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { var symbol = resolveEntityName ( node , node . typeName , SymbolFlags . Type ) ; if ( symbol ) { var type ; if ( ( symbol . flags & SymbolFlags . TypeParameter ) && isTypeParameterReferenceIllegalInConstraint ( node , symbol ) ) { type = unknownType ; } else { type = getDeclaredTypeOfSymbol ( symbol ) ; if ( type . flags & ( TypeFlags . Class | TypeFlags . Interface ) && type . flags & TypeFlags . Reference ) { var typeParameters = ( < InterfaceType > type ) . typeParameters ; if ( node . typeArguments && node . typeArguments . length === typeParameters . length ) { type = createTypeReference ( < GenericType > type , map ( node . typeArguments , getTypeFromTypeNode ) ) ; } else { error ( node , Diagnostics . Generic_type_0_requires_1_type_argument_s , typeToString ( type , undefined , TypeFormatFlags . WriteArrayAsGenericType ) , typeParameters . length ) ; type = undefined ; } } else { if ( node . typeArguments ) { error ( node , Diagnostics . Type_0_is_not_generic , typeToString ( type ) ) ; type = undefined ; } } } } links . resolvedType = type || unknownType ; } return links . resolvedType ; } function getTypeFromTypeQueryNode ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { links . resolvedType = getWidenedType ( checkExpressionOrQualifiedName ( node . exprName ) ) ; } return links . resolvedType ; } function getTypeOfGlobalSymbol ( symbol , arity ) { function getTypeDeclaration ( symbol ) { var declarations = symbol . declarations ; for ( var i = 0 ; i < declarations . length ; i ++ ) { var declaration = declarations [ i ] ; switch ( declaration . kind ) { case SyntaxKind . ClassDeclaration : case SyntaxKind . InterfaceDeclaration : case SyntaxKind . EnumDeclaration : return declaration ; } } } if ( ! symbol ) { return emptyObjectType ; } var type = getDeclaredTypeOfSymbol ( symbol ) ; if ( ! ( type . flags & TypeFlags . ObjectType ) ) { error ( getTypeDeclaration ( symbol ) , Diagnostics . Global_type_0_must_be_a_class_or_interface_type , symbol . name ) ; return emptyObjectType ; } if ( ( ( < InterfaceType > type ) . typeParameters ? ( < InterfaceType > type ) . typeParameters . length : 0 ) !== arity ) { error ( getTypeDeclaration ( symbol ) , Diagnostics . Global_type_0_must_have_1_type_parameter_s , symbol . name , arity ) ; return emptyObjectType ; } return < ObjectType > type ; } function getGlobalSymbol ( name ) { return resolveName ( undefined , name , SymbolFlags . Type , Diagnostics . Cannot_find_global_type_0 , name ) ; } function getGlobalType ( name ) { return getTypeOfGlobalSymbol ( getGlobalSymbol ( name ) , 0 ) ; } function createArrayType ( elementType ) { var arrayType = globalArrayType || getDeclaredTypeOfSymbol ( globalArraySymbol ) ; return arrayType !== emptyObjectType ? createTypeReference ( < GenericType > arrayType , [ elementType ] ) : emptyObjectType ; } function getTypeFromArrayTypeNode ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { links . resolvedType = createArrayType ( getTypeFromTypeNode ( node . elementType ) ) ; } return links . resolvedType ; } function createTupleType ( elementTypes ) { var id = getTypeListId ( elementTypes ) ; var type = tupleTypes [ id ] ; if ( ! type ) { type = tupleTypes [ id ] = < TupleType > createObjectType ( TypeFlags . Tuple ) ; type . elementTypes = elementTypes ; } return type ; } function getTypeFromTupleTypeNode ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { links . resolvedType = createTupleType ( map ( node . elementTypes , getTypeFromTypeNode ) ) ; } return links . resolvedType ; } function addTypeToSortedSet ( sortedSet , type ) { if ( type . flags & TypeFlags . Union ) { addTypesToSortedSet ( sortedSet , ( < UnionType > type ) . types ) ; } else { var i = 0 ; var id = type . id ; while ( i < sortedSet . length && sortedSet [ i ] . id < id ) { i ++ ; } if ( i === sortedSet . length || sortedSet [ i ] . id !== id ) { sortedSet . splice ( i , 0 , type ) ; } } } function addTypesToSortedSet ( sortedTypes , types ) { for ( var i = 0 , len = types . length ; i < len ; i ++ ) { addTypeToSortedSet ( sortedTypes , types [ i ] ) ; } } function isSubtypeOfAny ( candidate , types ) { for ( var i = 0 , len = types . length ; i < len ; i ++ ) { if ( candidate !== types [ i ] && isTypeSubtypeOf ( candidate , types [ i ] ) ) { return true ; } } return false ; } function removeSubtypes ( types ) { var i = types . length ; while ( i > 0 ) { i -- ; if ( isSubtypeOfAny ( types [ i ] , types ) ) { types . splice ( i , 1 ) ; } } } function containsAnyType ( types ) { for ( var i = 0 ; i < types . length ; i ++ ) { if ( types [ i ] . flags & TypeFlags . Any ) { return true ; } } return false ; } function removeAllButLast ( types , typeToRemove ) { var i = types . length ; while ( i > 0 && types . length > 1 ) { i -- ; if ( types [ i ] === typeToRemove ) { types . splice ( i , 1 ) ; } } } function getUnionType ( types , noSubtypeReduction ? ) { if ( types . length === 0 ) { return emptyObjectType ; } var sortedTypes = [ ] ; addTypesToSortedSet ( sortedTypes , types ) ; if ( noSubtypeReduction ) { if ( containsAnyType ( sortedTypes ) ) { return anyType ; } removeAllButLast ( sortedTypes , undefinedType ) ; removeAllButLast ( sortedTypes , nullType ) ; } else { removeSubtypes ( sortedTypes ) ; } if ( sortedTypes . length === 1 ) { return sortedTypes [ 0 ] ; } var id = getTypeListId ( sortedTypes ) ; var type = unionTypes [ id ] ; if ( ! type ) { type = unionTypes [ id ] = < UnionType > createObjectType ( TypeFlags . Union ) ; type . types = sortedTypes ; } return type ; } function getTypeFromUnionTypeNode ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { links . resolvedType = getUnionType ( map ( node . types , getTypeFromTypeNode ) , true ) ; } return links . resolvedType ; } function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { links . resolvedType = createObjectType ( TypeFlags . Anonymous , node . symbol ) ; } return links . resolvedType ; } function getStringLiteralType ( node ) { if ( hasProperty ( stringLiteralTypes , node . text ) ) { return stringLiteralTypes [ node . text ] ; } var type = stringLiteralTypes [ node . text ] = < StringLiteralType > createType ( TypeFlags . StringLiteral ) ; type . text = getTextOfNode ( node ) ; return type ; } function getTypeFromStringLiteral ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedType ) { links . resolvedType = getStringLiteralType ( node ) ; } return links . resolvedType ; } function getTypeFromTypeNode ( node ) { switch ( node . kind ) { case SyntaxKind . AnyKeyword : return anyType ; case SyntaxKind . StringKeyword : return stringType ; case SyntaxKind . NumberKeyword : return numberType ; case SyntaxKind . BooleanKeyword : return booleanType ; case SyntaxKind . VoidKeyword : return voidType ; case SyntaxKind . StringLiteral : return getTypeFromStringLiteral ( < LiteralExpression > node ) ; case SyntaxKind . TypeReference : return getTypeFromTypeReferenceNode ( < TypeReferenceNode > node ) ; case SyntaxKind . TypeQuery : return getTypeFromTypeQueryNode ( < TypeQueryNode > node ) ; case SyntaxKind . ArrayType : return getTypeFromArrayTypeNode ( < ArrayTypeNode > node ) ; case SyntaxKind . TupleType : return getTypeFromTupleTypeNode ( < TupleTypeNode > node ) ; case SyntaxKind . UnionType : return getTypeFromUnionTypeNode ( < UnionTypeNode > node ) ; case SyntaxKind . ParenthesizedType : return getTypeFromTypeNode ( ( < ParenthesizedTypeNode > node ) . type ) ; case SyntaxKind . FunctionType : case SyntaxKind . ConstructorType : case SyntaxKind . TypeLiteral : return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode ( node ) ; case SyntaxKind . Identifier : case SyntaxKind . QualifiedName : var symbol = getSymbolInfo ( node ) ; return symbol && getDeclaredTypeOfSymbol ( symbol ) ; default : return unknownType ; } } function instantiateList < T > ( items , mapper , instantiator ) { if ( items && items . length ) { var result = [ ] ; for ( var i = 0 ; i < items . length ; i ++ ) { result . push ( instantiator ( items [ i ] , mapper ) ) ; } return result ; } return items ; } function createUnaryTypeMapper ( source , target ) { return t => t === source ? target : t ; } function createBinaryTypeMapper ( source1 , target1 , source2 , target2 ) { return t => t === source1 ? target1 : t === source2 ? target2 : t ; } function createTypeMapper ( sources , targets ) { switch ( sources . length ) { case 1 : return createUnaryTypeMapper ( sources [ 0 ] , targets [ 0 ] ) ; case 2 : return createBinaryTypeMapper ( sources [ 0 ] , targets [ 0 ] , sources [ 1 ] , targets [ 1 ] ) ; } return t => { for ( var i = 0 ; i < sources . length ; i ++ ) { if ( t === sources [ i ] ) return targets [ i ] ; } return t ; } ; } function createUnaryTypeEraser ( source ) { return t => t === source ? anyType : t ; } function createBinaryTypeEraser ( source1 , source2 ) { return t => t === source1 || t === source2 ? anyType : t ; } function createTypeEraser ( sources ) { switch ( sources . length ) { case 1 : return createUnaryTypeEraser ( sources [ 0 ] ) ; case 2 : return createBinaryTypeEraser ( sources [ 0 ] , sources [ 1 ] ) ; } return t => { for ( var i = 0 ; i < sources . length ; i ++ ) { if ( t === sources [ i ] ) return anyType ; } return t ; } ; } function createInferenceMapper ( context ) { return t => { for ( var i = 0 ; i < context . typeParameters . length ; i ++ ) { if ( t === context . typeParameters [ i ] ) { return getInferredType ( context , i ) ; } } return t ; } ; } function identityMapper ( type ) { return type ; } function combineTypeMappers ( mapper1 , mapper2 ) { return t => mapper2 ( mapper1 ( t ) ) ; } function instantiateTypeParameter ( typeParameter , mapper ) { var result = < TypeParameter > createType ( TypeFlags . TypeParameter ) ; result . symbol = typeParameter . symbol ; if ( typeParameter . constraint ) { result . constraint = instantiateType ( typeParameter . constraint , mapper ) ; } else { result . target = typeParameter ; result . mapper = mapper ; } return result ; } function instantiateSignature ( signature , mapper , eraseTypeParameters ? ) { if ( signature . typeParameters && ! eraseTypeParameters ) { var freshTypeParameters = instantiateList ( signature . typeParameters , mapper , instantiateTypeParameter ) ; mapper = combineTypeMappers ( createTypeMapper ( signature . typeParameters , freshTypeParameters ) , mapper ) ; } var result = createSignature ( signature . declaration , freshTypeParameters , instantiateList ( signature . parameters , mapper , instantiateSymbol ) , signature . resolvedReturnType ? instantiateType ( signature . resolvedReturnType , mapper ) : undefined , signature . minArgumentCount , signature . hasRestParameter , signature . hasStringLiterals ) ; result . target = signature ; result . mapper = mapper ; return result ; } function instantiateSymbol ( symbol , mapper ) { if ( symbol . flags & SymbolFlags . Instantiated ) { var links = getSymbolLinks ( symbol ) ; symbol = links . target ; mapper = combineTypeMappers ( links . mapper , mapper ) ; } var result = < TransientSymbol > createSymbol ( SymbolFlags . Instantiated | SymbolFlags . Transient | symbol . flags , symbol . name ) ; result . declarations = symbol . declarations ; result . parent = symbol . parent ; result . target = symbol ; result . mapper = mapper ; if ( symbol . valueDeclaration ) { result . valueDeclaration = symbol . valueDeclaration ; } return result ; } function instantiateAnonymousType ( type , mapper ) { var result = < ResolvedType > createObjectType ( TypeFlags . Anonymous , type . symbol ) ; result . properties = instantiateList ( getPropertiesOfObjectType ( type ) , mapper , instantiateSymbol ) ; result . members = createSymbolTable ( result . properties ) ; result . callSignatures = instantiateList ( getSignaturesOfType ( type , SignatureKind . Call ) , mapper , instantiateSignature ) ; result . constructSignatures = instantiateList ( getSignaturesOfType ( type , SignatureKind . Construct ) , mapper , instantiateSignature ) ; var stringIndexType = getIndexTypeOfType ( type , IndexKind . String ) ; var numberIndexType = getIndexTypeOfType ( type , IndexKind . Number ) ; if ( stringIndexType ) result . stringIndexType = instantiateType ( stringIndexType , mapper ) ; if ( numberIndexType ) result . numberIndexType = instantiateType ( numberIndexType , mapper ) ; return result ; } function instantiateType ( type , mapper ) { if ( mapper !== identityMapper ) { if ( type . flags & TypeFlags . TypeParameter ) { return mapper ( type ) ; } if ( type . flags & TypeFlags . Anonymous ) { return type . symbol && type . symbol . flags & ( SymbolFlags . Function | SymbolFlags . Method | SymbolFlags . TypeLiteral | SymbolFlags . ObjectLiteral ) ? instantiateAnonymousType ( < ObjectType > type , mapper ) : type ; } if ( type . flags & TypeFlags . Reference ) { return createTypeReference ( ( < TypeReference > type ) . target , instantiateList ( ( < TypeReference > type ) . typeArguments , mapper , instantiateType ) ) ; } if ( type . flags & TypeFlags . Tuple ) { return createTupleType ( instantiateList ( ( < TupleType > type ) . elementTypes , mapper , instantiateType ) ) ; } if ( type . flags & TypeFlags . Union ) { return getUnionType ( instantiateList ( ( < UnionType > type ) . types , mapper , instantiateType ) , true ) ; } } return type ; } function isContextSensitive ( node ) { Debug . assert ( node . kind !== SyntaxKind . Method || isObjectLiteralMethod ( node ) ) ; switch ( node . kind ) { case SyntaxKind . FunctionExpression : case SyntaxKind . ArrowFunction : return isContextSensitiveFunctionLikeDeclaration ( < FunctionExpression > node ) ; case SyntaxKind . ObjectLiteralExpression : return forEach ( ( < ObjectLiteralExpression > node ) . properties , isContextSensitive ) ; case SyntaxKind . ArrayLiteralExpression : return forEach ( ( < ArrayLiteralExpression > node ) . elements , isContextSensitive ) ; case SyntaxKind . ConditionalExpression : return isContextSensitive ( ( < ConditionalExpression > node ) . whenTrue ) || isContextSensitive ( ( < ConditionalExpression > node ) . whenFalse ) ; case SyntaxKind . BinaryExpression : return ( < BinaryExpression > node ) . operator === SyntaxKind . BarBarToken && ( isContextSensitive ( ( < BinaryExpression > node ) . left ) || isContextSensitive ( ( < BinaryExpression > node ) . right ) ) ; case SyntaxKind . PropertyAssignment : return isContextSensitive ( ( < PropertyAssignment > node ) . initializer ) ; case SyntaxKind . Method : return isContextSensitiveFunctionLikeDeclaration ( < MethodDeclaration > node ) ; } return false ; } function isContextSensitiveFunctionLikeDeclaration ( node ) { return ! node . typeParameters && ! forEach ( node . parameters , p => p . type ) ; } function getTypeWithoutConstructors ( type ) { if ( type . flags & TypeFlags . ObjectType ) { var resolved = resolveObjectOrUnionTypeMembers ( < ObjectType > type ) ; if ( resolved . constructSignatures . length ) { var result = < ResolvedType > createObjectType ( TypeFlags . Anonymous , type . symbol ) ; result . members = resolved . members ; result . properties = resolved . properties ; result . callSignatures = resolved . callSignatures ; result . constructSignatures = emptyArray ; type = result ; } } return type ; } var subtypeRelation = { } ; var assignableRelation = { } ; var identityRelation = { } ; function isTypeIdenticalTo ( source , target ) { return checkTypeRelatedTo ( source , target , identityRelation , undefined ) ; } function compareTypes ( source , target ) { return checkTypeRelatedTo ( source , target , identityRelation , undefined ) ? Ternary . True : Ternary . False ; } function isTypeSubtypeOf ( source , target ) { return checkTypeSubtypeOf ( source , target , undefined ) ; } function isTypeAssignableTo ( source , target ) { return checkTypeAssignableTo ( source , target , undefined ) ; } function checkTypeSubtypeOf ( source , target , errorNode , headMessage ? , containingMessageChain ? ) { return checkTypeRelatedTo ( source , target , subtypeRelation , errorNode , headMessage , containingMessageChain ) ; } function checkTypeAssignableTo ( source , target , errorNode , headMessage ? ) { return checkTypeRelatedTo ( source , target , assignableRelation , errorNode , headMessage ) ; } function isSignatureAssignableTo ( source , target ) { var sourceType = getOrCreateTypeFromSignature ( source ) ; var targetType = getOrCreateTypeFromSignature ( target ) ; return checkTypeRelatedTo ( sourceType , targetType , assignableRelation , undefined ) ; } function checkTypeRelatedTo ( source , target , relation , errorNode , headMessage ? , containingMessageChain ? ) { var errorInfo ; var sourceStack ; var targetStack ; var maybeStack ; var expandingFlags ; var depth = 0 ; var overflow = false ; Debug . assert ( relation !== identityRelation || ! errorNode , "no error reporting in identity checking" ) ; var result = isRelatedTo ( source , target , errorNode !== undefined , headMessage ) ; if ( overflow ) { error ( errorNode , Diagnostics . Excessive_stack_depth_comparing_types_0_and_1 , typeToString ( source ) , typeToString ( target ) ) ; } else if ( errorInfo ) { if ( containingMessageChain ) { errorInfo = concatenateDiagnosticMessageChains ( containingMessageChain , errorInfo ) ; } addDiagnostic ( createDiagnosticForNodeFromMessageChain ( errorNode , errorInfo , program . getCompilerHost ( ) . getNewLine ( ) ) ) ; } return result !== Ternary . False ; function reportError ( message , arg0 ? , arg1 ? , arg2 ? ) { errorInfo = chainDiagnosticMessages ( errorInfo , message , arg0 , arg1 , arg2 ) ; } function isRelatedTo ( source , target , reportErrors ? , headMessage ? ) { var result ; if ( relation === identityRelation ) { if ( source === target ) return Ternary . True ; } else { if ( source === target ) return Ternary . True ; if ( target . flags & TypeFlags . Any ) return Ternary . True ; if ( source === undefinedType ) return Ternary . True ; if ( source === nullType && target !== undefinedType ) return Ternary . True ; if ( source . flags & TypeFlags . Enum && target === numberType ) return Ternary . True ; if ( source . flags & TypeFlags . StringLiteral && target === stringType ) return Ternary . True ; if ( relation === assignableRelation ) { if ( source . flags & TypeFlags . Any ) return Ternary . True ; if ( source === numberType && target . flags & TypeFlags . Enum ) return Ternary . True ; } } if ( source . flags & TypeFlags . Union ) { if ( result = unionTypeRelatedToType ( < UnionType > source , target , reportErrors ) ) { return result ; } } else if ( target . flags & TypeFlags . Union ) { if ( result = typeRelatedToUnionType ( source , < UnionType > target , reportErrors ) ) { return result ; } } else if ( source . flags & TypeFlags . TypeParameter && target . flags & TypeFlags . TypeParameter ) { if ( result = typeParameterRelatedTo ( < TypeParameter > source , < TypeParameter > target , reportErrors ) ) { return result ; } } else { var saveErrorInfo = errorInfo ; if ( source . flags & TypeFlags . Reference && target . flags & TypeFlags . Reference && ( < TypeReference > source ) . target === ( < TypeReference > target ) . target ) { if ( result = typesRelatedTo ( ( < TypeReference > source ) . typeArguments , ( < TypeReference > target ) . typeArguments , reportErrors ) ) { return result ; } } var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo ; var sourceOrApparentType = relation === identityRelation ? source : getApparentType ( source ) ; if ( sourceOrApparentType . flags & TypeFlags . ObjectType && target . flags & TypeFlags . ObjectType && ( result = objectTypeRelatedTo ( sourceOrApparentType , < ObjectType > target , reportStructuralErrors ) ) ) { errorInfo = saveErrorInfo ; return result ; } } if ( reportErrors ) { headMessage = headMessage || Diagnostics . Type_0_is_not_assignable_to_type_1 ; reportError ( headMessage , typeToString ( source ) , typeToString ( target ) ) ; } return Ternary . False ; } function typeRelatedToUnionType ( source , target , reportErrors ) { var targetTypes = target . types ; for ( var i = 0 , len = targetTypes . length ; i < len ; i ++ ) { var related = isRelatedTo ( source , targetTypes [ i ] , reportErrors && i === len - 1 ) ; if ( related ) { return related ; } } return Ternary . False ; } function unionTypeRelatedToType ( source , target , reportErrors ) { var result = Ternary . True ; var sourceTypes = source . types ; for ( var i = 0 , len = sourceTypes . length ; i < len ; i ++ ) { var related = isRelatedTo ( sourceTypes [ i ] , target , reportErrors ) ; if ( ! related ) { return Ternary . False ; } result &= related ; } return result ; } function typesRelatedTo ( sources , targets , reportErrors ) { var result = Ternary . True ; for ( var i = 0 , len = sources . length ; i < len ; i ++ ) { var related = isRelatedTo ( sources [ i ] , targets [ i ] , reportErrors ) ; if ( ! related ) { return Ternary . False ; } result &= related ; } return result ; } function typeParameterRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { if ( source . symbol . name !== target . symbol . name ) { return Ternary . False ; } if ( source . constraint === target . constraint ) { return Ternary . True ; } if ( source . constraint === noConstraintType || target . constraint === noConstraintType ) { return Ternary . False ; } return isRelatedTo ( source . constraint , target . constraint , reportErrors ) ; } else { while ( true ) { var constraint = getConstraintOfTypeParameter ( source ) ; if ( constraint === target ) return Ternary . True ; if ( ! ( constraint && constraint . flags & TypeFlags . TypeParameter ) ) break ; source = < TypeParameter > constraint ; } return Ternary . False ; } } function objectTypeRelatedTo ( source , target , reportErrors ) { if ( overflow ) { return Ternary . False ; } var id = source . id + "," + target . id ; var related = relation [ id ] ; if ( related !== undefined ) { return related ? Ternary . True : Ternary . False ; } if ( depth > 0 ) { for ( var i = 0 ; i < depth ; i ++ ) { if ( maybeStack [ i ] [ id ] ) { return Ternary . Maybe ; } } if ( depth === 100 ) { overflow = true ; return Ternary . False ; } } else { sourceStack = [ ] ; targetStack = [ ] ; maybeStack = [ ] ; expandingFlags = 0 ; } sourceStack [ depth ] = source ; targetStack [ depth ] = target ; maybeStack [ depth ] = { } ; maybeStack [ depth ] [ id ] = true ; depth ++ ; var saveExpandingFlags = expandingFlags ; if ( ! ( expandingFlags & 1 ) && isDeeplyNestedGeneric ( source , sourceStack ) ) expandingFlags |= 1 ; if ( ! ( expandingFlags & 2 ) && isDeeplyNestedGeneric ( target , targetStack ) ) expandingFlags |= 2 ; if ( expandingFlags === 3 ) { var result = Ternary . Maybe ; } else { var result = propertiesRelatedTo ( source , target , reportErrors ) ; if ( result ) { result &= signaturesRelatedTo ( source , target , SignatureKind . Call , reportErrors ) ; if ( result ) { result &= signaturesRelatedTo ( source , target , SignatureKind . Construct , reportErrors ) ; if ( result ) { result &= stringIndexTypesRelatedTo ( source , target , reportErrors ) ; if ( result ) { result &= numberIndexTypesRelatedTo ( source , target , reportErrors ) ; } } } } } expandingFlags = saveExpandingFlags ; depth -- ; if ( result ) { var maybeCache = maybeStack [ depth ] ; var destinationCache = result === Ternary . True || depth === 0 ? relation : maybeStack [ depth - 1 ] ; for ( var p in maybeCache ) { destinationCache [ p ] = maybeCache [ p ] ; } } else { relation [ id ] = false ; } return result ; } function isDeeplyNestedGeneric ( type , stack ) { if ( type . flags & TypeFlags . Reference && depth >= 10 ) { var target = ( < TypeReference > type ) . target ; var count = 0 ; for ( var i = 0 ; i < depth ; i ++ ) { var t = stack [ i ] ; if ( t . flags & TypeFlags . Reference && ( < TypeReference > t ) . target === target ) { count ++ ; if ( count >= 10 ) return true ; } } } return false ; } function propertiesRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { return propertiesIdenticalTo ( source , target ) ; } var result = Ternary . True ; var properties = getPropertiesOfObjectType ( target ) ; for ( var i = 0 ; i < properties . length ; i ++ ) { var targetProp = properties [ i ] ; var sourceProp = getPropertyOfType ( source , targetProp . name ) ; if ( sourceProp !== targetProp ) { if ( ! sourceProp ) { if ( relation === subtypeRelation || ! isOptionalProperty ( targetProp ) ) { if ( reportErrors ) { reportError ( Diagnostics . Property_0_is_missing_in_type_1 , symbolToString ( targetProp ) , typeToString ( source ) ) ; } return Ternary . False ; } } else if ( ! ( targetProp . flags & SymbolFlags . Prototype ) ) { var sourceFlags = getDeclarationFlagsFromSymbol ( sourceProp ) ; var targetFlags = getDeclarationFlagsFromSymbol ( targetProp ) ; if ( sourceFlags & NodeFlags . Private || targetFlags & NodeFlags . Private ) { if ( sourceProp . valueDeclaration !== targetProp . valueDeclaration ) { if ( reportErrors ) { if ( sourceFlags & NodeFlags . Private && targetFlags & NodeFlags . Private ) { reportError ( Diagnostics . Types_have_separate_declarations_of_a_private_property_0 , symbolToString ( targetProp ) ) ; } else { reportError ( Diagnostics . Property_0_is_private_in_type_1_but_not_in_type_2 , symbolToString ( targetProp ) , typeToString ( sourceFlags & NodeFlags . Private ? source : target ) , typeToString ( sourceFlags & NodeFlags . Private ? target : source ) ) ; } } return Ternary . False ; } } else if ( targetFlags & NodeFlags . Protected ) { var sourceDeclaredInClass = sourceProp . parent && sourceProp . parent . flags & SymbolFlags . Class ; var sourceClass = sourceDeclaredInClass ? < InterfaceType > getDeclaredTypeOfSymbol ( sourceProp . parent ) : undefined ; var targetClass = < InterfaceType > getDeclaredTypeOfSymbol ( targetProp . parent ) ; if ( ! sourceClass || ! hasBaseType ( sourceClass , targetClass ) ) { if ( reportErrors ) { reportError ( Diagnostics . Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2 , symbolToString ( targetProp ) , typeToString ( sourceClass || source ) , typeToString ( targetClass ) ) ; } return Ternary . False ; } } else if ( sourceFlags & NodeFlags . Protected ) { if ( reportErrors ) { reportError ( Diagnostics . Property_0_is_protected_in_type_1_but_public_in_type_2 , symbolToString ( targetProp ) , typeToString ( source ) , typeToString ( target ) ) ; } return Ternary . False ; } var related = isRelatedTo ( getTypeOfSymbol ( sourceProp ) , getTypeOfSymbol ( targetProp ) , reportErrors ) ; if ( ! related ) { if ( reportErrors ) { reportError ( Diagnostics . Types_of_property_0_are_incompatible , symbolToString ( targetProp ) ) ; } return Ternary . False ; } result &= related ; if ( isOptionalProperty ( sourceProp ) && ! isOptionalProperty ( targetProp ) ) { if ( reportErrors ) { reportError ( Diagnostics . Property_0_is_optional_in_type_1_but_required_in_type_2 , symbolToString ( targetProp ) , typeToString ( source ) , typeToString ( target ) ) ; } return Ternary . False ; } } } } return result ; } function propertiesIdenticalTo ( source , target ) { var sourceProperties = getPropertiesOfObjectType ( source ) ; var targetProperties = getPropertiesOfObjectType ( target ) ; if ( sourceProperties . length !== targetProperties . length ) { return Ternary . False ; } var result = Ternary . True ; for ( var i = 0 , len = sourceProperties . length ; i < len ; ++ i ) { var sourceProp = sourceProperties [ i ] ; var targetProp = getPropertyOfObjectType ( target , sourceProp . name ) ; if ( ! targetProp ) { return Ternary . False ; } var related = compareProperties ( sourceProp , targetProp , isRelatedTo ) ; if ( ! related ) { return Ternary . False ; } result &= related ; } return result ; } function signaturesRelatedTo ( source , target , kind , reportErrors ) { if ( relation === identityRelation ) { return signaturesIdenticalTo ( source , target , kind ) ; } if ( target === anyFunctionType || source === anyFunctionType ) { return Ternary . True ; } var sourceSignatures = getSignaturesOfType ( source , kind ) ; var targetSignatures = getSignaturesOfType ( target , kind ) ; var result = Ternary . True ; var saveErrorInfo = errorInfo ; outer : for ( var i = 0 ; i < targetSignatures . length ; i ++ ) { var t = targetSignatures [ i ] ; if ( ! t . hasStringLiterals || target . flags & TypeFlags . FromSignature ) { var localErrors = reportErrors ; for ( var j = 0 ; j < sourceSignatures . length ; j ++ ) { var s = sourceSignatures [ j ] ; if ( ! s . hasStringLiterals || source . flags & TypeFlags . FromSignature ) { var related = signatureRelatedTo ( s , t , localErrors ) ; if ( related ) { result &= related ; errorInfo = saveErrorInfo ; continue outer ; } localErrors = false ; } } return Ternary . False ; } } return result ; } function signatureRelatedTo ( source , target , reportErrors ) { if ( source === target ) { return Ternary . True ; } if ( ! target . hasRestParameter && source . minArgumentCount > target . parameters . length ) { return Ternary . False ; } var sourceMax = source . parameters . length ; var targetMax = target . parameters . length ; var checkCount ; if ( source . hasRestParameter && target . hasRestParameter ) { checkCount = sourceMax > targetMax ? sourceMax : targetMax ; sourceMax -- ; targetMax -- ; } else if ( source . hasRestParameter ) { sourceMax -- ; checkCount = targetMax ; } else if ( target . hasRestParameter ) { targetMax -- ; checkCount = sourceMax ; } else { checkCount = sourceMax < targetMax ? sourceMax : targetMax ; } source = getErasedSignature ( source ) ; target = getErasedSignature ( target ) ; var result = Ternary . True ; for ( var i = 0 ; i < checkCount ; i ++ ) { var s = i < sourceMax ? getTypeOfSymbol ( source . parameters [ i ] ) : getRestTypeOfSignature ( source ) ; var t = i < targetMax ? getTypeOfSymbol ( target . parameters [ i ] ) : getRestTypeOfSignature ( target ) ; var saveErrorInfo = errorInfo ; var related = isRelatedTo ( s , t , reportErrors ) ; if ( ! related ) { related = isRelatedTo ( t , s , false ) ; if ( ! related ) { if ( reportErrors ) { reportError ( Diagnostics . Types_of_parameters_0_and_1_are_incompatible , source . parameters [ i < sourceMax ? i : sourceMax ] . name , target . parameters [ i < targetMax ? i : targetMax ] . name ) ; } return Ternary . False ; } errorInfo = saveErrorInfo ; } result &= related ; } var t = getReturnTypeOfSignature ( target ) ; if ( t === voidType ) return result ; var s = getReturnTypeOfSignature ( source ) ; return result & isRelatedTo ( s , t , reportErrors ) ; } function signaturesIdenticalTo ( source , target , kind ) { var sourceSignatures = getSignaturesOfType ( source , kind ) ; var targetSignatures = getSignaturesOfType ( target , kind ) ; if ( sourceSignatures . length !== targetSignatures . length ) { return Ternary . False ; } var result = Ternary . True ; for ( var i = 0 , len = sourceSignatures . length ; i < len ; ++ i ) { var related = compareSignatures ( sourceSignatures [ i ] , targetSignatures [ i ] , true , isRelatedTo ) ; if ( ! related ) { return Ternary . False ; } result &= related ; } return result ; } function stringIndexTypesRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { return indexTypesIdenticalTo ( IndexKind . String , source , target ) ; } var targetType = getIndexTypeOfType ( target , IndexKind . String ) ; if ( targetType ) { var sourceType = getIndexTypeOfType ( source , IndexKind . String ) ; if ( ! sourceType ) { if ( reportErrors ) { reportError ( Diagnostics . Index_signature_is_missing_in_type_0 , typeToString ( source ) ) ; } return Ternary . False ; } var related = isRelatedTo ( sourceType , targetType , reportErrors ) ; if ( ! related ) { if ( reportErrors ) { reportError ( Diagnostics . Index_signatures_are_incompatible ) ; } return Ternary . False ; } return related ; } return Ternary . True ; } function numberIndexTypesRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { return indexTypesIdenticalTo ( IndexKind . Number , source , target ) ; } var targetType = getIndexTypeOfType ( target , IndexKind . Number ) ; if ( targetType ) { var sourceStringType = getIndexTypeOfType ( source , IndexKind . String ) ; var sourceNumberType = getIndexTypeOfType ( source , IndexKind . Number ) ; if ( ! ( sourceStringType || sourceNumberType ) ) { if ( reportErrors ) { reportError ( Diagnostics . Index_signature_is_missing_in_type_0 , typeToString ( source ) ) ; } return Ternary . False ; } if ( sourceStringType && sourceNumberType ) { var related = isRelatedTo ( sourceStringType , targetType , false ) || isRelatedTo ( sourceNumberType , targetType , reportErrors ) ; } else { var related = isRelatedTo ( sourceStringType || sourceNumberType , targetType , reportErrors ) ; } if ( ! related ) { if ( reportErrors ) { reportError ( Diagnostics . Index_signatures_are_incompatible ) ; } return Ternary . False ; } return related ; } return Ternary . True ; } function indexTypesIdenticalTo ( indexKind , source , target ) { var targetType = getIndexTypeOfType ( target , indexKind ) ; var sourceType = getIndexTypeOfType ( source , indexKind ) ; if ( ! sourceType && ! targetType ) { return Ternary . True ; } if ( sourceType && targetType ) { return isRelatedTo ( sourceType , targetType ) ; } return Ternary . False ; } } function isPropertyIdenticalTo ( sourceProp , targetProp ) { return compareProperties ( sourceProp , targetProp , compareTypes ) !== Ternary . False ; } function compareProperties ( sourceProp , targetProp , compareTypes ) { if ( sourceProp === targetProp ) { return Ternary . True ; } var sourcePropAccessibility = getDeclarationFlagsFromSymbol ( sourceProp ) & ( NodeFlags . Private | NodeFlags . Protected ) ; var targetPropAccessibility = getDeclarationFlagsFromSymbol ( targetProp ) & ( NodeFlags . Private | NodeFlags . Protected ) ; if ( sourcePropAccessibility !== targetPropAccessibility ) { return Ternary . False ; } if ( sourcePropAccessibility ) { if ( getTargetSymbol ( sourceProp ) !== getTargetSymbol ( targetProp ) ) { return Ternary . False ; } } else { if ( isOptionalProperty ( sourceProp ) !== isOptionalProperty ( targetProp ) ) { return Ternary . False ; } } return compareTypes ( getTypeOfSymbol ( sourceProp ) , getTypeOfSymbol ( targetProp ) ) ; } function compareSignatures ( source , target , compareReturnTypes , compareTypes ) { if ( source === target ) { return Ternary . True ; } if ( source . parameters . length !== target . parameters . length || source . minArgumentCount !== target . minArgumentCount || source . hasRestParameter !== target . hasRestParameter ) { return Ternary . False ; } var result = Ternary . True ; if ( source . typeParameters && target . typeParameters ) { if ( source . typeParameters . length !== target . typeParameters . length ) { return Ternary . False ; } for ( var i = 0 , len = source . typeParameters . length ; i < len ; ++ i ) { var related = compareTypes ( source . typeParameters [ i ] , target . typeParameters [ i ] ) ; if ( ! related ) { return Ternary . False ; } result &= related ; } } else if ( source . typeParameters || source . typeParameters ) { return Ternary . False ; } source = getErasedSignature ( source ) ; target = getErasedSignature ( target ) ; for ( var i = 0 , len = source . parameters . length ; i < len ; i ++ ) { var s = source . hasRestParameter && i === len - 1 ? getRestTypeOfSignature ( source ) : getTypeOfSymbol ( source . parameters [ i ] ) ; var t = target . hasRestParameter && i === len - 1 ? getRestTypeOfSignature ( target ) : getTypeOfSymbol ( target . parameters [ i ] ) ; var related = compareTypes ( s , t ) ; if ( ! related ) { return Ternary . False ; } result &= related ; } if ( compareReturnTypes ) { result &= compareTypes ( getReturnTypeOfSignature ( source ) , getReturnTypeOfSignature ( target ) ) ; } return result ; } function isSupertypeOfEach ( candidate , types ) { for ( var i = 0 , len = types . length ; i < len ; i ++ ) { if ( candidate !== types [ i ] && ! isTypeSubtypeOf ( types [ i ] , candidate ) ) return false ; } return true ; } function getCommonSupertype ( types ) { return forEach ( types , t => isSupertypeOfEach ( t , types ) ? t : undefined ) ; } function reportNoCommonSupertypeError ( types , errorLocation , errorMessageChainHead ) { var bestSupertype ; var bestSupertypeDownfallType ; var bestSupertypeScore = 0 ; for ( var i = 0 ; i < types . length ; i ++ ) { var score = 0 ; var downfallType = undefined ; for ( var j = 0 ; j < types . length ; j ++ ) { if ( isTypeSubtypeOf ( types [ j ] , types [ i ] ) ) { score ++ ; } else if ( ! downfallType ) { downfallType = types [ j ] ; } } if ( score > bestSupertypeScore ) { bestSupertype = types [ i ] ; bestSupertypeDownfallType = downfallType ; bestSupertypeScore = score ; } if ( bestSupertypeScore === types . length - 1 ) { break ; } } checkTypeSubtypeOf ( bestSupertypeDownfallType , bestSupertype , errorLocation , Diagnostics . Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0 , errorMessageChainHead ) ; } function isTypeOfObjectLiteral ( type ) { return ( type . flags & TypeFlags . Anonymous ) && type . symbol && ( type . symbol . flags & SymbolFlags . ObjectLiteral ) ? true : false ; } function isArrayType ( type ) { return type . flags & TypeFlags . Reference && ( < TypeReference > type ) . target === globalArrayType ; } function getInnermostTypeOfNestedArrayTypes ( type ) { while ( isArrayType ( type ) ) { type = ( < GenericType > type ) . typeArguments [ 0 ] ; } return type ; } function getWidenedType ( type , suppressNoImplicitAnyErrors ? ) { if ( type . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) { return anyType ; } if ( type . flags & TypeFlags . Union ) { return getWidenedTypeOfUnion ( type ) ; } if ( isTypeOfObjectLiteral ( type ) ) { return getWidenedTypeOfObjectLiteral ( type ) ; } if ( isArrayType ( type ) ) { return getWidenedTypeOfArrayLiteral ( type ) ; } return type ; function getWidenedTypeOfUnion ( type ) { return getUnionType ( map ( ( < UnionType > type ) . types , t => getWidenedType ( t , suppressNoImplicitAnyErrors ) ) ) ; } function getWidenedTypeOfObjectLiteral ( type ) { var properties = getPropertiesOfObjectType ( type ) ; if ( properties . length ) { var widenedTypes = [ ] ; var propTypeWasWidened = false ; forEach ( properties , p => { var propType = getTypeOfSymbol ( p ) ; var widenedType = getWidenedType ( propType ) ; if ( propType !== widenedType ) { propTypeWasWidened = true ; if ( ! suppressNoImplicitAnyErrors && compilerOptions . noImplicitAny && getInnermostTypeOfNestedArrayTypes ( widenedType ) === anyType ) { error ( p . valueDeclaration , Diagnostics . Object_literal_s_property_0_implicitly_has_an_1_type , p . name , typeToString ( widenedType ) ) ; } } widenedTypes . push ( widenedType ) ; } ) ; if ( propTypeWasWidened ) { var members = { } ; var index = 0 ; forEach ( properties , p => { var symbol = < TransientSymbol > createSymbol ( SymbolFlags . Property | SymbolFlags . Transient | p . flags , p . name ) ; symbol . declarations = p . declarations ; symbol . parent = p . parent ; symbol . type = widenedTypes [ index ++ ] ; symbol . target = p ; if ( p . valueDeclaration ) symbol . valueDeclaration = p . valueDeclaration ; members [ symbol . name ] = symbol ; } ) ; var stringIndexType = getIndexTypeOfType ( type , IndexKind . String ) ; var numberIndexType = getIndexTypeOfType ( type , IndexKind . Number ) ; if ( stringIndexType ) stringIndexType = getWidenedType ( stringIndexType ) ; if ( numberIndexType ) numberIndexType = getWidenedType ( numberIndexType ) ; type = createAnonymousType ( type . symbol , members , emptyArray , emptyArray , stringIndexType , numberIndexType ) ; } } return type ; } function getWidenedTypeOfArrayLiteral ( type ) { var elementType = ( < TypeReference > type ) . typeArguments [ 0 ] ; var widenedType = getWidenedType ( elementType , suppressNoImplicitAnyErrors ) ; type = elementType !== widenedType ? createArrayType ( widenedType ) : type ; return type ; } } function forEachMatchingParameterType ( source , target , callback ) { var sourceMax = source . parameters . length ; var targetMax = target . parameters . length ; var count ; if ( source . hasRestParameter && target . hasRestParameter ) { count = sourceMax > targetMax ? sourceMax : targetMax ; sourceMax -- ; targetMax -- ; } else if ( source . hasRestParameter ) { sourceMax -- ; count = targetMax ; } else if ( target . hasRestParameter ) { targetMax -- ; count = sourceMax ; } else { count = sourceMax < targetMax ? sourceMax : targetMax ; } for ( var i = 0 ; i < count ; i ++ ) { var s = i < sourceMax ? getTypeOfSymbol ( source . parameters [ i ] ) : getRestTypeOfSignature ( source ) ; var t = i < targetMax ? getTypeOfSymbol ( target . parameters [ i ] ) : getRestTypeOfSignature ( target ) ; callback ( s , t ) ; } } function createInferenceContext ( typeParameters , inferUnionTypes ) { var inferences = [ ] ; for ( var i = 0 ; i < typeParameters . length ; i ++ ) { inferences . push ( { primary : undefined , secondary : undefined } ) ; } return { typeParameters : typeParameters , inferUnionTypes : inferUnionTypes , inferenceCount : 0 , inferences : inferences , inferredTypes : new Array ( typeParameters . length ) , } ; } function inferTypes ( context , source , target ) { var sourceStack ; var targetStack ; var depth = 0 ; var inferiority = 0 ; inferFromTypes ( source , target ) ; function isInProcess ( source , target ) { for ( var i = 0 ; i < depth ; i ++ ) { if ( source === sourceStack [ i ] && target === targetStack [ i ] ) return true ; } return false ; } function isWithinDepthLimit ( type , stack ) { if ( depth >= 5 ) { var target = ( < TypeReference > type ) . target ; var count = 0 ; for ( var i = 0 ; i < depth ; i ++ ) { var t = stack [ i ] ; if ( t . flags & TypeFlags . Reference && ( < TypeReference > t ) . target === target ) count ++ ; } return count < 5 ; } return true ; } function inferFromTypes ( source , target ) { if ( target . flags & TypeFlags . TypeParameter ) { var typeParameters = context . typeParameters ; for ( var i = 0 ; i < typeParameters . length ; i ++ ) { if ( target === typeParameters [ i ] ) { var inferences = context . inferences [ i ] ; var candidates = inferiority ? inferences . secondary || ( inferences . secondary = [ ] ) : inferences . primary || ( inferences . primary = [ ] ) ; if ( ! contains ( candidates , source ) ) candidates . push ( source ) ; break ; } } } else if ( source . flags & TypeFlags . Reference && target . flags & TypeFlags . Reference && ( < TypeReference > source ) . target === ( < TypeReference > target ) . target ) { var sourceTypes = ( < TypeReference > source ) . typeArguments ; var targetTypes = ( < TypeReference > target ) . typeArguments ; for ( var i = 0 ; i < sourceTypes . length ; i ++ ) { inferFromTypes ( sourceTypes [ i ] , targetTypes [ i ] ) ; } } else if ( target . flags & TypeFlags . Union ) { var targetTypes = ( < UnionType > target ) . types ; var typeParameterCount = 0 ; var typeParameter ; for ( var i = 0 ; i < targetTypes . length ; i ++ ) { var t = targetTypes [ i ] ; if ( t . flags & TypeFlags . TypeParameter && contains ( context . typeParameters , t ) ) { typeParameter = < TypeParameter > t ; typeParameterCount ++ ; } else { inferFromTypes ( source , t ) ; } } if ( typeParameterCount === 1 ) { inferiority ++ ; inferFromTypes ( source , typeParameter ) ; inferiority -- ; } } else if ( source . flags & TypeFlags . Union ) { var sourceTypes = ( < UnionType > source ) . types ; for ( var i = 0 ; i < sourceTypes . length ; i ++ ) { inferFromTypes ( sourceTypes [ i ] , target ) ; } } else if ( source . flags & TypeFlags . ObjectType && ( target . flags & ( TypeFlags . Reference | TypeFlags . Tuple ) || ( target . flags & TypeFlags . Anonymous ) && target . symbol && target . symbol . flags & ( SymbolFlags . Method | SymbolFlags . TypeLiteral ) ) ) { if ( ! isInProcess ( source , target ) && isWithinDepthLimit ( source , sourceStack ) && isWithinDepthLimit ( target , targetStack ) ) { if ( depth === 0 ) { sourceStack = [ ] ; targetStack = [ ] ; } sourceStack [ depth ] = source ; targetStack [ depth ] = target ; depth ++ ; inferFromProperties ( source , target ) ; inferFromSignatures ( source , target , SignatureKind . Call ) ; inferFromSignatures ( source , target , SignatureKind . Construct ) ; inferFromIndexTypes ( source , target , IndexKind . String , IndexKind . String ) ; inferFromIndexTypes ( source , target , IndexKind . Number , IndexKind . Number ) ; inferFromIndexTypes ( source , target , IndexKind . String , IndexKind . Number ) ; depth -- ; } } } function inferFromProperties ( source , target ) { var properties = getPropertiesOfObjectType ( target ) ; for ( var i = 0 ; i < properties . length ; i ++ ) { var targetProp = properties [ i ] ; var sourceProp = getPropertyOfObjectType ( source , targetProp . name ) ; if ( sourceProp ) { inferFromTypes ( getTypeOfSymbol ( sourceProp ) , getTypeOfSymbol ( targetProp ) ) ; } } } function inferFromSignatures ( source , target , kind ) { var sourceSignatures = getSignaturesOfType ( source , kind ) ; var targetSignatures = getSignaturesOfType ( target , kind ) ; var sourceLen = sourceSignatures . length ; var targetLen = targetSignatures . length ; var len = sourceLen < targetLen ? sourceLen : targetLen ; for ( var i = 0 ; i < len ; i ++ ) { inferFromSignature ( getErasedSignature ( sourceSignatures [ sourceLen - len + i ] ) , getErasedSignature ( targetSignatures [ targetLen - len + i ] ) ) ; } } function inferFromSignature ( source , target ) { forEachMatchingParameterType ( source , target , inferFromTypes ) ; inferFromTypes ( getReturnTypeOfSignature ( source ) , getReturnTypeOfSignature ( target ) ) ; } function inferFromIndexTypes ( source , target , sourceKind , targetKind ) { var targetIndexType = getIndexTypeOfType ( target , targetKind ) ; if ( targetIndexType ) { var sourceIndexType = getIndexTypeOfType ( source , sourceKind ) ; if ( sourceIndexType ) { inferFromTypes ( sourceIndexType , targetIndexType ) ; } } } } function getInferenceCandidates ( context , index ) { var inferences = context . inferences [ index ] ; return inferences . primary || inferences . secondary || emptyArray ; } function getInferredType ( context , index ) { var inferredType = context . inferredTypes [ index ] ; if ( ! inferredType ) { var inferences = getInferenceCandidates ( context , index ) ; if ( inferences . length ) { var unionOrSuperType = context . inferUnionTypes ? getUnionType ( inferences ) : getCommonSupertype ( inferences ) ; inferredType = unionOrSuperType ? getWidenedType ( unionOrSuperType ) : inferenceFailureType ; } else { inferredType = emptyObjectType ; } if ( inferredType !== inferenceFailureType ) { var constraint = getConstraintOfTypeParameter ( context . typeParameters [ index ] ) ; inferredType = constraint && ! isTypeAssignableTo ( inferredType , constraint ) ? constraint : inferredType ; } context . inferredTypes [ index ] = inferredType ; } return inferredType ; } function getInferredTypes ( context ) { for ( var i = 0 ; i < context . inferredTypes . length ; i ++ ) { getInferredType ( context , i ) ; } return context . inferredTypes ; } function hasAncestor ( node , kind ) { return getAncestor ( node , kind ) !== undefined ; } function getResolvedSymbol ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedSymbol ) { links . resolvedSymbol = ( getFullWidth ( node ) > 0 && resolveName ( node , node . text , SymbolFlags . Value | SymbolFlags . ExportValue , Diagnostics . Cannot_find_name_0 , node ) ) || unknownSymbol ; } return links . resolvedSymbol ; } function isInTypeQuery ( node ) { while ( node ) { switch ( node . kind ) { case SyntaxKind . TypeQuery : return true ; case SyntaxKind . Identifier : case SyntaxKind . QualifiedName : node = node . parent ; continue ; default : return false ; } } Debug . fail ( "should not get here" ) ; } function subtractPrimitiveTypes ( type , subtractMask ) { if ( type . flags & TypeFlags . Union ) { var types = ( < UnionType > type ) . types ; if ( forEach ( types , t => t . flags & subtractMask ) ) { return getUnionType ( filter ( types , t => ! ( t . flags & subtractMask ) ) ) ; } } return type ; } function isVariableAssignedWithin ( symbol , node ) { var links = getNodeLinks ( node ) ; if ( links . assignmentChecks ) { var cachedResult = links . assignmentChecks [ symbol . id ] ; if ( cachedResult !== undefined ) { return cachedResult ; } } else { links . assignmentChecks = { } ; } return links . assignmentChecks [ symbol . id ] = isAssignedIn ( node ) ; function isAssignedInBinaryExpression ( node ) { if ( node . operator >= SyntaxKind . FirstAssignment && node . operator <= SyntaxKind . LastAssignment ) { var n = node . left ; while ( n . kind === SyntaxKind . ParenthesizedExpression ) { n = ( < ParenthesizedExpression > n ) . expression ; } if ( n . kind === SyntaxKind . Identifier && getResolvedSymbol ( < Identifier > n ) === symbol ) { return true ; } } return forEachChild ( node , isAssignedIn ) ; } function isAssignedInVariableDeclaration ( node ) { if ( getSymbolOfNode ( node ) === symbol && node . initializer ) { return true ; } return forEachChild ( node , isAssignedIn ) ; } function isAssignedIn ( node ) { switch ( node . kind ) { case SyntaxKind . BinaryExpression : return isAssignedInBinaryExpression ( < BinaryExpression > node ) ; case SyntaxKind . VariableDeclaration : return isAssignedInVariableDeclaration ( < VariableDeclaration > node ) ; case SyntaxKind . ArrayLiteralExpression : case SyntaxKind . ObjectLiteralExpression : case SyntaxKind . PropertyAccessExpression : case SyntaxKind . ElementAccessExpression : case SyntaxKind . CallExpression : case SyntaxKind . NewExpression : case SyntaxKind . TypeAssertionExpression : case SyntaxKind . ParenthesizedExpression : case SyntaxKind . PrefixUnaryExpression : case SyntaxKind . DeleteExpression : case SyntaxKind . TypeOfExpression : case SyntaxKind . VoidExpression : case SyntaxKind . PostfixUnaryExpression : case SyntaxKind . ConditionalExpression : case SyntaxKind . Block : case SyntaxKind . VariableStatement : case SyntaxKind . ExpressionStatement : case SyntaxKind . IfStatement : case SyntaxKind . DoStatement : case SyntaxKind . WhileStatement : case SyntaxKind . ForStatement : case SyntaxKind . ForInStatement : case SyntaxKind . ReturnStatement : case SyntaxKind . WithStatement : case SyntaxKind . SwitchStatement : case SyntaxKind . CaseClause : case SyntaxKind . DefaultClause : case SyntaxKind . LabeledStatement : case SyntaxKind . ThrowStatement : case SyntaxKind . TryStatement : case SyntaxKind . TryBlock : case SyntaxKind . CatchClause : case SyntaxKind . FinallyBlock : return forEachChild ( node , isAssignedIn ) ; } return false ; } } function resolveLocation ( node ) { var containerNodes = [ ] ; for ( var parent = node . parent ; parent ; parent = parent . parent ) { if ( ( isExpression ( parent ) || isObjectLiteralMethod ( node ) ) && isContextSensitive ( < Expression > parent ) ) { containerNodes . unshift ( parent ) ; } } ts . forEach ( containerNodes , node => { getTypeOfNode ( node ) ; } ) ; } function getSymbolAtLocation ( node ) { resolveLocation ( node ) ; return getSymbolInfo ( node ) ; } function getTypeAtLocation ( node ) { resolveLocation ( node ) ; return getTypeOfNode ( node ) ; } function getTypeOfSymbolAtLocation ( symbol , node ) { resolveLocation ( node ) ; return getNarrowedTypeOfSymbol ( symbol , node ) ; } function getNarrowedTypeOfSymbol ( symbol , node ) { var type = getTypeOfSymbol ( symbol ) ; if ( node && symbol . flags & SymbolFlags . Variable && type . flags & ( TypeFlags . ObjectType | TypeFlags . Union | TypeFlags . TypeParameter ) ) { loop : while ( node . parent ) { var child = node ; node = node . parent ; var narrowedType = type ; switch ( node . kind ) { case SyntaxKind . IfStatement : if ( child !== ( < IfStatement > node ) . expression ) { narrowedType = narrowType ( type , ( < IfStatement > node ) . expression , child === ( < IfStatement > node ) . thenStatement ) ; } break ; case SyntaxKind . ConditionalExpression : if ( child !== ( < ConditionalExpression > node ) . condition ) { narrowedType = narrowType ( type , ( < ConditionalExpression > node ) . condition , child === ( < ConditionalExpression > node ) . whenTrue ) ; } break ; case SyntaxKind . BinaryExpression : if ( child === ( < BinaryExpression > node ) . right ) { if ( ( < BinaryExpression > node ) . operator === SyntaxKind . AmpersandAmpersandToken ) { narrowedType = narrowType ( type , ( < BinaryExpression > node ) . left , true ) ; } else if ( ( < BinaryExpression > node ) . operator === SyntaxKind . BarBarToken ) { narrowedType = narrowType ( type , ( < BinaryExpression > node ) . left , false ) ; } } break ; case SyntaxKind . SourceFile : case SyntaxKind . ModuleDeclaration : case SyntaxKind . FunctionDeclaration : case SyntaxKind . Method : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : case SyntaxKind . Constructor : break loop ; } if ( narrowedType !== type && isTypeSubtypeOf ( narrowedType , type ) ) { if ( isVariableAssignedWithin ( symbol , node ) ) { break ; } type = narrowedType ; } } } return type ; function narrowTypeByEquality ( type , expr , assumeTrue ) { if ( expr . left . kind !== SyntaxKind . TypeOfExpression || expr . right . kind !== SyntaxKind . StringLiteral ) { return type ; } var left = < TypeOfExpression > expr . left ; var right = < LiteralExpression > expr . right ; if ( left . expression . kind !== SyntaxKind . Identifier || getResolvedSymbol ( < Identifier > left . expression ) !== symbol ) { return type ; } var t = right . text ; var checkType = t === "string" ? stringType : t === "number" ? numberType : t === "boolean" ? booleanType : emptyObjectType ; if ( expr . operator === SyntaxKind . ExclamationEqualsEqualsToken ) { assumeTrue = ! assumeTrue ; } if ( assumeTrue ) { return checkType === emptyObjectType ? subtractPrimitiveTypes ( type , TypeFlags . String | TypeFlags . Number | TypeFlags . Boolean ) : checkType ; } else { return checkType === emptyObjectType ? type : subtractPrimitiveTypes ( type , checkType . flags ) ; } } function narrowTypeByAnd ( type , expr , assumeTrue ) { if ( assumeTrue ) { return narrowType ( narrowType ( type , expr . left , true ) , expr . right , true ) ; } else { return getUnionType ( [ narrowType ( type , expr . left , false ) , narrowType ( narrowType ( type , expr . left , true ) , expr . right , false ) ] ) ; } } function narrowTypeByOr ( type , expr , assumeTrue ) { if ( assumeTrue ) { return getUnionType ( [ narrowType ( type , expr . left , true ) , narrowType ( narrowType ( type , expr . left , false ) , expr . right , true ) ] ) ; } else { return narrowType ( narrowType ( type , expr . left , false ) , expr . right , false ) ; } } function narrowTypeByInstanceof ( type , expr , assumeTrue ) { if ( ! assumeTrue || expr . left . kind !== SyntaxKind . Identifier || getResolvedSymbol ( < Identifier > expr . left ) !== symbol ) { return type ; } var rightType = checkExpression ( expr . right ) ; if ( ! isTypeSubtypeOf ( rightType , globalFunctionType ) ) { return type ; } var prototypeProperty = getPropertyOfType ( rightType , "prototype" ) ; if ( ! prototypeProperty ) { return type ; } var prototypeType = getTypeOfSymbol ( prototypeProperty ) ; return isTypeSubtypeOf ( prototypeType , type ) ? prototypeType : type ; } function narrowType ( type , expr , assumeTrue ) { switch ( expr . kind ) { case SyntaxKind . ParenthesizedExpression : return narrowType ( type , ( < ParenthesizedExpression > expr ) . expression , assumeTrue ) ; case SyntaxKind . BinaryExpression : var operator = ( < BinaryExpression > expr ) . operator ; if ( operator === SyntaxKind . EqualsEqualsEqualsToken || operator === SyntaxKind . ExclamationEqualsEqualsToken ) { return narrowTypeByEquality ( type , < BinaryExpression > expr , assumeTrue ) ; } else if ( operator === SyntaxKind . AmpersandAmpersandToken ) { return narrowTypeByAnd ( type , < BinaryExpression > expr , assumeTrue ) ; } else if ( operator === SyntaxKind . BarBarToken ) { return narrowTypeByOr ( type , < BinaryExpression > expr , assumeTrue ) ; } else if ( operator === SyntaxKind . InstanceOfKeyword ) { return narrowTypeByInstanceof ( type , < BinaryExpression > expr , assumeTrue ) ; } break ; case SyntaxKind . PrefixUnaryExpression : if ( ( < PrefixUnaryExpression > expr ) . operator === SyntaxKind . ExclamationToken ) { return narrowType ( type , ( < PrefixUnaryExpression > expr ) . operand , ! assumeTrue ) ; } break ; } return type ; } } function checkIdentifier ( node ) { var symbol = getResolvedSymbol ( node ) ; if ( symbol . flags & SymbolFlags . Import ) { getSymbolLinks ( symbol ) . referenced = getSymbolLinks ( symbol ) . referenced || ( ! isInTypeQuery ( node ) && ! isConstEnumOrConstEnumOnlyModule ( resolveImport ( symbol ) ) ) ; } checkCollisionWithCapturedSuperVariable ( node , node ) ; checkCollisionWithCapturedThisVariable ( node , node ) ; checkCollisionWithIndexVariableInGeneratedCode ( node , node ) ; return getNarrowedTypeOfSymbol ( getExportSymbolOfValueSymbolIfExported ( symbol ) , node ) ; } function captureLexicalThis ( node , container ) { var classNode = container . parent && container . parent . kind === SyntaxKind . ClassDeclaration ? container . parent : undefined ; getNodeLinks ( node ) . flags |= NodeCheckFlags . LexicalThis ; if ( container . kind === SyntaxKind . Property || container . kind === SyntaxKind . Constructor ) { getNodeLinks ( classNode ) . flags |= NodeCheckFlags . CaptureThis ; } else { getNodeLinks ( container ) . flags |= NodeCheckFlags . CaptureThis ; } } function checkThisExpression ( node ) { var container = getThisContainer ( node , true ) ; var needToCaptureLexicalThis = false ; if ( container . kind === SyntaxKind . ArrowFunction ) { container = getThisContainer ( container , false ) ; needToCaptureLexicalThis = true ; } switch ( container . kind ) { case SyntaxKind . ModuleDeclaration : error ( node , Diagnostics . this_cannot_be_referenced_in_a_module_body ) ; break ; case SyntaxKind . EnumDeclaration : error ( node , Diagnostics . this_cannot_be_referenced_in_current_location ) ; break ; case SyntaxKind . Constructor : if ( isInConstructorArgumentInitializer ( node , container ) ) { error ( node , Diagnostics . this_cannot_be_referenced_in_constructor_arguments ) ; } break ; case SyntaxKind . Property : if ( container . flags & NodeFlags . Static ) { error ( node , Diagnostics . this_cannot_be_referenced_in_a_static_property_initializer ) ; } break ; } if ( needToCaptureLexicalThis ) { captureLexicalThis ( node , container ) ; } var classNode = container . parent && container . parent . kind === SyntaxKind . ClassDeclaration ? container . parent : undefined ; if ( classNode ) { var symbol = getSymbolOfNode ( classNode ) ; return container . flags & NodeFlags . Static ? getTypeOfSymbol ( symbol ) : getDeclaredTypeOfSymbol ( symbol ) ; } return anyType ; } function getSuperContainer ( node ) { while ( true ) { node = node . parent ; if ( ! node ) return node ; switch ( node . kind ) { case SyntaxKind . FunctionDeclaration : case SyntaxKind . FunctionExpression : case SyntaxKind . ArrowFunction : case SyntaxKind . Property : case SyntaxKind . Method : case SyntaxKind . Constructor : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : return node ; } } } function isInConstructorArgumentInitializer ( node , constructorDecl ) { for ( var n = node ; n && n !== constructorDecl ; n = n . parent ) { if ( n . kind === SyntaxKind . Parameter ) { return true ; } } return false ; } function checkSuperExpression ( node ) { var isCallExpression = node . parent . kind === SyntaxKind . CallExpression && ( < CallExpression > node . parent ) . expression === node ; var enclosingClass = < ClassDeclaration > getAncestor ( node , SyntaxKind . ClassDeclaration ) ; var baseClass ; if ( enclosingClass && getClassBaseTypeNode ( enclosingClass ) ) { var classType = < InterfaceType > getDeclaredTypeOfSymbol ( getSymbolOfNode ( enclosingClass ) ) ; baseClass = classType . baseTypes . length && classType . baseTypes [ 0 ] ; } if ( ! baseClass ) { error ( node , Diagnostics . super_can_only_be_referenced_in_a_derived_class ) ; return unknownType ; } var container = getSuperContainer ( node ) ; if ( container ) { var canUseSuperExpression = false ; if ( isCallExpression ) { canUseSuperExpression = container . kind === SyntaxKind . Constructor ; } else { var needToCaptureLexicalThis = false ; while ( container && container . kind === SyntaxKind . ArrowFunction ) { container = getSuperContainer ( container ) ; needToCaptureLexicalThis = true ; } if ( container && container . parent && container . parent . kind === SyntaxKind . ClassDeclaration ) { if ( container . flags & NodeFlags . Static ) { canUseSuperExpression = container . kind === SyntaxKind . Method || container . kind === SyntaxKind . GetAccessor || container . kind === SyntaxKind . SetAccessor ; } else { canUseSuperExpression = container . kind === SyntaxKind . Method || container . kind === SyntaxKind . GetAccessor || container . kind === SyntaxKind . SetAccessor || container . kind === SyntaxKind . Property || container . kind === SyntaxKind . Constructor ; } } } if ( canUseSuperExpression ) { var returnType ; if ( ( container . flags & NodeFlags . Static ) || isCallExpression ) { getNodeLinks ( node ) . flags |= NodeCheckFlags . SuperStatic ; returnType = getTypeOfSymbol ( baseClass . symbol ) ; } else { getNodeLinks ( node ) . flags |= NodeCheckFlags . SuperInstance ; returnType = baseClass ; } if ( container . kind === SyntaxKind . Constructor && isInConstructorArgumentInitializer ( node , container ) ) { error ( node , Diagnostics . super_cannot_be_referenced_in_constructor_arguments ) ; returnType = unknownType ; } if ( ! isCallExpression && needToCaptureLexicalThis ) { captureLexicalThis ( node . parent , container ) ; } return returnType ; } } if ( isCallExpression ) { error ( node , Diagnostics . Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors ) ; } else { error ( node , Diagnostics . super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class ) ; } return unknownType ; } function getContextuallyTypedParameterType ( parameter ) { if ( isFunctionExpressionOrArrowFunction ( parameter . parent ) ) { var func = < FunctionExpression > parameter . parent ; if ( isContextSensitive ( func ) ) { var contextualSignature = getContextualSignature ( func ) ; if ( contextualSignature ) { var funcHasRestParameters = hasRestParameters ( func ) ; var len = func . parameters . length - ( funcHasRestParameters ? 1 : 0 ) ; var indexOfParameter = indexOf ( func . parameters , parameter ) ; if ( indexOfParameter < len ) { return getTypeAtPosition ( contextualSignature , indexOfParameter ) ; } if ( indexOfParameter === ( func . parameters . length - 1 ) && funcHasRestParameters && contextualSignature . hasRestParameter && func . parameters . length >= contextualSignature . parameters . length ) { return getTypeOfSymbol ( contextualSignature . parameters [ contextualSignature . parameters . length - 1 ] ) ; } } } } return undefined ; } function getContextualTypeForInitializerExpression ( node ) { var declaration = < VariableOrParameterDeclaration > node . parent ; if ( node === declaration . initializer ) { if ( declaration . type ) { return getTypeFromTypeNode ( declaration . type ) ; } if ( declaration . kind === SyntaxKind . Parameter ) { return getContextuallyTypedParameterType ( < ParameterDeclaration > declaration ) ; } } return undefined ; } function getContextualTypeForReturnExpression ( node ) { var func = getContainingFunction ( node ) ; if ( func ) { if ( func . type || func . kind === SyntaxKind . Constructor || func . kind === SyntaxKind . GetAccessor && getSetAccessorTypeAnnotationNode ( < AccessorDeclaration > getDeclarationOfKind ( func . symbol , SyntaxKind . SetAccessor ) ) ) { return getReturnTypeOfSignature ( getSignatureFromDeclaration ( func ) ) ; } var signature = getContextualSignatureForFunctionLikeDeclaration ( < FunctionExpression > func ) ; if ( signature ) { return getReturnTypeOfSignature ( signature ) ; } } return undefined ; } function getContextualTypeForArgument ( callTarget , arg ) { var args = getEffectiveCallArguments ( callTarget ) ; var argIndex = indexOf ( args , arg ) ; if ( argIndex >= 0 ) { var signature = getResolvedSignature ( callTarget ) ; return getTypeAtPosition ( signature , argIndex ) ; } return undefined ; } function getContextualTypeForSubstitutionExpression ( template , substitutionExpression ) { if ( template . parent . kind === SyntaxKind . TaggedTemplateExpression ) { return getContextualTypeForArgument ( < TaggedTemplateExpression > template . parent , substitutionExpression ) ; } return undefined ; } function getContextualTypeForBinaryOperand ( node ) { var binaryExpression = < BinaryExpression > node . parent ; var operator = binaryExpression . operator ; if ( operator >= SyntaxKind . FirstAssignment && operator <= SyntaxKind . LastAssignment ) { if ( node === binaryExpression . right ) { return checkExpression ( binaryExpression . left ) ; } } else if ( operator === SyntaxKind . BarBarToken ) { var type = getContextualType ( binaryExpression ) ; if ( ! type && node === binaryExpression . right ) { type = checkExpression ( binaryExpression . left ) ; } return type ; } return undefined ; } function applyToContextualType ( type , mapper ) { if ( ! ( type . flags & TypeFlags . Union ) ) { return mapper ( type ) ; } var types = ( < UnionType > type ) . types ; var mappedType ; var mappedTypes ; for ( var i = 0 ; i < types . length ; i ++ ) { var t = mapper ( types [ i ] ) ; if ( t ) { if ( ! mappedType ) { mappedType = t ; } else if ( ! mappedTypes ) { mappedTypes = [ mappedType , t ] ; } else { mappedTypes . push ( t ) ; } } } return mappedTypes ? getUnionType ( mappedTypes ) : mappedType ; } function getTypeOfPropertyOfContextualType ( type , name ) { return applyToContextualType ( type , t => { var prop = getPropertyOfObjectType ( t , name ) ; return prop ? getTypeOfSymbol ( prop ) : undefined ; } ) ; } function getIndexTypeOfContextualType ( type , kind ) { return applyToContextualType ( type , t => getIndexTypeOfObjectOrUnionType ( t , kind ) ) ; } function contextualTypeIsTupleType ( type ) { return ! ! ( type . flags & TypeFlags . Union ? forEach ( ( < UnionType > type ) . types , t => getPropertyOfObjectType ( t , "0" ) ) : getPropertyOfObjectType ( type , "0" ) ) ; } function contextualTypeHasIndexSignature ( type , kind ) { return ! ! ( type . flags & TypeFlags . Union ? forEach ( ( < UnionType > type ) . types , t => getIndexTypeOfObjectOrUnionType ( t , kind ) ) : getIndexTypeOfObjectOrUnionType ( type , kind ) ) ; } function getContextualTypeForObjectLiteralMethod ( node ) { Debug . assert ( isObjectLiteralMethod ( node ) ) ; if ( isInsideWithStatementBody ( node ) ) { return undefined ; } return getContextualTypeForObjectLiteralElement ( node ) ; } function getContextualTypeForObjectLiteralElement ( element ) { var objectLiteral = < ObjectLiteralExpression > element . parent ; var type = getContextualType ( objectLiteral ) ; var name = ( < Identifier > element . name ) . text ; if ( type && name ) { return getTypeOfPropertyOfContextualType ( type , name ) || isNumericName ( name ) && getIndexTypeOfContextualType ( type , IndexKind . Number ) || getIndexTypeOfContextualType ( type , IndexKind . String ) ; } return undefined ; } function getContextualTypeForElementExpression ( node ) { var arrayLiteral = < ArrayLiteralExpression > node . parent ; var type = getContextualType ( arrayLiteral ) ; if ( type ) { var index = indexOf ( arrayLiteral . elements , node ) ; return getTypeOfPropertyOfContextualType ( type , "" + index ) || getIndexTypeOfContextualType ( type , IndexKind . Number ) ; } return undefined ; } function getContextualTypeForConditionalOperand ( node ) { var conditional = < ConditionalExpression > node . parent ; return node === conditional . whenTrue || node === conditional . whenFalse ? getContextualType ( conditional ) : undefined ; } function getContextualType ( node ) { if ( isInsideWithStatementBody ( node ) ) { return undefined ; } if ( node . contextualType ) { return node . contextualType ; } var parent = node . parent ; switch ( parent . kind ) { case SyntaxKind . VariableDeclaration : case SyntaxKind . Parameter : case SyntaxKind . Property : return getContextualTypeForInitializerExpression ( node ) ; case SyntaxKind . ArrowFunction : case SyntaxKind . ReturnStatement : return getContextualTypeForReturnExpression ( node ) ; case SyntaxKind . CallExpression : case SyntaxKind . NewExpression : return getContextualTypeForArgument ( < CallExpression > parent , node ) ; case SyntaxKind . TypeAssertionExpression : return getTypeFromTypeNode ( ( < TypeAssertion > parent ) . type ) ; case SyntaxKind . BinaryExpression : return getContextualTypeForBinaryOperand ( node ) ; case SyntaxKind . PropertyAssignment : return getContextualTypeForObjectLiteralElement ( < ObjectLiteralElement > parent ) ; case SyntaxKind . ArrayLiteralExpression : return getContextualTypeForElementExpression ( node ) ; case SyntaxKind . ConditionalExpression : return getContextualTypeForConditionalOperand ( node ) ; case SyntaxKind . TemplateSpan : Debug . assert ( parent . parent . kind === SyntaxKind . TemplateExpression ) ; return getContextualTypeForSubstitutionExpression ( < TemplateExpression > parent . parent , node ) ; } return undefined ; } function getNonGenericSignature ( type ) { var signatures = getSignaturesOfObjectOrUnionType ( type , SignatureKind . Call ) ; if ( signatures . length === 1 ) { var signature = signatures [ 0 ] ; if ( ! signature . typeParameters ) { return signature ; } } } function isFunctionExpressionOrArrowFunction ( node ) { return node . kind === SyntaxKind . FunctionExpression || node . kind === SyntaxKind . ArrowFunction ; } function getContextualSignatureForFunctionLikeDeclaration ( node ) { return isFunctionExpressionOrArrowFunction ( node ) ? getContextualSignature ( < FunctionExpression > node ) : undefined ; } function getContextualSignature ( node ) { Debug . assert ( node . kind !== SyntaxKind . Method || isObjectLiteralMethod ( node ) ) ; var type = isObjectLiteralMethod ( node ) ? getContextualTypeForObjectLiteralMethod ( < MethodDeclaration > node ) : getContextualType ( < FunctionExpression > node ) ; if ( ! type ) { return undefined ; } if ( ! ( type . flags & TypeFlags . Union ) ) { return getNonGenericSignature ( type ) ; } var signatureList ; var types = ( < UnionType > type ) . types ; for ( var i = 0 ; i < types . length ; i ++ ) { if ( signatureList && getSignaturesOfObjectOrUnionType ( types [ i ] , SignatureKind . Call ) . length > 1 ) { return undefined ; } var signature = getNonGenericSignature ( types [ i ] ) ; if ( signature ) { if ( ! signatureList ) { signatureList = [ signature ] ; } else if ( ! compareSignatures ( signatureList [ 0 ] , signature , false , compareTypes ) ) { return undefined ; } else { signatureList . push ( signature ) ; } } } var result ; if ( signatureList ) { result = cloneSignature ( signatureList [ 0 ] ) ; result . resolvedReturnType = undefined ; result . unionSignatures = signatureList ; } return result ; } function isInferentialContext ( mapper ) { return mapper && mapper !== identityMapper ; } function checkArrayLiteral ( node , contextualMapper ? ) { var elements = node . elements ; if ( ! elements . length ) { return createArrayType ( undefinedType ) ; } var elementTypes = map ( elements , e => checkExpression ( e , contextualMapper ) ) ; var contextualType = getContextualType ( node ) ; if ( contextualType && contextualTypeIsTupleType ( contextualType ) ) { return createTupleType ( elementTypes ) ; } return createArrayType ( getUnionType ( elementTypes ) ) ; } function isNumericName ( name ) { return ( + name ) . toString ( ) === name ; } function checkObjectLiteral ( node , contextualMapper ? ) { var members = node . symbol . members ; var properties = { } ; var contextualType = getContextualType ( node ) ; for ( var id in members ) { if ( hasProperty ( members , id ) ) { var member = members [ id ] ; if ( member . flags & SymbolFlags . Property || isObjectLiteralMethod ( member . declarations [ 0 ] ) ) { var memberDecl = < ObjectLiteralElement > member . declarations [ 0 ] ; var type ; if ( memberDecl . kind === SyntaxKind . PropertyAssignment ) { type = checkExpression ( ( < PropertyAssignment > memberDecl ) . initializer , contextualMapper ) ; } else if ( memberDecl . kind === SyntaxKind . Method ) { type = checkObjectLiteralMethod ( < MethodDeclaration > memberDecl , contextualMapper ) ; } else { Debug . assert ( memberDecl . kind === SyntaxKind . ShorthandPropertyAssignment ) ; type = memberDecl . name . kind === SyntaxKind . ComputedPropertyName ? unknownType : checkExpression ( < Expression > < Node > memberDecl . name , contextualMapper ) ; } var prop = < TransientSymbol > createSymbol ( SymbolFlags . Property | SymbolFlags . Transient | member . flags , member . name ) ; prop . declarations = member . declarations ; prop . parent = member . parent ; if ( member . valueDeclaration ) { prop . valueDeclaration = member . valueDeclaration ; } prop . type = type ; prop . target = member ; member = prop ; } else { var getAccessor = < AccessorDeclaration > getDeclarationOfKind ( member , SyntaxKind . GetAccessor ) ; if ( getAccessor ) { checkAccessorDeclaration ( getAccessor ) ; } var setAccessor = < AccessorDeclaration > getDeclarationOfKind ( member , SyntaxKind . SetAccessor ) ; if ( setAccessor ) { checkAccessorDeclaration ( setAccessor ) ; } } properties [ member . name ] = member ; } } var stringIndexType = getIndexType ( IndexKind . String ) ; var numberIndexType = getIndexType ( IndexKind . Number ) ; return createAnonymousType ( node . symbol , properties , emptyArray , emptyArray , stringIndexType , numberIndexType ) ; function getIndexType ( kind ) { if ( contextualType && contextualTypeHasIndexSignature ( contextualType , kind ) ) { var propTypes = [ ] ; for ( var id in properties ) { if ( hasProperty ( properties , id ) ) { if ( kind === IndexKind . String || isNumericName ( id ) ) { var type = getTypeOfSymbol ( properties [ id ] ) ; if ( ! contains ( propTypes , type ) ) { propTypes . push ( type ) ; } } } } return propTypes . length ? getUnionType ( propTypes ) : undefinedType ; } return undefined ; } } function getDeclarationKindFromSymbol ( s ) { return s . valueDeclaration ? s . valueDeclaration . kind : SyntaxKind . Property ; } function getDeclarationFlagsFromSymbol ( s ) { return s . valueDeclaration ? s . valueDeclaration . flags : s . flags & SymbolFlags . Prototype ? NodeFlags . Public | NodeFlags . Static : 0 ; } function checkClassPropertyAccess ( node , left , type , prop ) { var flags = getDeclarationFlagsFromSymbol ( prop ) ; if ( ! ( flags & ( NodeFlags . Private | NodeFlags . Protected ) ) ) { return ; } var enclosingClassDeclaration = getAncestor ( node , SyntaxKind . ClassDeclaration ) ; var enclosingClass = enclosingClassDeclaration ? < InterfaceType > getDeclaredTypeOfSymbol ( getSymbolOfNode ( enclosingClassDeclaration ) ) : undefined ; var declaringClass = < InterfaceType > getDeclaredTypeOfSymbol ( prop . parent ) ; if ( flags & NodeFlags . Private ) { if ( declaringClass !== enclosingClass ) { error ( node , Diagnostics . Property_0_is_private_and_only_accessible_within_class_1 , symbolToString ( prop ) , typeToString ( declaringClass ) ) ; } return ; } if ( left . kind === SyntaxKind . SuperKeyword ) { return ; } if ( ! enclosingClass || ! hasBaseType ( enclosingClass , declaringClass ) ) { error ( node , Diagnostics . Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses , symbolToString ( prop ) , typeToString ( declaringClass ) ) ; return ; } if ( flags & NodeFlags . Static ) { return ; } if ( ! ( getTargetType ( type ) . flags & ( TypeFlags . Class | TypeFlags . Interface ) && hasBaseType ( < InterfaceType > type , enclosingClass ) ) ) { error ( node , Diagnostics . Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1 , symbolToString ( prop ) , typeToString ( enclosingClass ) ) ; } } function checkPropertyAccessExpression ( node ) { return checkPropertyAccessExpressionOrQualifiedName ( node , node . expression , node . name ) ; } function checkQualifiedName ( node ) { return checkPropertyAccessExpressionOrQualifiedName ( node , node . left , node . right ) ; } function checkPropertyAccessExpressionOrQualifiedName ( node , left , right ) { var type = checkExpressionOrQualifiedName ( left ) ; if ( type === unknownType ) return type ; if ( type !== anyType ) { var apparentType = getApparentType ( getWidenedType ( type ) ) ; if ( apparentType === unknownType ) { return unknownType ; } var prop = getPropertyOfType ( apparentType , right . text ) ; if ( ! prop ) { if ( right . text ) { error ( right , Diagnostics . Property_0_does_not_exist_on_type_1 , declarationNameToString ( right ) , typeToString ( type ) ) ; } return unknownType ; } getNodeLinks ( node ) . resolvedSymbol = prop ; if ( prop . parent && prop . parent . flags & SymbolFlags . Class ) { if ( left . kind === SyntaxKind . SuperKeyword && getDeclarationKindFromSymbol ( prop ) !== SyntaxKind . Method ) { error ( right , Diagnostics . Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword ) ; } else { checkClassPropertyAccess ( node , left , type , prop ) ; } } return getTypeOfSymbol ( prop ) ; } return anyType ; } function isValidPropertyAccess ( node , propertyName ) { var left = node . kind === SyntaxKind . PropertyAccessExpression ? ( < PropertyAccessExpression > node ) . expression : ( < QualifiedName > node ) . left ; var type = checkExpressionOrQualifiedName ( left ) ; if ( type !== unknownType && type !== anyType ) { var prop = getPropertyOfType ( getWidenedType ( type ) , propertyName ) ; if ( prop && prop . parent && prop . parent . flags & SymbolFlags . Class ) { if ( left . kind === SyntaxKind . SuperKeyword && getDeclarationKindFromSymbol ( prop ) !== SyntaxKind . Method ) { return false ; } else { var diagnosticsCount = diagnostics . length ; checkClassPropertyAccess ( node , left , type , prop ) ; return diagnostics . length === diagnosticsCount ; } } } return true ; } function checkIndexedAccess ( node ) { var objectType = getApparentType ( checkExpression ( node . expression ) ) ; var indexType = node . argumentExpression ? checkExpression ( node . argumentExpression ) : unknownType ; if ( objectType === unknownType ) { return unknownType ; } if ( isConstEnumObjectType ( objectType ) && node . argumentExpression && node . argumentExpression . kind !== SyntaxKind . StringLiteral ) { error ( node . argumentExpression , Diagnostics . Index_expression_arguments_in_const_enums_must_be_of_type_string ) ; } if ( node . argumentExpression ) { if ( node . argumentExpression . kind === SyntaxKind . StringLiteral || node . argumentExpression . kind === SyntaxKind . NumericLiteral ) { var name = ( < LiteralExpression > node . argumentExpression ) . text ; var prop = getPropertyOfType ( objectType , name ) ; if ( prop ) { getNodeLinks ( node ) . resolvedSymbol = prop ; return getTypeOfSymbol ( prop ) ; } } } if ( indexType . flags & ( TypeFlags . Any | TypeFlags . StringLike | TypeFlags . NumberLike ) ) { if ( indexType . flags & ( TypeFlags . Any | TypeFlags . NumberLike ) ) { var numberIndexType = getIndexTypeOfType ( objectType , IndexKind . Number ) ; if ( numberIndexType ) { return numberIndexType ; } } var stringIndexType = getIndexTypeOfType ( objectType , IndexKind . String ) ; if ( stringIndexType ) { return stringIndexType ; } if ( compilerOptions . noImplicitAny && ! compilerOptions . suppressImplicitAnyIndexErrors && objectType !== anyType ) { error ( node , Diagnostics . Index_signature_of_object_type_implicitly_has_an_any_type ) ; } return anyType ; } error ( node , Diagnostics . An_index_expression_argument_must_be_of_type_string_number_or_any ) ; return unknownType ; } function resolveUntypedCall ( node ) { if ( node . kind === SyntaxKind . TaggedTemplateExpression ) { checkExpression ( ( < TaggedTemplateExpression > node ) . template ) ; } else { forEach ( ( < CallExpression > node ) . arguments , argument => { checkExpression ( argument ) ; } ) ; } return anySignature ; } function resolveErrorCall ( node ) { resolveUntypedCall ( node ) ; return unknownSignature ; } function hasCorrectArity ( node , args , signature ) { var adjustedArgCount ; var typeArguments ; var callIsIncomplete ; if ( node . kind === SyntaxKind . TaggedTemplateExpression ) { var tagExpression = < TaggedTemplateExpression > node ; adjustedArgCount = args . length ; typeArguments = undefined ; if ( tagExpression . template . kind === SyntaxKind . TemplateExpression ) { var templateExpression = < TemplateExpression > tagExpression . template ; var lastSpan = lastOrUndefined ( templateExpression . templateSpans ) ; Debug . assert ( lastSpan !== undefined ) ; callIsIncomplete = getFullWidth ( lastSpan . literal ) === 0 || ! ! lastSpan . literal . isUnterminated ; } else { var templateLiteral = < LiteralExpression > tagExpression . template ; Debug . assert ( templateLiteral . kind === SyntaxKind . NoSubstitutionTemplateLiteral ) ; callIsIncomplete = ! ! templateLiteral . isUnterminated ; } } else { var callExpression = < CallExpression > node ; if ( ! callExpression . arguments ) { Debug . assert ( callExpression . kind === SyntaxKind . NewExpression ) ; return signature . minArgumentCount === 0 ; } adjustedArgCount = callExpression . arguments . hasTrailingComma ? args . length + 1 : args . length ; callIsIncomplete = ( < CallExpression > callExpression ) . arguments . end === callExpression . end ; typeArguments = callExpression . typeArguments ; } Debug . assert ( adjustedArgCount !== undefined , "'adjustedArgCount' undefined" ) ; Debug . assert ( callIsIncomplete !== undefined , "'callIsIncomplete' undefined" ) ; return checkArity ( adjustedArgCount , typeArguments , callIsIncomplete , signature ) ; param adjustedArgCount param typeArguments param callIsIncomplete param signature function checkArity ( adjustedArgCount , typeArguments , callIsIncomplete , signature ) { if ( ! signature . hasRestParameter && adjustedArgCount > signature . parameters . length ) { return false ; } var hasRightNumberOfTypeArgs = ! typeArguments || ( signature . typeParameters && typeArguments . length === signature . typeParameters . length ) ; if ( ! hasRightNumberOfTypeArgs ) { return false ; } var hasEnoughArguments = adjustedArgCount >= signature . minArgumentCount ; return callIsIncomplete || hasEnoughArguments ; } } function getSingleCallSignature ( type ) { if ( type . flags & TypeFlags . ObjectType ) { var resolved = resolveObjectOrUnionTypeMembers ( < ObjectType > type ) ; if ( resolved . callSignatures . length === 1 && resolved . constructSignatures . length === 0 && resolved . properties . length === 0 && ! resolved . stringIndexType && ! resolved . numberIndexType ) { return resolved . callSignatures [ 0 ] ; } } return undefined ; } function instantiateSignatureInContextOf ( signature , contextualSignature , contextualMapper ) { var context = createInferenceContext ( signature . typeParameters , true ) ; forEachMatchingParameterType ( contextualSignature , signature , ( source , target ) => { inferTypes ( context , instantiateType ( source , contextualMapper ) , target ) ; } ) ; return getSignatureInstantiation ( signature , getInferredTypes ( context ) ) ; } function inferTypeArguments ( signature , args , excludeArgument ? ) { var typeParameters = signature . typeParameters ; var context = createInferenceContext ( typeParameters , false ) ; var mapper = createInferenceMapper ( context ) ; for ( var i = 0 ; i < args . length ; i ++ ) { if ( args [ i ] . kind === SyntaxKind . OmittedExpression ) { continue ; } if ( ! excludeArgument || excludeArgument [ i ] === undefined ) { var parameterType = getTypeAtPosition ( signature , i ) ; if ( i === 0 && args [ i ] . parent . kind === SyntaxKind . TaggedTemplateExpression ) { inferTypes ( context , globalTemplateStringsArrayType , parameterType ) ; continue ; } inferTypes ( context , checkExpressionWithContextualType ( args [ i ] , parameterType , mapper ) , parameterType ) ; } } if ( excludeArgument ) { for ( var i = 0 ; i < args . length ; i ++ ) { if ( args [ i ] . kind === SyntaxKind . OmittedExpression ) { continue ; } if ( excludeArgument [ i ] === false ) { var parameterType = getTypeAtPosition ( signature , i ) ; inferTypes ( context , checkExpressionWithContextualType ( args [ i ] , parameterType , mapper ) , parameterType ) ; } } } var inferredTypes = getInferredTypes ( context ) ; context . failedTypeParameterIndex = indexOf ( inferredTypes , inferenceFailureType ) ; for ( var i = 0 ; i < inferredTypes . length ; i ++ ) { if ( inferredTypes [ i ] === inferenceFailureType ) { inferredTypes [ i ] = unknownType ; } } return context ; } function checkTypeArguments ( signature , typeArguments , typeArgumentResultTypes , reportErrors ) { var typeParameters = signature . typeParameters ; var typeArgumentsAreAssignable = true ; for ( var i = 0 ; i < typeParameters . length ; i ++ ) { var typeArgNode = typeArguments [ i ] ; var typeArgument = getTypeFromTypeNode ( typeArgNode ) ; typeArgumentResultTypes [ i ] = typeArgument ; if ( typeArgumentsAreAssignable ) { var constraint = getConstraintOfTypeParameter ( typeParameters [ i ] ) ; if ( constraint ) { typeArgumentsAreAssignable = checkTypeAssignableTo ( typeArgument , constraint , reportErrors ? typeArgNode : undefined , Diagnostics . Type_0_does_not_satisfy_the_constraint_1 ) ; } } } return typeArgumentsAreAssignable ; } function checkApplicableSignature ( node , args , signature , relation , excludeArgument , reportErrors ) { for ( var i = 0 ; i < args . length ; i ++ ) { var arg = args [ i ] ; var argType ; if ( arg . kind === SyntaxKind . OmittedExpression ) { continue ; } var paramType = getTypeAtPosition ( signature , i ) ; if ( i === 0 && node . kind === SyntaxKind . TaggedTemplateExpression ) { argType = globalTemplateStringsArrayType ; } else { argType = arg . kind === SyntaxKind . StringLiteral && ! reportErrors ? getStringLiteralType ( < LiteralExpression > arg ) : checkExpressionWithContextualType ( < LiteralExpression > arg , paramType , excludeArgument && excludeArgument [ i ] ? identityMapper : undefined ) ; } var isValidArgument = checkTypeRelatedTo ( argType , paramType , relation , reportErrors ? arg : undefined , Diagnostics . Argument_of_type_0_is_not_assignable_to_parameter_of_type_1 ) ; if ( ! isValidArgument ) { return false ; } } return true ; } /**
         * Returns the effective arguments for an expression that works like a function invocation.
         *
         * If 'node' is a CallExpression or a NewExpression, then its argument list is returned.
         * If 'node' is a TaggedTemplateExpression, a new argument list is constructed from the substitution
         *    expressions, where the first element of the list is the template for error reporting purposes.
         */ function getEffectiveCallArguments ( node ) { var args ; if ( node . kind === SyntaxKind . TaggedTemplateExpression ) { var template = ( < TaggedTemplateExpression > node ) . template ; args = [ template ] ; if ( template . kind === SyntaxKind . TemplateExpression ) { forEach ( ( < TemplateExpression > template ) . templateSpans , span => { args . push ( span . expression ) ; } ) ; } } else { args = ( < CallExpression > node ) . arguments || emptyArray ; } return args ; } function resolveCall ( node , signatures , candidatesOutArray ) { var isTaggedTemplate = node . kind === SyntaxKind . TaggedTemplateExpression ; var typeArguments = isTaggedTemplate ? undefined : ( < CallExpression > node ) . typeArguments ; forEach ( typeArguments , checkSourceElement ) ; var candidates = candidatesOutArray || [ ] ; collectCandidates ( ) ; if ( ! candidates . length ) { error ( node , Diagnostics . Supplied_parameters_do_not_match_any_signature_of_call_target ) ; return resolveErrorCall ( node ) ; } var args = getEffectiveCallArguments ( node ) ; var excludeArgument ; for ( var i = isTaggedTemplate ? 1 : 0 ; i < args . length ; i ++ ) { if ( isContextSensitive ( args [ i ] ) ) { if ( ! excludeArgument ) { excludeArgument = new Array ( args . length ) ; } excludeArgument [ i ] = true ; } } var candidateForArgumentError ; var candidateForTypeArgumentError ; var resultOfFailedInference ; var result ; if ( candidates . length > 1 ) { result = chooseOverload ( candidates , subtypeRelation ) ; } if ( ! result ) { candidateForArgumentError = undefined ; candidateForTypeArgumentError = undefined ; resultOfFailedInference = undefined ; result = chooseOverload ( candidates , assignableRelation ) ; } if ( result ) { return result ; } if ( candidateForArgumentError ) { checkApplicableSignature ( node , args , candidateForArgumentError , assignableRelation , undefined , true ) ; } else if ( candidateForTypeArgumentError ) { if ( ! isTaggedTemplate && ( < CallExpression > node ) . typeArguments ) { checkTypeArguments ( candidateForTypeArgumentError , ( < CallExpression > node ) . typeArguments , [ ] , true ) ; } else { Debug . assert ( resultOfFailedInference . failedTypeParameterIndex >= 0 ) ; var failedTypeParameter = candidateForTypeArgumentError . typeParameters [ resultOfFailedInference . failedTypeParameterIndex ] ; var inferenceCandidates = getInferenceCandidates ( resultOfFailedInference , resultOfFailedInference . failedTypeParameterIndex ) ; var diagnosticChainHead = chainDiagnosticMessages ( undefined , Diagnostics . The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly , typeToString ( failedTypeParameter ) ) ; reportNoCommonSupertypeError ( inferenceCandidates , ( < CallExpression > node ) . expression || ( < TaggedTemplateExpression > node ) . tag , diagnosticChainHead ) ; } } else { error ( node , Diagnostics . Supplied_parameters_do_not_match_any_signature_of_call_target ) ; } if ( ! fullTypeCheck ) { for ( var i = 0 , n = candidates . length ; i < n ; i ++ ) { if ( hasCorrectArity ( node , args , candidates [ i ] ) ) { return candidates [ i ] ; } } } return resolveErrorCall ( node ) ; function chooseOverload ( candidates , relation ) { for ( var i = 0 ; i < candidates . length ; i ++ ) { if ( ! hasCorrectArity ( node , args , candidates [ i ] ) ) { continue ; } var originalCandidate = candidates [ i ] ; var inferenceResult ; while ( true ) { var candidate = originalCandidate ; if ( candidate . typeParameters ) { var typeArgumentTypes ; var typeArgumentsAreValid ; if ( typeArguments ) { typeArgumentTypes = new Array < Type > ( candidate . typeParameters . length ) ; typeArgumentsAreValid = checkTypeArguments ( candidate , typeArguments , typeArgumentTypes , false ) ; } else { inferenceResult = inferTypeArguments ( candidate , args , excludeArgument ) ; typeArgumentsAreValid = inferenceResult . failedTypeParameterIndex < 0 ; typeArgumentTypes = inferenceResult . inferredTypes ; } if ( ! typeArgumentsAreValid ) { break ; } candidate = getSignatureInstantiation ( candidate , typeArgumentTypes ) ; } if ( ! checkApplicableSignature ( node , args , candidate , relation , excludeArgument , false ) ) { break ; } var index = excludeArgument ? indexOf ( excludeArgument , true ) : - 1 ; if ( index < 0 ) { return candidate ; } excludeArgument [ index ] = false ; } if ( originalCandidate . typeParameters ) { var instantiatedCandidate = candidate ; if ( typeArgumentsAreValid ) { candidateForArgumentError = instantiatedCandidate ; } else { candidateForTypeArgumentError = originalCandidate ; if ( ! typeArguments ) { resultOfFailedInference = inferenceResult ; } } } else { Debug . assert ( originalCandidate === candidate ) ; candidateForArgumentError = originalCandidate ; } } return undefined ; } function collectCandidates ( ) { var result = candidates ; var lastParent ; var lastSymbol ; var cutoffPos = 0 ; var pos ; Debug . assert ( ! result . length ) ; for ( var i = 0 ; i < signatures . length ; i ++ ) { var signature = signatures [ i ] ; var symbol = signature . declaration && getSymbolOfNode ( signature . declaration ) ; var parent = signature . declaration && signature . declaration . parent ; if ( ! lastSymbol || symbol === lastSymbol ) { if ( lastParent && parent === lastParent ) { pos ++ ; } else { lastParent = parent ; pos = cutoffPos ; } } else { pos = cutoffPos = result . length ; lastParent = parent ; } lastSymbol = symbol ; for ( var j = result . length ; j > pos ; j -- ) { result [ j ] = result [ j - 1 ] ; } result [ pos ] = signature ; } } } function resolveCallExpression ( node , candidatesOutArray ) { if ( node . expression . kind === SyntaxKind . SuperKeyword ) { var superType = checkSuperExpression ( node . expression ) ; if ( superType !== unknownType ) { return resolveCall ( node , getSignaturesOfType ( superType , SignatureKind . Construct ) , candidatesOutArray ) ; } return resolveUntypedCall ( node ) ; } var funcType = checkExpression ( node . expression ) ; var apparentType = getApparentType ( funcType ) ; if ( apparentType === unknownType ) { return resolveErrorCall ( node ) ; } var callSignatures = getSignaturesOfType ( apparentType , SignatureKind . Call ) ; var constructSignatures = getSignaturesOfType ( apparentType , SignatureKind . Construct ) ; if ( funcType === anyType || ( ! callSignatures . length && ! constructSignatures . length && ! ( funcType . flags & TypeFlags . Union ) && isTypeAssignableTo ( funcType , globalFunctionType ) ) ) { if ( node . typeArguments ) { error ( node , Diagnostics . Untyped_function_calls_may_not_accept_type_arguments ) ; } return resolveUntypedCall ( node ) ; } if ( ! callSignatures . length ) { if ( constructSignatures . length ) { error ( node , Diagnostics . Value_of_type_0_is_not_callable_Did_you_mean_to_include_new , typeToString ( funcType ) ) ; } else { error ( node , Diagnostics . Cannot_invoke_an_expression_whose_type_lacks_a_call_signature ) ; } return resolveErrorCall ( node ) ; } return resolveCall ( node , callSignatures , candidatesOutArray ) ; } function resolveNewExpression ( node , candidatesOutArray ) { var expressionType = checkExpression ( node . expression ) ; if ( expressionType === anyType ) { if ( node . typeArguments ) { error ( node , Diagnostics . Untyped_function_calls_may_not_accept_type_arguments ) ; } return resolveUntypedCall ( node ) ; } expressionType = getApparentType ( expressionType ) ; if ( expressionType === unknownType ) { return resolveErrorCall ( node ) ; } var constructSignatures = getSignaturesOfType ( expressionType , SignatureKind . Construct ) ; if ( constructSignatures . length ) { return resolveCall ( node , constructSignatures , candidatesOutArray ) ; } var callSignatures = getSignaturesOfType ( expressionType , SignatureKind . Call ) ; if ( callSignatures . length ) { var signature = resolveCall ( node , callSignatures , candidatesOutArray ) ; if ( getReturnTypeOfSignature ( signature ) !== voidType ) { error ( node , Diagnostics . Only_a_void_function_can_be_called_with_the_new_keyword ) ; } return signature ; } error ( node , Diagnostics . Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature ) ; return resolveErrorCall ( node ) ; } function resolveTaggedTemplateExpression ( node , candidatesOutArray ) { var tagType = checkExpression ( node . tag ) ; var apparentType = getApparentType ( tagType ) ; if ( apparentType === unknownType ) { return resolveErrorCall ( node ) ; } var callSignatures = getSignaturesOfType ( apparentType , SignatureKind . Call ) ; if ( tagType === anyType || ( ! callSignatures . length && ! ( tagType . flags & TypeFlags . Union ) && isTypeAssignableTo ( tagType , globalFunctionType ) ) ) { return resolveUntypedCall ( node ) ; } if ( ! callSignatures . length ) { error ( node , Diagnostics . Cannot_invoke_an_expression_whose_type_lacks_a_call_signature ) ; return resolveErrorCall ( node ) ; } return resolveCall ( node , callSignatures , candidatesOutArray ) ; } function getResolvedSignature ( node , candidatesOutArray ? ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedSignature || candidatesOutArray ) { links . resolvedSignature = anySignature ; if ( node . kind === SyntaxKind . CallExpression ) { links . resolvedSignature = resolveCallExpression ( < CallExpression > node , candidatesOutArray ) ; } else if ( node . kind === SyntaxKind . NewExpression ) { links . resolvedSignature = resolveNewExpression ( < NewExpression > node , candidatesOutArray ) ; } else if ( node . kind === SyntaxKind . TaggedTemplateExpression ) { links . resolvedSignature = resolveTaggedTemplateExpression ( < TaggedTemplateExpression > node , candidatesOutArray ) ; } else { Debug . fail ( "Branch in 'getResolvedSignature' should be unreachable." ) ; } } return links . resolvedSignature ; } function checkCallExpression ( node ) { var signature = getResolvedSignature ( node ) ; if ( node . expression . kind === SyntaxKind . SuperKeyword ) { return voidType ; } if ( node . kind === SyntaxKind . NewExpression ) { var declaration = signature . declaration ; if ( declaration && declaration . kind !== SyntaxKind . Constructor && declaration . kind !== SyntaxKind . ConstructSignature && declaration . kind !== SyntaxKind . ConstructorType ) { if ( compilerOptions . noImplicitAny ) { error ( node , Diagnostics . new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type ) ; } return anyType ; } } return getReturnTypeOfSignature ( signature ) ; } function checkTaggedTemplateExpression ( node ) { return getReturnTypeOfSignature ( getResolvedSignature ( node ) ) ; } function checkTypeAssertion ( node ) { var exprType = checkExpression ( node . expression ) ; var targetType = getTypeFromTypeNode ( node . type ) ; if ( fullTypeCheck && targetType !== unknownType ) { var widenedType = getWidenedType ( exprType , true ) ; if ( ! ( isTypeAssignableTo ( targetType , widenedType ) ) ) { checkTypeAssignableTo ( exprType , targetType , node , Diagnostics . Neither_type_0_nor_type_1_is_assignable_to_the_other ) ; } } return targetType ; } function getTypeAtPosition ( signature , pos ) { return signature . hasRestParameter ? pos < signature . parameters . length - 1 ? getTypeOfSymbol ( signature . parameters [ pos ] ) : getRestTypeOfSignature ( signature ) : pos < signature . parameters . length ? getTypeOfSymbol ( signature . parameters [ pos ] ) : anyType ; } function assignContextualParameterTypes ( signature , context , mapper ) { var len = signature . parameters . length - ( signature . hasRestParameter ? 1 : 0 ) ; for ( var i = 0 ; i < len ; i ++ ) { var parameter = signature . parameters [ i ] ; var links = getSymbolLinks ( parameter ) ; links . type = instantiateType ( getTypeAtPosition ( context , i ) , mapper ) ; } if ( signature . hasRestParameter && context . hasRestParameter && signature . parameters . length >= context . parameters . length ) { var parameter = signature . parameters [ signature . parameters . length - 1 ] ; var links = getSymbolLinks ( parameter ) ; links . type = instantiateType ( getTypeOfSymbol ( context . parameters [ context . parameters . length - 1 ] ) , mapper ) ; } } function getReturnTypeFromBody ( func , contextualMapper ? ) { var contextualSignature = getContextualSignatureForFunctionLikeDeclaration ( func ) ; if ( func . body . kind !== SyntaxKind . Block ) { var unwidenedType = checkAndMarkExpression ( < Expression > func . body , contextualMapper ) ; var widenedType = getWidenedType ( unwidenedType ) ; if ( fullTypeCheck && compilerOptions . noImplicitAny && ! contextualSignature && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes ( widenedType ) === anyType ) { error ( func , Diagnostics . Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type , typeToString ( widenedType ) ) ; } return widenedType ; } var types = checkAndAggregateReturnExpressionTypes ( < Block > func . body , contextualMapper ) ; if ( types . length > 0 ) { var commonType = contextualSignature ? getUnionType ( types ) : getCommonSupertype ( types ) ; if ( ! commonType ) { error ( func , Diagnostics . No_best_common_type_exists_among_return_expressions ) ; return unknownType ; } var widenedType = getWidenedType ( commonType ) ; if ( fullTypeCheck && compilerOptions . noImplicitAny && ! contextualSignature && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes ( widenedType ) === anyType ) { var typeName = typeToString ( widenedType ) ; if ( func . name ) { error ( func , Diagnostics . _0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type , declarationNameToString ( func . name ) , typeName ) ; } else { error ( func , Diagnostics . Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type , typeName ) ; } } return widenedType ; } return voidType ; } function checkAndAggregateReturnExpressionTypes ( body , contextualMapper ? ) { var aggregatedTypes = [ ] ; forEachReturnStatement ( body , returnStatement => { var expr = returnStatement . expression ; if ( expr ) { var type = checkAndMarkExpression ( expr , contextualMapper ) ; if ( ! contains ( aggregatedTypes , type ) ) { aggregatedTypes . push ( type ) ; } } } ) ; return aggregatedTypes ; } function bodyContainsAReturnStatement ( funcBody ) { return forEachReturnStatement ( funcBody , returnStatement => { return true ; } ) ; } function bodyContainsSingleThrowStatement ( body ) { return ( body . statements . length === 1 ) && ( body . statements [ 0 ] . kind === SyntaxKind . ThrowStatement ) ; } function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment ( func , returnType ) { if ( ! fullTypeCheck ) { return ; } if ( returnType === voidType || returnType === anyType ) { return ; } if ( ! func . body || func . body . kind !== SyntaxKind . Block ) { return ; } var bodyBlock = < Block > func . body ; if ( bodyContainsAReturnStatement ( bodyBlock ) ) { return ; } if ( bodyContainsSingleThrowStatement ( bodyBlock ) ) { return ; } error ( func . type , Diagnostics . A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement ) ; } function checkFunctionExpressionOrObjectLiteralMethod ( node , contextualMapper ? ) { Debug . assert ( node . kind !== SyntaxKind . Method || isObjectLiteralMethod ( node ) ) ; if ( contextualMapper === identityMapper ) { return anyFunctionType ; } var links = getNodeLinks ( node ) ; var type = getTypeOfSymbol ( node . symbol ) ; if ( ! ( links . flags & NodeCheckFlags . ContextChecked ) ) { var contextualSignature = getContextualSignature ( node ) ; if ( ! ( links . flags & NodeCheckFlags . ContextChecked ) ) { links . flags |= NodeCheckFlags . ContextChecked ; if ( contextualSignature ) { var signature = getSignaturesOfType ( type , SignatureKind . Call ) [ 0 ] ; if ( isContextSensitive ( node ) ) { assignContextualParameterTypes ( signature , contextualSignature , contextualMapper || identityMapper ) ; } if ( ! node . type ) { signature . resolvedReturnType = resolvingType ; var returnType = getReturnTypeFromBody ( node , contextualMapper ) ; if ( signature . resolvedReturnType === resolvingType ) { signature . resolvedReturnType = returnType ; } } } checkSignatureDeclaration ( node ) ; } } if ( fullTypeCheck && node . kind !== SyntaxKind . Method ) { checkCollisionWithCapturedSuperVariable ( node , ( < FunctionExpression > node ) . name ) ; checkCollisionWithCapturedThisVariable ( node , ( < FunctionExpression > node ) . name ) ; } return type ; } function checkFunctionExpressionOrObjectLiteralMethodBody ( node ) { Debug . assert ( node . kind !== SyntaxKind . Method || isObjectLiteralMethod ( node ) ) ; if ( node . type ) { checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment ( node , getTypeFromTypeNode ( node . type ) ) ; } if ( node . body ) { if ( node . body . kind === SyntaxKind . Block ) { checkSourceElement ( node . body ) ; } else { var exprType = checkExpression ( < Expression > node . body ) ; if ( node . type ) { checkTypeAssignableTo ( exprType , getTypeFromTypeNode ( node . type ) , node . body , undefined ) ; } checkFunctionExpressionBodies ( node . body ) ; } } } function checkArithmeticOperandType ( operand , type , diagnostic ) { if ( ! ( type . flags & ( TypeFlags . Any | TypeFlags . NumberLike ) ) ) { error ( operand , diagnostic ) ; return false ; } return true ; } function checkReferenceExpression ( n , invalidReferenceMessage , constantVarianleMessage ) { function findSymbol ( n ) { var symbol = getNodeLinks ( n ) . resolvedSymbol ; return symbol && getExportSymbolOfValueSymbolIfExported ( symbol ) ; } function isReferenceOrErrorExpression ( n ) { switch ( n . kind ) { case SyntaxKind . Identifier : var symbol = findSymbol ( n ) ; return ! symbol || symbol === unknownSymbol || symbol === argumentsSymbol || ( symbol . flags & SymbolFlags . Variable ) !== 0 ; case SyntaxKind . PropertyAccessExpression : var symbol = findSymbol ( n ) ; return ! symbol || symbol === unknownSymbol || ( symbol . flags & ~ SymbolFlags . EnumMember ) !== 0 ; case SyntaxKind . ElementAccessExpression : return true ; case SyntaxKind . ParenthesizedExpression : return isReferenceOrErrorExpression ( ( < ParenthesizedExpression > n ) . expression ) ; default : return false ; } } function isConstVariableReference ( n ) { switch ( n . kind ) { case SyntaxKind . Identifier : case SyntaxKind . PropertyAccessExpression : var symbol = findSymbol ( n ) ; return symbol && ( symbol . flags & SymbolFlags . Variable ) !== 0 && ( getDeclarationFlagsFromSymbol ( symbol ) & NodeFlags . Const ) !== 0 ; case SyntaxKind . ElementAccessExpression : var index = ( < ElementAccessExpression > n ) . argumentExpression ; var symbol = findSymbol ( ( < ElementAccessExpression > n ) . expression ) ; if ( symbol && index && index . kind === SyntaxKind . StringLiteral ) { var name = ( < LiteralExpression > index ) . text ; var prop = getPropertyOfType ( getTypeOfSymbol ( symbol ) , name ) ; return prop && ( prop . flags & SymbolFlags . Variable ) !== 0 && ( getDeclarationFlagsFromSymbol ( prop ) & NodeFlags . Const ) !== 0 ; } return false ; case SyntaxKind . ParenthesizedExpression : return isConstVariableReference ( ( < ParenthesizedExpression > n ) . expression ) ; default : return false ; } } if ( ! isReferenceOrErrorExpression ( n ) ) { error ( n , invalidReferenceMessage ) ; return false ; } if ( isConstVariableReference ( n ) ) { error ( n , constantVarianleMessage ) ; return false ; } return true ; } function checkDeleteExpression ( node ) { var operandType = checkExpression ( node . expression ) ; return booleanType ; } function checkTypeOfExpression ( node ) { var operandType = checkExpression ( node . expression ) ; return stringType ; } function checkVoidExpression ( node ) { var operandType = checkExpression ( node . expression ) ; return undefinedType ; } function checkPrefixUnaryExpression ( node ) { var operandType = checkExpression ( node . operand ) ; switch ( node . operator ) { case SyntaxKind . PlusToken : case SyntaxKind . MinusToken : case SyntaxKind . TildeToken : return numberType ; case SyntaxKind . ExclamationToken : return booleanType ; case SyntaxKind . PlusPlusToken : case SyntaxKind . MinusMinusToken : var ok = checkArithmeticOperandType ( node . operand , operandType , Diagnostics . An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type ) ; if ( ok ) { checkReferenceExpression ( node . operand , Diagnostics . The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer , Diagnostics . The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant ) ; } return numberType ; } return unknownType ; } function checkPostfixUnaryExpression ( node ) { var operandType = checkExpression ( node . operand ) ; var ok = checkArithmeticOperandType ( node . operand , operandType , Diagnostics . An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type ) ; if ( ok ) { checkReferenceExpression ( node . operand , Diagnostics . The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer , Diagnostics . The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant ) ; } return numberType ; } function isStructuredType ( type ) { if ( type . flags & TypeFlags . Union ) { return ! forEach ( ( < UnionType > type ) . types , t => ! isStructuredType ( t ) ) ; } return ( type . flags & ( TypeFlags . ObjectType | TypeFlags . TypeParameter ) ) !== 0 ; } function isConstEnumObjectType ( type ) { return type . flags & ( TypeFlags . ObjectType | TypeFlags . Anonymous ) && type . symbol && isConstEnumSymbol ( type . symbol ) ; } function isConstEnumSymbol ( symbol ) { return ( symbol . flags & SymbolFlags . ConstEnum ) !== 0 ; } function checkInstanceOfExpression ( node , leftType , rightType ) { if ( ! ( leftType . flags & TypeFlags . Any || isStructuredType ( leftType ) ) ) { error ( node . left , Diagnostics . The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter ) ; } if ( ! ( rightType . flags & TypeFlags . Any || isTypeSubtypeOf ( rightType , globalFunctionType ) ) ) { error ( node . right , Diagnostics . The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type ) ; } return booleanType ; } function checkInExpression ( node , leftType , rightType ) { if ( leftType !== anyType && leftType !== stringType && leftType !== numberType ) { error ( node . left , Diagnostics . The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number ) ; } if ( ! ( rightType . flags & TypeFlags . Any || isStructuredType ( rightType ) ) ) { error ( node . right , Diagnostics . The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter ) ; } return booleanType ; } function checkBinaryExpression ( node , contextualMapper ? ) { var operator = node . operator ; var leftType = checkExpression ( node . left , contextualMapper ) ; var rightType = checkExpression ( node . right , contextualMapper ) ; switch ( operator ) { case SyntaxKind . AsteriskToken : case SyntaxKind . AsteriskEqualsToken : case SyntaxKind . SlashToken : case SyntaxKind . SlashEqualsToken : case SyntaxKind . PercentToken : case SyntaxKind . PercentEqualsToken : case SyntaxKind . MinusToken : case SyntaxKind . MinusEqualsToken : case SyntaxKind . LessThanLessThanToken : case SyntaxKind . LessThanLessThanEqualsToken : case SyntaxKind . GreaterThanGreaterThanToken : case SyntaxKind . GreaterThanGreaterThanEqualsToken : case SyntaxKind . GreaterThanGreaterThanGreaterThanToken : case SyntaxKind . GreaterThanGreaterThanGreaterThanEqualsToken : case SyntaxKind . BarToken : case SyntaxKind . BarEqualsToken : case SyntaxKind . CaretToken : case SyntaxKind . CaretEqualsToken : case SyntaxKind . AmpersandToken : case SyntaxKind . AmpersandEqualsToken : if ( leftType . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) leftType = rightType ; if ( rightType . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) rightType = leftType ; var suggestedOperator ; if ( ( leftType . flags & TypeFlags . Boolean ) && ( rightType . flags & TypeFlags . Boolean ) && ( suggestedOperator = getSuggestedBooleanOperator ( node . operator ) ) !== undefined ) { error ( node , Diagnostics . The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead , tokenToString ( node . operator ) , tokenToString ( suggestedOperator ) ) ; } else { var leftOk = checkArithmeticOperandType ( node . left , leftType , Diagnostics . The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type ) ; var rightOk = checkArithmeticOperandType ( node . right , rightType , Diagnostics . The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type ) ; if ( leftOk && rightOk ) { checkAssignmentOperator ( numberType ) ; } } return numberType ; case SyntaxKind . PlusToken : case SyntaxKind . PlusEqualsToken : if ( leftType . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) leftType = rightType ; if ( rightType . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) rightType = leftType ; var resultType ; if ( leftType . flags & TypeFlags . NumberLike && rightType . flags & TypeFlags . NumberLike ) { resultType = numberType ; } else if ( leftType . flags & TypeFlags . StringLike || rightType . flags & TypeFlags . StringLike ) { resultType = stringType ; } else if ( leftType . flags & TypeFlags . Any || leftType === unknownType || rightType . flags & TypeFlags . Any || rightType === unknownType ) { resultType = anyType ; } if ( ! resultType ) { reportOperatorError ( ) ; return anyType ; } if ( operator === SyntaxKind . PlusEqualsToken ) { checkAssignmentOperator ( resultType ) ; } return resultType ; case SyntaxKind . EqualsEqualsToken : case SyntaxKind . ExclamationEqualsToken : case SyntaxKind . EqualsEqualsEqualsToken : case SyntaxKind . ExclamationEqualsEqualsToken : case SyntaxKind . LessThanToken : case SyntaxKind . GreaterThanToken : case SyntaxKind . LessThanEqualsToken : case SyntaxKind . GreaterThanEqualsToken : if ( ! isTypeAssignableTo ( leftType , rightType ) && ! isTypeAssignableTo ( rightType , leftType ) ) { reportOperatorError ( ) ; } return booleanType ; case SyntaxKind . InstanceOfKeyword : return checkInstanceOfExpression ( node , leftType , rightType ) ; case SyntaxKind . InKeyword : return checkInExpression ( node , leftType , rightType ) ; case SyntaxKind . AmpersandAmpersandToken : return rightType ; case SyntaxKind . BarBarToken : return getUnionType ( [ leftType , rightType ] ) ; case SyntaxKind . EqualsToken : checkAssignmentOperator ( rightType ) ; return rightType ; case SyntaxKind . CommaToken : return rightType ; } function getSuggestedBooleanOperator ( operator ) { switch ( operator ) { case SyntaxKind . BarToken : case SyntaxKind . BarEqualsToken : return SyntaxKind . BarBarToken ; case SyntaxKind . CaretToken : case SyntaxKind . CaretEqualsToken : return SyntaxKind . ExclamationEqualsEqualsToken ; case SyntaxKind . AmpersandToken : case SyntaxKind . AmpersandEqualsToken : return SyntaxKind . AmpersandAmpersandToken ; default : return undefined ; } } function checkAssignmentOperator ( valueType ) { if ( fullTypeCheck && operator >= SyntaxKind . FirstAssignment && operator <= SyntaxKind . LastAssignment ) { var ok = checkReferenceExpression ( node . left , Diagnostics . Invalid_left_hand_side_of_assignment_expression , Diagnostics . Left_hand_side_of_assignment_expression_cannot_be_a_constant ) ; if ( ok ) { checkTypeAssignableTo ( valueType , leftType , node . left , undefined ) ; } } } function reportOperatorError ( ) { error ( node , Diagnostics . Operator_0_cannot_be_applied_to_types_1_and_2 , tokenToString ( node . operator ) , typeToString ( leftType ) , typeToString ( rightType ) ) ; } } function checkConditionalExpression ( node , contextualMapper ? ) { checkExpression ( node . condition ) ; var type1 = checkExpression ( node . whenTrue , contextualMapper ) ; var type2 = checkExpression ( node . whenFalse , contextualMapper ) ; return getUnionType ( [ type1 , type2 ] ) ; } function checkTemplateExpression ( node ) { forEach ( ( < TemplateExpression > node ) . templateSpans , templateSpan => { checkExpression ( templateSpan . expression ) ; } ) ; return stringType ; } function checkExpressionWithContextualType ( node , contextualType , contextualMapper ? ) { var saveContextualType = node . contextualType ; node . contextualType = contextualType ; var result = checkExpression ( node , contextualMapper ) ; node . contextualType = saveContextualType ; return result ; } function checkAndMarkExpression ( node , contextualMapper ? ) { var result = checkExpression ( node , contextualMapper ) ; getNodeLinks ( node ) . flags |= NodeCheckFlags . TypeChecked ; return result ; } function checkObjectLiteralMethod ( node , contextualMapper ? ) { var uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod ( node , contextualMapper ) ; return instantiateTypeWithSingleGenericCallSignature ( node , uninstantiatedType , contextualMapper ) ; } function instantiateTypeWithSingleGenericCallSignature ( node , type , contextualMapper ? ) { if ( contextualMapper && contextualMapper !== identityMapper ) { var signature = getSingleCallSignature ( type ) ; if ( signature && signature . typeParameters ) { var contextualType = getContextualType ( < Expression > node ) ; if ( contextualType ) { var contextualSignature = getSingleCallSignature ( contextualType ) ; if ( contextualSignature && ! contextualSignature . typeParameters ) { return getOrCreateTypeFromSignature ( instantiateSignatureInContextOf ( signature , contextualSignature , contextualMapper ) ) ; } } } } return type ; } function checkExpression ( node , contextualMapper ? ) { return checkExpressionOrQualifiedName ( node , contextualMapper ) ; } function checkExpressionOrQualifiedName ( node , contextualMapper ? ) { var type ; if ( node . kind == SyntaxKind . QualifiedName ) { type = checkQualifiedName ( < QualifiedName > node ) ; } else { var uninstantiatedType = checkExpressionWorker ( < Expression > node , contextualMapper ) ; type = instantiateTypeWithSingleGenericCallSignature ( < Expression > node , uninstantiatedType , contextualMapper ) ; } if ( isConstEnumObjectType ( type ) ) { var ok = ( node . parent . kind === SyntaxKind . PropertyAccessExpression && ( < PropertyAccessExpression > node . parent ) . expression === node ) || ( node . parent . kind === SyntaxKind . ElementAccessExpression && ( < ElementAccessExpression > node . parent ) . expression === node ) || ( ( node . kind === SyntaxKind . Identifier || node . kind === SyntaxKind . QualifiedName ) && isInRightSideOfImportOrExportAssignment ( < Identifier > node ) ) ; if ( ! ok ) { error ( node , Diagnostics . const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment ) ; } } return type ; } function checkExpressionWorker ( node , contextualMapper ) { switch ( node . kind ) { case SyntaxKind . Identifier : return checkIdentifier ( < Identifier > node ) ; case SyntaxKind . ThisKeyword : return checkThisExpression ( node ) ; case SyntaxKind . SuperKeyword : return checkSuperExpression ( node ) ; case SyntaxKind . NullKeyword : return nullType ; case SyntaxKind . TrueKeyword : case SyntaxKind . FalseKeyword : return booleanType ; case SyntaxKind . NumericLiteral : return numberType ; case SyntaxKind . TemplateExpression : return checkTemplateExpression ( < TemplateExpression > node ) ; case SyntaxKind . StringLiteral : case SyntaxKind . NoSubstitutionTemplateLiteral : return stringType ; case SyntaxKind . RegularExpressionLiteral : return globalRegExpType ; case SyntaxKind . ArrayLiteralExpression : return checkArrayLiteral ( < ArrayLiteralExpression > node , contextualMapper ) ; case SyntaxKind . ObjectLiteralExpression : return checkObjectLiteral ( < ObjectLiteralExpression > node , contextualMapper ) ; case SyntaxKind . PropertyAccessExpression : return checkPropertyAccessExpression ( < PropertyAccessExpression > node ) ; case SyntaxKind . ElementAccessExpression : return checkIndexedAccess ( < ElementAccessExpression > node ) ; case SyntaxKind . CallExpression : case SyntaxKind . NewExpression : return checkCallExpression ( < CallExpression > node ) ; case SyntaxKind . TaggedTemplateExpression : return checkTaggedTemplateExpression ( < TaggedTemplateExpression > node ) ; case SyntaxKind . TypeAssertionExpression : return checkTypeAssertion ( < TypeAssertion > node ) ; case SyntaxKind . ParenthesizedExpression : return checkExpression ( ( < ParenthesizedExpression > node ) . expression ) ; case SyntaxKind . FunctionExpression : case SyntaxKind . ArrowFunction : return checkFunctionExpressionOrObjectLiteralMethod ( < FunctionExpression > node , contextualMapper ) ; case SyntaxKind . TypeOfExpression : return checkTypeOfExpression ( < TypeOfExpression > node ) ; case SyntaxKind . DeleteExpression : return checkDeleteExpression ( < DeleteExpression > node ) ; case SyntaxKind . VoidExpression : return checkVoidExpression ( < VoidExpression > node ) ; case SyntaxKind . PrefixUnaryExpression : return checkPrefixUnaryExpression ( < PrefixUnaryExpression > node ) ; case SyntaxKind . PostfixUnaryExpression : return checkPostfixUnaryExpression ( < PostfixUnaryExpression > node ) ; case SyntaxKind . BinaryExpression : return checkBinaryExpression ( < BinaryExpression > node , contextualMapper ) ; case SyntaxKind . ConditionalExpression : return checkConditionalExpression ( < ConditionalExpression > node , contextualMapper ) ; case SyntaxKind . OmittedExpression : return undefinedType ; } return unknownType ; } function checkTypeParameter ( node ) { checkSourceElement ( node . constraint ) ; if ( fullTypeCheck ) { checkTypeParameterHasIllegalReferencesInConstraint ( node ) ; checkTypeNameIsReserved ( node . name , Diagnostics . Type_parameter_name_cannot_be_0 ) ; } } function checkParameter ( parameterDeclaration ) { checkVariableOrParameterDeclaration ( parameterDeclaration ) ; if ( fullTypeCheck ) { checkCollisionWithIndexVariableInGeneratedCode ( parameterDeclaration , parameterDeclaration . name ) ; if ( parameterDeclaration . flags & ( NodeFlags . Public | NodeFlags . Private | NodeFlags . Protected ) && ! ( parameterDeclaration . parent . kind === SyntaxKind . Constructor && ( < ConstructorDeclaration > parameterDeclaration . parent ) . body ) ) { error ( parameterDeclaration , Diagnostics . A_parameter_property_is_only_allowed_in_a_constructor_implementation ) ; } if ( parameterDeclaration . dotDotDotToken ) { if ( ! isArrayType ( getTypeOfSymbol ( parameterDeclaration . symbol ) ) ) { error ( parameterDeclaration , Diagnostics . A_rest_parameter_must_be_of_an_array_type ) ; } } else { if ( parameterDeclaration . initializer && ! ( < FunctionLikeDeclaration > parameterDeclaration . parent ) . body ) { error ( parameterDeclaration , Diagnostics . A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation ) ; } } } function checkReferencesInInitializer ( n ) { if ( n . kind === SyntaxKind . Identifier ) { var referencedSymbol = getNodeLinks ( n ) . resolvedSymbol ; if ( referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol ( parameterDeclaration . parent . locals , referencedSymbol . name , SymbolFlags . Value ) === referencedSymbol ) { if ( referencedSymbol . valueDeclaration . kind === SyntaxKind . Parameter ) { if ( referencedSymbol . valueDeclaration === parameterDeclaration ) { error ( n , Diagnostics . Parameter_0_cannot_be_referenced_in_its_initializer , declarationNameToString ( parameterDeclaration . name ) ) ; return ; } var enclosingOrReferencedParameter = forEach ( ( < FunctionLikeDeclaration > parameterDeclaration . parent ) . parameters , p => p === parameterDeclaration || p === referencedSymbol . valueDeclaration ? p : undefined ) ; if ( enclosingOrReferencedParameter === referencedSymbol . valueDeclaration ) { return ; } } error ( n , Diagnostics . Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it , declarationNameToString ( parameterDeclaration . name ) , declarationNameToString ( < Identifier > n ) ) ; } } else { forEachChild ( n , checkReferencesInInitializer ) ; } } if ( parameterDeclaration . initializer ) { checkReferencesInInitializer ( parameterDeclaration . initializer ) ; } } function checkSignatureDeclaration ( node ) { checkTypeParameters ( node . typeParameters ) ; forEach ( node . parameters , checkParameter ) ; if ( node . type ) { checkSourceElement ( node . type ) ; } if ( fullTypeCheck ) { checkCollisionWithArgumentsInGeneratedCode ( node ) ; if ( compilerOptions . noImplicitAny && ! node . type ) { switch ( node . kind ) { case SyntaxKind . ConstructSignature : error ( node , Diagnostics . Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type ) ; break ; case SyntaxKind . CallSignature : error ( node , Diagnostics . Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type ) ; break ; } } } checkSpecializedSignatureDeclaration ( node ) ; } function checkTypeForDuplicateIndexSignatures ( node ) { if ( node . kind === SyntaxKind . InterfaceDeclaration ) { var nodeSymbol = getSymbolOfNode ( node ) ; if ( nodeSymbol . declarations . length > 0 && nodeSymbol . declarations [ 0 ] !== node ) { return ; } } var indexSymbol = getIndexSymbol ( getSymbolOfNode ( node ) ) ; if ( indexSymbol ) { var seenNumericIndexer = false ; var seenStringIndexer = false ; for ( var i = 0 , len = indexSymbol . declarations . length ; i < len ; ++ i ) { var declaration = < SignatureDeclaration > indexSymbol . declarations [ i ] ; if ( declaration . parameters . length == 1 && declaration . parameters [ 0 ] . type ) { switch ( declaration . parameters [ 0 ] . type . kind ) { case SyntaxKind . StringKeyword : if ( ! seenStringIndexer ) { seenStringIndexer = true ; } else { error ( declaration , Diagnostics . Duplicate_string_index_signature ) ; } break ; case SyntaxKind . NumberKeyword : if ( ! seenNumericIndexer ) { seenNumericIndexer = true ; } else { error ( declaration , Diagnostics . Duplicate_number_index_signature ) ; } break ; } } } } } function checkPropertyDeclaration ( node ) { if ( fullTypeCheck ) { checkVariableOrParameterOrPropertyInFullTypeCheck ( node ) ; } } function checkMethodDeclaration ( node ) { checkFunctionLikeDeclaration ( node ) ; } function checkConstructorDeclaration ( node ) { checkSignatureDeclaration ( node ) ; checkSourceElement ( node . body ) ; var symbol = getSymbolOfNode ( node ) ; var firstDeclaration = getDeclarationOfKind ( symbol , node . kind ) ; if ( node === firstDeclaration ) { checkFunctionOrConstructorSymbol ( symbol ) ; } if ( ! node . body ) { return ; } if ( ! fullTypeCheck ) { return ; } function isSuperCallExpression ( n ) { return n . kind === SyntaxKind . CallExpression && ( < CallExpression > n ) . expression . kind === SyntaxKind . SuperKeyword ; } function containsSuperCall ( n ) { if ( isSuperCallExpression ( n ) ) { return true ; } switch ( n . kind ) { case SyntaxKind . FunctionExpression : case SyntaxKind . FunctionDeclaration : case SyntaxKind . ArrowFunction : case SyntaxKind . ObjectLiteralExpression : return false ; default : return forEachChild ( n , containsSuperCall ) ; } } function markThisReferencesAsErrors ( n ) { if ( n . kind === SyntaxKind . ThisKeyword ) { error ( n , Diagnostics . this_cannot_be_referenced_in_current_location ) ; } else if ( n . kind !== SyntaxKind . FunctionExpression && n . kind !== SyntaxKind . FunctionDeclaration ) { forEachChild ( n , markThisReferencesAsErrors ) ; } } function isInstancePropertyWithInitializer ( n ) { return n . kind === SyntaxKind . Property && ! ( n . flags & NodeFlags . Static ) && ! ! ( < PropertyDeclaration > n ) . initializer ; } if ( getClassBaseTypeNode ( < ClassDeclaration > node . parent ) ) { if ( containsSuperCall ( node . body ) ) { var superCallShouldBeFirst = forEach ( ( < ClassDeclaration > node . parent ) . members , isInstancePropertyWithInitializer ) || forEach ( node . parameters , p => p . flags & ( NodeFlags . Public | NodeFlags . Private | NodeFlags . Protected ) ) ; if ( superCallShouldBeFirst ) { var statements = ( < Block > node . body ) . statements ; if ( ! statements . length || statements [ 0 ] . kind !== SyntaxKind . ExpressionStatement || ! isSuperCallExpression ( ( < ExpressionStatement > statements [ 0 ] ) . expression ) ) { error ( node , Diagnostics . A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties ) ; } else { markThisReferencesAsErrors ( ( < ExpressionStatement > statements [ 0 ] ) . expression ) ; } } } else { error ( node , Diagnostics . Constructors_for_derived_classes_must_contain_a_super_call ) ; } } } function checkAccessorDeclaration ( node ) { if ( fullTypeCheck ) { if ( node . kind === SyntaxKind . GetAccessor ) { if ( ! isInAmbientContext ( node ) && node . body && ! ( bodyContainsAReturnStatement ( < Block > node . body ) || bodyContainsSingleThrowStatement ( < Block > node . body ) ) ) { error ( node . name , Diagnostics . A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement ) ; } } if ( ! hasComputedNameButNotSymbol ( node ) ) { var otherKind = node . kind === SyntaxKind . GetAccessor ? SyntaxKind . SetAccessor : SyntaxKind . GetAccessor ; var otherAccessor = < AccessorDeclaration > getDeclarationOfKind ( node . symbol , otherKind ) ; if ( otherAccessor ) { if ( ( ( node . flags & NodeFlags . AccessibilityModifier ) !== ( otherAccessor . flags & NodeFlags . AccessibilityModifier ) ) ) { error ( node . name , Diagnostics . Getter_and_setter_accessors_do_not_agree_in_visibility ) ; } var currentAccessorType = getAnnotatedAccessorType ( node ) ; var otherAccessorType = getAnnotatedAccessorType ( otherAccessor ) ; if ( currentAccessorType && otherAccessorType ) { if ( ! isTypeIdenticalTo ( currentAccessorType , otherAccessorType ) ) { error ( node , Diagnostics . get_and_set_accessor_must_have_the_same_type ) ; } } } checkAndStoreTypeOfAccessors ( getSymbolOfNode ( node ) ) ; } } checkFunctionLikeDeclaration ( node ) ; } function checkTypeReference ( node ) { var type = getTypeFromTypeReferenceNode ( node ) ; if ( type && type . symbol && type . symbol . declarations ) { var sourceFile = getSourceFile ( node ) ; var dependFile = getSourceFile ( type . symbol . declarations [ 0 ] ) ; if ( sourceFile && dependFile ) { ts . UsedFileResolver . mapFile ( sourceFile . filename , dependFile . filename ) ; } } if ( type !== unknownType && node . typeArguments ) { var len = node . typeArguments . length ; for ( var i = 0 ; i < len ; i ++ ) { checkSourceElement ( node . typeArguments [ i ] ) ; var constraint = getConstraintOfTypeParameter ( ( < TypeReference > type ) . target . typeParameters [ i ] ) ; if ( fullTypeCheck && constraint ) { var typeArgument = ( < TypeReference > type ) . typeArguments [ i ] ; checkTypeAssignableTo ( typeArgument , constraint , node , Diagnostics . Type_0_does_not_satisfy_the_constraint_1 ) ; } } } } function checkTypeQuery ( node ) { getTypeFromTypeQueryNode ( node ) ; } function checkTypeLiteral ( node ) { forEach ( node . members , checkSourceElement ) ; if ( fullTypeCheck ) { var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode ( node ) ; checkIndexConstraints ( type ) ; checkTypeForDuplicateIndexSignatures ( node ) ; } } function checkArrayType ( node ) { checkSourceElement ( node . elementType ) ; } function checkTupleType ( node ) { forEach ( node . elementTypes , checkSourceElement ) ; } function checkUnionType ( node ) { forEach ( node . types , checkSourceElement ) ; } function isPrivateWithinAmbient ( node ) { return ( node . flags & NodeFlags . Private ) && isInAmbientContext ( node ) ; } function checkSpecializedSignatureDeclaration ( signatureDeclarationNode ) { if ( ! fullTypeCheck ) { return ; } var signature = getSignatureFromDeclaration ( signatureDeclarationNode ) ; if ( ! signature . hasStringLiterals ) { return ; } if ( ( < FunctionLikeDeclaration > signatureDeclarationNode ) . body ) { error ( signatureDeclarationNode , Diagnostics . A_signature_with_an_implementation_cannot_use_a_string_literal_type ) ; return ; } var signaturesToCheck ; if ( ! signatureDeclarationNode . name && signatureDeclarationNode . parent && signatureDeclarationNode . parent . kind === SyntaxKind . InterfaceDeclaration ) { Debug . assert ( signatureDeclarationNode . kind === SyntaxKind . CallSignature || signatureDeclarationNode . kind === SyntaxKind . ConstructSignature ) ; var signatureKind = signatureDeclarationNode . kind === SyntaxKind . CallSignature ? SignatureKind . Call : SignatureKind . Construct ; var containingSymbol = getSymbolOfNode ( signatureDeclarationNode . parent ) ; var containingType = getDeclaredTypeOfSymbol ( containingSymbol ) ; signaturesToCheck = getSignaturesOfType ( containingType , signatureKind ) ; } else { signaturesToCheck = getSignaturesOfSymbol ( getSymbolOfNode ( signatureDeclarationNode ) ) ; } for ( var i = 0 ; i < signaturesToCheck . length ; i ++ ) { var otherSignature = signaturesToCheck [ i ] ; if ( ! otherSignature . hasStringLiterals && isSignatureAssignableTo ( signature , otherSignature ) ) { return ; } } error ( signatureDeclarationNode , Diagnostics . Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature ) ; } function getEffectiveDeclarationFlags ( n , flagsToCheck ) { var flags = n . flags ; if ( n . parent . kind !== SyntaxKind . InterfaceDeclaration && isInAmbientContext ( n ) ) { if ( ! ( flags & NodeFlags . Ambient ) ) { flags |= NodeFlags . Export ; } flags |= NodeFlags . Ambient ; } return flags & flagsToCheck ; } function checkFunctionOrConstructorSymbol ( symbol ) { if ( ! fullTypeCheck ) { return ; } function getCanonicalOverload ( overloads , implementation ) { var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation . parent === overloads [ 0 ] . parent ; return implementationSharesContainerWithFirstOverload ? implementation : overloads [ 0 ] ; } function checkFlagAgreementBetweenOverloads ( overloads , implementation , flagsToCheck , someOverloadFlags , allOverloadFlags ) { var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags ; if ( someButNotAllOverloadFlags !== 0 ) { var canonicalFlags = getEffectiveDeclarationFlags ( getCanonicalOverload ( overloads , implementation ) , flagsToCheck ) ; forEach ( overloads , o => { var deviation = getEffectiveDeclarationFlags ( o , flagsToCheck ) ^ canonicalFlags ; if ( deviation & NodeFlags . Export ) { error ( o . name , Diagnostics . Overload_signatures_must_all_be_exported_or_not_exported ) ; } else if ( deviation & NodeFlags . Ambient ) { error ( o . name , Diagnostics . Overload_signatures_must_all_be_ambient_or_non_ambient ) ; } else if ( deviation & ( NodeFlags . Private | NodeFlags . Protected ) ) { error ( o . name , Diagnostics . Overload_signatures_must_all_be_public_private_or_protected ) ; } } ) ; } } function checkQuestionTokenAgreementBetweenOverloads ( overloads , implementation , someHaveQuestionToken , allHaveQuestionToken ) { if ( someHaveQuestionToken !== allHaveQuestionToken ) { var canonicalHasQuestionToken = hasQuestionToken ( getCanonicalOverload ( overloads , implementation ) ) ; forEach ( overloads , o => { var deviation = hasQuestionToken ( o ) !== canonicalHasQuestionToken ; if ( deviation ) { error ( o . name , Diagnostics . Overload_signatures_must_all_be_optional_or_required ) ; } } ) ; } } var flagsToCheck = NodeFlags . Export | NodeFlags . Ambient | NodeFlags . Private | NodeFlags . Protected ; var someNodeFlags = 0 ; var allNodeFlags = flagsToCheck ; var someHaveQuestionToken = false ; var allHaveQuestionToken = true ; var hasOverloads = false ; var bodyDeclaration ; var lastSeenNonAmbientDeclaration ; var previousDeclaration ; var declarations = symbol . declarations ; var isConstructor = ( symbol . flags & SymbolFlags . Constructor ) !== 0 ; function reportImplementationExpectedError ( node ) { if ( node . name && getFullWidth ( node . name ) === 0 ) { return ; } var seen = false ; var subsequentNode = forEachChild ( node . parent , c => { if ( seen ) { return c ; } else { seen = c === node ; } } ) ; if ( subsequentNode ) { if ( subsequentNode . kind === node . kind ) { var errorNode = ( < FunctionLikeDeclaration > subsequentNode ) . name || subsequentNode ; if ( node . name && ( < FunctionLikeDeclaration > subsequentNode ) . name && ( < Identifier > node . name ) . text === ( < Identifier > ( < FunctionLikeDeclaration > subsequentNode ) . name ) . text ) { Debug . assert ( node . kind === SyntaxKind . Method ) ; Debug . assert ( ( node . flags & NodeFlags . Static ) !== ( subsequentNode . flags & NodeFlags . Static ) ) ; var diagnostic = node . flags & NodeFlags . Static ? Diagnostics . Function_overload_must_be_static : Diagnostics . Function_overload_must_not_be_static ; error ( errorNode , diagnostic ) ; return ; } else if ( ( < FunctionLikeDeclaration > subsequentNode ) . body ) { error ( errorNode , Diagnostics . Function_implementation_name_must_be_0 , declarationNameToString ( node . name ) ) ; return ; } } } var errorNode = node . name || node ; if ( isConstructor ) { error ( errorNode , Diagnostics . Constructor_implementation_is_missing ) ; } else { error ( errorNode , Diagnostics . Function_implementation_is_missing_or_not_immediately_following_the_declaration ) ; } } var isExportSymbolInsideModule = symbol . parent && symbol . parent . flags & SymbolFlags . Module ; var duplicateFunctionDeclaration = false ; var multipleConstructorImplementation = false ; for ( var i = 0 ; i < declarations . length ; i ++ ) { var node = < FunctionLikeDeclaration > declarations [ i ] ; var inAmbientContext = isInAmbientContext ( node ) ; var inAmbientContextOrInterface = node . parent . kind === SyntaxKind . InterfaceDeclaration || node . parent . kind === SyntaxKind . TypeLiteral || inAmbientContext ; if ( inAmbientContextOrInterface ) { previousDeclaration = undefined ; } if ( node . kind === SyntaxKind . FunctionDeclaration || node . kind === SyntaxKind . Method || node . kind === SyntaxKind . Constructor ) { var currentNodeFlags = getEffectiveDeclarationFlags ( node , flagsToCheck ) ; someNodeFlags |= currentNodeFlags ; allNodeFlags &= currentNodeFlags ; someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken ( node ) ; allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken ( node ) ; if ( node . body && bodyDeclaration ) { if ( isConstructor ) { multipleConstructorImplementation = true ; } else { duplicateFunctionDeclaration = true ; } } else if ( ! isExportSymbolInsideModule && previousDeclaration && previousDeclaration . parent === node . parent && previousDeclaration . end !== node . pos ) { reportImplementationExpectedError ( previousDeclaration ) ; } if ( node . body ) { if ( ! bodyDeclaration ) { bodyDeclaration = node ; } } else { hasOverloads = true ; } previousDeclaration = node ; if ( ! inAmbientContextOrInterface ) { lastSeenNonAmbientDeclaration = node ; } } } if ( multipleConstructorImplementation ) { forEach ( declarations , declaration => { error ( declaration , Diagnostics . Multiple_constructor_implementations_are_not_allowed ) ; } ) ; } if ( duplicateFunctionDeclaration ) { forEach ( declarations , declaration => { error ( declaration . name , Diagnostics . Duplicate_function_implementation ) ; } ) ; } if ( ! isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && ! lastSeenNonAmbientDeclaration . body ) { reportImplementationExpectedError ( lastSeenNonAmbientDeclaration ) ; } if ( hasOverloads ) { checkFlagAgreementBetweenOverloads ( declarations , bodyDeclaration , flagsToCheck , someNodeFlags , allNodeFlags ) ; checkQuestionTokenAgreementBetweenOverloads ( declarations , bodyDeclaration , someHaveQuestionToken , allHaveQuestionToken ) ; if ( bodyDeclaration ) { var signatures = getSignaturesOfSymbol ( symbol ) ; var bodySignature = getSignatureFromDeclaration ( bodyDeclaration ) ; if ( ! bodySignature . hasStringLiterals ) { for ( var i = 0 , len = signatures . length ; i < len ; ++ i ) { if ( ! signatures [ i ] . hasStringLiterals && ! isSignatureAssignableTo ( bodySignature , signatures [ i ] ) ) { error ( signatures [ i ] . declaration , Diagnostics . Overload_signature_is_not_compatible_with_function_implementation ) ; break ; } } } } } } function checkExportsOnMergedDeclarations ( node ) { if ( ! fullTypeCheck ) { return ; } var symbol ; var symbol = node . localSymbol ; if ( ! symbol ) { symbol = getSymbolOfNode ( node ) ; if ( ! ( symbol . flags & SymbolFlags . Export ) ) { return ; } } if ( getDeclarationOfKind ( symbol , node . kind ) !== node ) { return ; } var exportedDeclarationSpaces = 0 ; var nonExportedDeclarationSpaces = 0 ; forEach ( symbol . declarations , d => { var declarationSpaces = getDeclarationSpaces ( d ) ; if ( getEffectiveDeclarationFlags ( d , NodeFlags . Export ) ) { exportedDeclarationSpaces |= declarationSpaces ; } else { nonExportedDeclarationSpaces |= declarationSpaces ; } } ) ; var commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces ; if ( commonDeclarationSpace ) { forEach ( symbol . declarations , d => { if ( getDeclarationSpaces ( d ) & commonDeclarationSpace ) { error ( d . name , Diagnostics . Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local , declarationNameToString ( d . name ) ) ; } } ) ; } function getDeclarationSpaces ( d ) { switch ( d . kind ) { case SyntaxKind . InterfaceDeclaration : return SymbolFlags . ExportType ; case SyntaxKind . ModuleDeclaration : return ( < ModuleDeclaration > d ) . name . kind === SyntaxKind . StringLiteral || getModuleInstanceState ( d ) !== ModuleInstanceState . NonInstantiated ? SymbolFlags . ExportNamespace | SymbolFlags . ExportValue : SymbolFlags . ExportNamespace ; case SyntaxKind . ClassDeclaration : case SyntaxKind . EnumDeclaration : return SymbolFlags . ExportType | SymbolFlags . ExportValue ; case SyntaxKind . ImportDeclaration : var result = 0 ; var target = resolveImport ( getSymbolOfNode ( d ) ) ; forEach ( target . declarations , d => { result |= getDeclarationSpaces ( d ) ; } ) ; return result ; default : return SymbolFlags . ExportValue ; } } } function checkFunctionDeclaration ( node ) { checkFunctionLikeDeclaration ( node ) ; if ( fullTypeCheck ) { checkCollisionWithCapturedSuperVariable ( node , node . name ) ; checkCollisionWithCapturedThisVariable ( node , node . name ) ; checkCollisionWithRequireExportsInGeneratedCode ( node , node . name ) ; } } function checkFunctionLikeDeclaration ( node ) { checkSignatureDeclaration ( node ) ; if ( ! hasComputedNameButNotSymbol ( node ) ) { var symbol = getSymbolOfNode ( node ) ; var localSymbol = node . localSymbol || symbol ; var firstDeclaration = getDeclarationOfKind ( localSymbol , node . kind ) ; if ( node === firstDeclaration ) { checkFunctionOrConstructorSymbol ( localSymbol ) ; } if ( symbol . parent ) { if ( getDeclarationOfKind ( symbol , node . kind ) === node ) { checkFunctionOrConstructorSymbol ( symbol ) ; } } } checkSourceElement ( node . body ) ; if ( node . type && ! isAccessor ( node . kind ) ) { checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment ( node , getTypeFromTypeNode ( node . type ) ) ; } if ( fullTypeCheck && compilerOptions . noImplicitAny && ! node . body && ! node . type ) { if ( ! isPrivateWithinAmbient ( node ) ) { var typeName = typeToString ( anyType ) ; if ( node . name ) { error ( node , Diagnostics . _0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type , declarationNameToString ( node . name ) , typeName ) ; } else { error ( node , Diagnostics . Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type , typeName ) ; } } } } function checkBlock ( node ) { forEach ( node . statements , checkSourceElement ) ; if ( isFunctionBlock ( node ) || node . kind === SyntaxKind . ModuleBlock ) { checkFunctionExpressionBodies ( node ) ; } } function checkCollisionWithArgumentsInGeneratedCode ( node ) { if ( ! hasRestParameters ( node ) || isInAmbientContext ( node ) || ! ( < FunctionLikeDeclaration > node ) . body ) { return ; } forEach ( node . parameters , p => { if ( p . name && p . name . text === argumentsSymbol . name ) { error ( p , Diagnostics . Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters ) ; } } ) ; } function checkCollisionWithIndexVariableInGeneratedCode ( node , name ) { if ( ! ( name && name . text === "_i" ) ) { return ; } if ( node . kind === SyntaxKind . Parameter ) { if ( ( < FunctionLikeDeclaration > node . parent ) . body && hasRestParameters ( < FunctionLikeDeclaration > node . parent ) && ! isInAmbientContext ( node ) ) { error ( node , Diagnostics . Duplicate_identifier_i_Compiler_uses_i_to_initialize_rest_parameter ) ; } return ; } var symbol = getNodeLinks ( node ) . resolvedSymbol ; if ( symbol === unknownSymbol ) { return ; } var current = node ; while ( current ) { var definedOnCurrentLevel = forEach ( symbol . declarations , d => d . parent === current ? d : undefined ) ; if ( definedOnCurrentLevel ) { return ; } switch ( current . kind ) { case SyntaxKind . FunctionDeclaration : case SyntaxKind . FunctionExpression : case SyntaxKind . Method : case SyntaxKind . ArrowFunction : case SyntaxKind . Constructor : if ( hasRestParameters ( < FunctionLikeDeclaration > current ) ) { error ( node , Diagnostics . Expression_resolves_to_variable_declaration_i_that_compiler_uses_to_initialize_rest_parameter ) ; return ; } break ; } current = current . parent ; } } function needCollisionCheckForIdentifier ( node , identifier , name ) { if ( ! identifier || identifier . text !== name ) { return false ; } if ( node . kind === SyntaxKind . Property || node . kind === SyntaxKind . Method || node . kind === SyntaxKind . GetAccessor || node . kind === SyntaxKind . SetAccessor ) { return false ; } if ( isInAmbientContext ( node ) ) { return false ; } if ( node . kind === SyntaxKind . Parameter && ! ( < FunctionLikeDeclaration > node . parent ) . body ) { return false ; } return true ; } function checkCollisionWithCapturedThisVariable ( node , name ) { if ( needCollisionCheckForIdentifier ( node , name , "_this" ) ) { potentialThisCollisions . push ( node ) ; } } function checkIfThisIsCapturedInEnclosingScope ( node ) { var current = node ; while ( current ) { if ( getNodeCheckFlags ( current ) & NodeCheckFlags . CaptureThis ) { var isDeclaration = node . kind !== SyntaxKind . Identifier ; if ( isDeclaration ) { error ( ( < Declaration > node ) . name , Diagnostics . Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference ) ; } else { error ( node , Diagnostics . Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference ) ; } return ; } current = current . parent ; } } function checkCollisionWithCapturedSuperVariable ( node , name ) { if ( ! needCollisionCheckForIdentifier ( node , name , "_super" ) ) { return ; } var enclosingClass = < ClassDeclaration > getAncestor ( node , SyntaxKind . ClassDeclaration ) ; if ( ! enclosingClass || isInAmbientContext ( enclosingClass ) ) { return ; } if ( getClassBaseTypeNode ( enclosingClass ) ) { var isDeclaration = node . kind !== SyntaxKind . Identifier ; if ( isDeclaration ) { error ( node , Diagnostics . Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference ) ; } else { error ( node , Diagnostics . Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference ) ; } } } function checkCollisionWithRequireExportsInGeneratedCode ( node , name ) { if ( ! needCollisionCheckForIdentifier ( node , name , "require" ) && ! needCollisionCheckForIdentifier ( node , name , "exports" ) ) { return ; } if ( node . kind === SyntaxKind . ModuleDeclaration && getModuleInstanceState ( node ) !== ModuleInstanceState . Instantiated ) { return ; } var parent = node . kind === SyntaxKind . VariableDeclaration ? node . parent . parent : node . parent ; if ( parent . kind === SyntaxKind . SourceFile && isExternalModule ( < SourceFile > parent ) ) { error ( name , Diagnostics . Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module , declarationNameToString ( name ) , declarationNameToString ( name ) ) ; } } function checkCollisionWithConstDeclarations ( node ) { if ( node . initializer && ( node . flags & NodeFlags . BlockScoped ) === 0 ) { var symbol = getSymbolOfNode ( node ) ; if ( symbol . flags & SymbolFlags . FunctionScopedVariable ) { var localDeclarationSymbol = resolveName ( node , node . name . text , SymbolFlags . Variable , undefined , undefined ) ; if ( localDeclarationSymbol && localDeclarationSymbol !== symbol && localDeclarationSymbol . flags & SymbolFlags . BlockScopedVariable ) { if ( getDeclarationFlagsFromSymbol ( localDeclarationSymbol ) & NodeFlags . Const ) { error ( node , Diagnostics . Cannot_redeclare_block_scoped_variable_0 , symbolToString ( localDeclarationSymbol ) ) ; } } } } } function checkVariableOrParameterOrPropertyInFullTypeCheck ( node ) { Debug . assert ( fullTypeCheck ) ; checkSourceElement ( node . type ) ; if ( hasComputedNameButNotSymbol ( node ) ) { return node . initializer ? checkAndMarkExpression ( node . initializer ) : anyType ; } var symbol = getSymbolOfNode ( node ) ; var type ; if ( symbol . valueDeclaration !== node ) { type = getTypeOfVariableOrParameterOrPropertyDeclaration ( node ) ; } else { type = getTypeOfVariableOrParameterOrProperty ( symbol ) ; } if ( node . initializer && ! ( getNodeLinks ( node . initializer ) . flags & NodeCheckFlags . TypeChecked ) ) { checkTypeAssignableTo ( checkAndMarkExpression ( node . initializer ) , type , node , undefined ) ; } return type ; } function checkVariableOrParameterDeclaration ( node ) { if ( fullTypeCheck ) { var type = checkVariableOrParameterOrPropertyInFullTypeCheck ( node ) ; checkExportsOnMergedDeclarations ( node ) ; if ( node . initializer ) { checkCollisionWithConstDeclarations ( node ) ; } checkCollisionWithCapturedSuperVariable ( node , node . name ) ; checkCollisionWithCapturedThisVariable ( node , node . name ) ; checkCollisionWithRequireExportsInGeneratedCode ( node , node . name ) ; var symbol = getSymbolOfNode ( node ) ; if ( node !== symbol . valueDeclaration ) { var typeOfValueDeclaration = getTypeOfVariableOrParameterOrProperty ( symbol ) ; if ( typeOfValueDeclaration !== unknownType && type !== unknownType && ! isTypeIdenticalTo ( typeOfValueDeclaration , type ) ) { error ( node . name , Diagnostics . Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2 , declarationNameToString ( node . name ) , typeToString ( typeOfValueDeclaration ) , typeToString ( type ) ) ; } } } } function checkVariableStatement ( node ) { forEach ( node . declarations , checkVariableOrParameterDeclaration ) ; } function checkExpressionStatement ( node ) { checkExpression ( node . expression ) ; } function checkIfStatement ( node ) { checkExpression ( node . expression ) ; checkSourceElement ( node . thenStatement ) ; checkSourceElement ( node . elseStatement ) ; } function checkDoStatement ( node ) { checkSourceElement ( node . statement ) ; checkExpression ( node . expression ) ; } function checkWhileStatement ( node ) { checkExpression ( node . expression ) ; checkSourceElement ( node . statement ) ; } function checkForStatement ( node ) { if ( node . declarations ) forEach ( node . declarations , checkVariableOrParameterDeclaration ) ; if ( node . initializer ) checkExpression ( node . initializer ) ; if ( node . condition ) checkExpression ( node . condition ) ; if ( node . iterator ) checkExpression ( node . iterator ) ; checkSourceElement ( node . statement ) ; } function checkForInStatement ( node ) { if ( node . declarations ) { if ( node . declarations . length >= 1 ) { var decl = node . declarations [ 0 ] ; checkVariableOrParameterDeclaration ( decl ) ; if ( decl . type ) { error ( decl , Diagnostics . The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation ) ; } } } if ( node . variable ) { var exprType = checkExpression ( node . variable ) ; if ( exprType !== anyType && exprType !== stringType ) { error ( node . variable , Diagnostics . The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any ) ; } else { checkReferenceExpression ( node . variable , Diagnostics . Invalid_left_hand_side_in_for_in_statement , Diagnostics . Left_hand_side_of_assignment_expression_cannot_be_a_constant ) ; } } var exprType = checkExpression ( node . expression ) ; if ( ! ( exprType . flags & TypeFlags . Any || isStructuredType ( exprType ) ) ) { error ( node . expression , Diagnostics . The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter ) ; } checkSourceElement ( node . statement ) ; } function checkBreakOrContinueStatement ( node ) { } function checkReturnStatement ( node ) { if ( node . expression && ! ( getNodeLinks ( node . expression ) . flags & NodeCheckFlags . TypeChecked ) ) { var func = getContainingFunction ( node ) ; if ( func ) { if ( func . kind === SyntaxKind . SetAccessor ) { if ( node . expression ) { error ( node . expression , Diagnostics . Setters_cannot_return_a_value ) ; } } else { var returnType = getReturnTypeOfSignature ( getSignatureFromDeclaration ( func ) ) ; var checkAssignability = func . type || ( func . kind === SyntaxKind . GetAccessor && getSetAccessorTypeAnnotationNode ( < AccessorDeclaration > getDeclarationOfKind ( func . symbol , SyntaxKind . SetAccessor ) ) ) ; if ( checkAssignability ) { checkTypeAssignableTo ( checkExpression ( node . expression ) , returnType , node . expression , undefined ) ; } else if ( func . kind == SyntaxKind . Constructor ) { if ( ! isTypeAssignableTo ( checkExpression ( node . expression ) , returnType ) ) { error ( node . expression , Diagnostics . Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class ) ; } } } } } } function checkWithStatement ( node ) { checkExpression ( node . expression ) ; error ( node . expression , Diagnostics . All_symbols_within_a_with_block_will_be_resolved_to_any ) ; } function checkSwitchStatement ( node ) { var expressionType = checkExpression ( node . expression ) ; forEach ( node . clauses , clause => { if ( fullTypeCheck && clause . kind === SyntaxKind . CaseClause ) { var caseClause = < CaseClause > clause ; var caseType = checkExpression ( caseClause . expression ) ; if ( ! isTypeAssignableTo ( expressionType , caseType ) ) { checkTypeAssignableTo ( caseType , expressionType , caseClause . expression , undefined ) ; } } forEach ( clause . statements , checkSourceElement ) ; } ) ; } function checkLabeledStatement ( node ) { checkSourceElement ( node . statement ) ; } function checkThrowStatement ( node ) { if ( node . expression ) { checkExpression ( node . expression ) ; } } function checkTryStatement ( node ) { checkBlock ( node . tryBlock ) ; if ( node . catchClause ) checkBlock ( node . catchClause . block ) ; if ( node . finallyBlock ) checkBlock ( node . finallyBlock ) ; } function checkIndexConstraints ( type ) { function checkIndexConstraintForProperty ( prop , propertyType , indexDeclaration , indexType , indexKind ) { if ( ! indexType ) { return ; } if ( indexKind === IndexKind . Number && ! isNumericName ( prop . name ) ) { return ; } var errorNode ; if ( prop . parent === type . symbol ) { errorNode = prop . valueDeclaration ; } else if ( indexDeclaration ) { errorNode = indexDeclaration ; } else if ( type . flags & TypeFlags . Interface ) { var someBaseClassHasBothPropertyAndIndexer = forEach ( ( < InterfaceType > type ) . baseTypes , base => getPropertyOfObjectType ( base , prop . name ) && getIndexTypeOfType ( base , indexKind ) ) ; errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : type . symbol . declarations [ 0 ] ; } if ( errorNode && ! isTypeAssignableTo ( propertyType , indexType ) ) { var errorMessage = indexKind === IndexKind . String ? Diagnostics . Property_0_of_type_1_is_not_assignable_to_string_index_type_2 : Diagnostics . Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2 ; error ( errorNode , errorMessage , symbolToString ( prop ) , typeToString ( propertyType ) , typeToString ( indexType ) ) ; } } var declaredNumberIndexer = getIndexDeclarationOfSymbol ( type . symbol , IndexKind . Number ) ; var declaredStringIndexer = getIndexDeclarationOfSymbol ( type . symbol , IndexKind . String ) ; var stringIndexType = getIndexTypeOfType ( type , IndexKind . String ) ; var numberIndexType = getIndexTypeOfType ( type , IndexKind . Number ) ; if ( stringIndexType || numberIndexType ) { forEach ( getPropertiesOfObjectType ( type ) , prop => { var propType = getTypeOfSymbol ( prop ) ; checkIndexConstraintForProperty ( prop , propType , declaredStringIndexer , stringIndexType , IndexKind . String ) ; checkIndexConstraintForProperty ( prop , propType , declaredNumberIndexer , numberIndexType , IndexKind . Number ) ; } ) ; } var errorNode ; if ( stringIndexType && numberIndexType ) { errorNode = declaredNumberIndexer || declaredStringIndexer ; if ( ! errorNode && ( type . flags & TypeFlags . Interface ) ) { var someBaseTypeHasBothIndexers = forEach ( ( < InterfaceType > type ) . baseTypes , base => getIndexTypeOfType ( base , IndexKind . String ) && getIndexTypeOfType ( base , IndexKind . Number ) ) ; errorNode = someBaseTypeHasBothIndexers ? undefined : type . symbol . declarations [ 0 ] ; } } if ( errorNode && ! isTypeAssignableTo ( numberIndexType , stringIndexType ) ) { error ( errorNode , Diagnostics . Numeric_index_type_0_is_not_assignable_to_string_index_type_1 , typeToString ( numberIndexType ) , typeToString ( stringIndexType ) ) ; } } function checkTypeNameIsReserved ( name , message ) { switch ( ( < Identifier > name ) . text ) { case "any" : case "number" : case "boolean" : case "string" : case "void" : error ( name , message , ( < Identifier > name ) . text ) ; } } function checkTypeParameters ( typeParameterDeclarations ) { if ( typeParameterDeclarations ) { for ( var i = 0 ; i < typeParameterDeclarations . length ; i ++ ) { var node = typeParameterDeclarations [ i ] ; checkTypeParameter ( node ) ; if ( fullTypeCheck ) { for ( var j = 0 ; j < i ; j ++ ) { if ( typeParameterDeclarations [ j ] . symbol === node . symbol ) { error ( node . name , Diagnostics . Duplicate_identifier_0 , declarationNameToString ( node . name ) ) ; } } } } } } function checkClassDeclaration ( node ) { checkTypeNameIsReserved ( node . name , Diagnostics . Class_name_cannot_be_0 ) ; checkTypeParameters ( node . typeParameters ) ; checkCollisionWithCapturedThisVariable ( node , node . name ) ; checkCollisionWithRequireExportsInGeneratedCode ( node , node . name ) ; checkExportsOnMergedDeclarations ( node ) ; var symbol = getSymbolOfNode ( node ) ; var type = < InterfaceType > getDeclaredTypeOfSymbol ( symbol ) ; var staticType = < ObjectType > getTypeOfSymbol ( symbol ) ; var baseTypeNode = getClassBaseTypeNode ( node ) ; if ( baseTypeNode ) { emitExtends = emitExtends || ! isInAmbientContext ( node ) ; checkTypeReference ( baseTypeNode ) ; } if ( type . baseTypes . length ) { if ( fullTypeCheck ) { var baseType = type . baseTypes [ 0 ] ; checkTypeAssignableTo ( type , baseType , node . name , Diagnostics . Class_0_incorrectly_extends_base_class_1 ) ; var staticBaseType = getTypeOfSymbol ( baseType . symbol ) ; checkTypeAssignableTo ( staticType , getTypeWithoutConstructors ( staticBaseType ) , node . name , Diagnostics . Class_static_side_0_incorrectly_extends_base_class_static_side_1 ) ; if ( baseType . symbol !== resolveEntityName ( node , baseTypeNode . typeName , SymbolFlags . Value ) ) { error ( baseTypeNode , Diagnostics . Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0 , typeToString ( baseType ) ) ; } checkKindsOfPropertyMemberOverrides ( type , baseType ) ; } checkExpressionOrQualifiedName ( baseTypeNode . typeName ) ; } var implementedTypeNodes = getClassImplementedTypeNodes ( node ) ; if ( implementedTypeNodes ) { forEach ( implementedTypeNodes , typeRefNode => { checkTypeReference ( typeRefNode ) ; if ( fullTypeCheck ) { var t = getTypeFromTypeReferenceNode ( typeRefNode ) ; if ( t !== unknownType ) { var declaredType = ( t . flags & TypeFlags . Reference ) ? ( < TypeReference > t ) . target : t ; if ( declaredType . flags & ( TypeFlags . Class | TypeFlags . Interface ) ) { checkTypeAssignableTo ( type , t , node . name , Diagnostics . Class_0_incorrectly_implements_interface_1 ) ; } else { error ( typeRefNode , Diagnostics . A_class_may_only_implement_another_class_or_interface ) ; } } } } ) ; } forEach ( node . members , checkSourceElement ) ; if ( fullTypeCheck ) { checkIndexConstraints ( type ) ; checkTypeForDuplicateIndexSignatures ( node ) ; } } function getTargetSymbol ( s ) { return s . flags & SymbolFlags . Instantiated ? getSymbolLinks ( s ) . target : s ; } function checkKindsOfPropertyMemberOverrides ( type , baseType ) { var baseProperties = getPropertiesOfObjectType ( baseType ) ; for ( var i = 0 , len = baseProperties . length ; i < len ; ++ i ) { var base = getTargetSymbol ( baseProperties [ i ] ) ; if ( base . flags & SymbolFlags . Prototype ) { continue ; } var derived = getTargetSymbol ( getPropertyOfObjectType ( type , base . name ) ) ; if ( derived ) { var baseDeclarationFlags = getDeclarationFlagsFromSymbol ( base ) ; var derivedDeclarationFlags = getDeclarationFlagsFromSymbol ( derived ) ; if ( ( baseDeclarationFlags & NodeFlags . Private ) || ( derivedDeclarationFlags & NodeFlags . Private ) ) { continue ; } if ( ( baseDeclarationFlags & NodeFlags . Static ) !== ( derivedDeclarationFlags & NodeFlags . Static ) ) { continue ; } if ( ( base . flags & derived . flags & SymbolFlags . Method ) || ( ( base . flags & SymbolFlags . PropertyOrAccessor ) && ( derived . flags & SymbolFlags . PropertyOrAccessor ) ) ) { continue ; } var errorMessage ; if ( base . flags & SymbolFlags . Method ) { if ( derived . flags & SymbolFlags . Accessor ) { errorMessage = Diagnostics . Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor ; } else { Debug . assert ( ( derived . flags & SymbolFlags . Property ) !== 0 ) ; errorMessage = Diagnostics . Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property ; } } else if ( base . flags & SymbolFlags . Property ) { Debug . assert ( ( derived . flags & SymbolFlags . Method ) !== 0 ) ; errorMessage = Diagnostics . Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function ; } else { Debug . assert ( ( base . flags & SymbolFlags . Accessor ) !== 0 ) ; Debug . assert ( ( derived . flags & SymbolFlags . Method ) !== 0 ) ; errorMessage = Diagnostics . Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function ; } error ( derived . valueDeclaration . name , errorMessage , typeToString ( baseType ) , symbolToString ( base ) , typeToString ( type ) ) ; } } } function isAccessor ( kind ) { return kind === SyntaxKind . GetAccessor || kind === SyntaxKind . SetAccessor ; } function areTypeParametersIdentical ( list1 , list2 ) { if ( ! list1 && ! list2 ) { return true ; } if ( ! list1 || ! list2 || list1 . length !== list2 . length ) { return false ; } for ( var i = 0 , len = list1 . length ; i < len ; i ++ ) { var tp1 = list1 [ i ] ; var tp2 = list2 [ i ] ; if ( tp1 . name . text !== tp2 . name . text ) { return false ; } if ( ! tp1 . constraint && ! tp2 . constraint ) { continue ; } if ( ! tp1 . constraint || ! tp2 . constraint ) { return false ; } if ( ! isTypeIdenticalTo ( getTypeFromTypeNode ( tp1 . constraint ) , getTypeFromTypeNode ( tp2 . constraint ) ) ) { return false ; } } return true ; } function checkInheritedPropertiesAreIdentical ( type , typeNode ) { if ( ! type . baseTypes . length || type . baseTypes . length === 1 ) { return true ; } var seen = { } ; forEach ( type . declaredProperties , p => { seen [ p . name ] = { prop : p , containingType : type } ; } ) ; var ok = true ; for ( var i = 0 , len = type . baseTypes . length ; i < len ; ++ i ) { var base = type . baseTypes [ i ] ; var properties = getPropertiesOfObjectType ( base ) ; for ( var j = 0 , proplen = properties . length ; j < proplen ; ++ j ) { var prop = properties [ j ] ; if ( ! hasProperty ( seen , prop . name ) ) { seen [ prop . name ] = { prop : prop , containingType : base } ; } else { var existing = seen [ prop . name ] ; var isInheritedProperty = existing . containingType !== type ; if ( isInheritedProperty && ! isPropertyIdenticalTo ( existing . prop , prop ) ) { ok = false ; var typeName1 = typeToString ( existing . containingType ) ; var typeName2 = typeToString ( base ) ; var errorInfo = chainDiagnosticMessages ( undefined , Diagnostics . Named_properties_0_of_types_1_and_2_are_not_identical , prop . name , typeName1 , typeName2 ) ; errorInfo = chainDiagnosticMessages ( errorInfo , Diagnostics . Interface_0_cannot_simultaneously_extend_types_1_and_2 , typeToString ( type ) , typeName1 , typeName2 ) ; addDiagnostic ( createDiagnosticForNodeFromMessageChain ( typeNode , errorInfo , program . getCompilerHost ( ) . getNewLine ( ) ) ) ; } } } } return ok ; } function checkInterfaceDeclaration ( node ) { checkTypeParameters ( node . typeParameters ) ; if ( fullTypeCheck ) { checkTypeNameIsReserved ( node . name , Diagnostics . Interface_name_cannot_be_0 ) ; checkExportsOnMergedDeclarations ( node ) ; var symbol = getSymbolOfNode ( node ) ; var firstInterfaceDecl = < InterfaceDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . InterfaceDeclaration ) ; if ( symbol . declarations . length > 1 ) { if ( node !== firstInterfaceDecl && ! areTypeParametersIdentical ( firstInterfaceDecl . typeParameters , node . typeParameters ) ) { error ( node . name , Diagnostics . All_declarations_of_an_interface_must_have_identical_type_parameters ) ; } } if ( node === firstInterfaceDecl ) { var type = < InterfaceType > getDeclaredTypeOfSymbol ( symbol ) ; if ( checkInheritedPropertiesAreIdentical ( type , node . name ) ) { forEach ( type . baseTypes , baseType => { checkTypeAssignableTo ( type , baseType , node . name , Diagnostics . Interface_0_incorrectly_extends_interface_1 ) ; } ) ; checkIndexConstraints ( type ) ; } } } forEach ( getInterfaceBaseTypeNodes ( node ) , checkTypeReference ) ; forEach ( node . members , checkSourceElement ) ; if ( fullTypeCheck ) { checkTypeForDuplicateIndexSignatures ( node ) ; } } function checkTypeAliasDeclaration ( node ) { checkTypeNameIsReserved ( node . name , Diagnostics . Type_alias_name_cannot_be_0 ) ; checkSourceElement ( node . type ) ; } function computeEnumMemberValues ( node ) { var nodeLinks = getNodeLinks ( node ) ; if ( ! ( nodeLinks . flags & NodeCheckFlags . EnumValuesComputed ) ) { var enumSymbol = getSymbolOfNode ( node ) ; var enumType = getDeclaredTypeOfSymbol ( enumSymbol ) ; var autoValue = 0 ; var ambient = isInAmbientContext ( node ) ; var enumIsConst = isConst ( node ) ; forEach ( node . members , member => { if ( isNumericName ( ( < Identifier > member . name ) . text ) ) { error ( member . name , Diagnostics . An_enum_member_cannot_have_a_numeric_name ) ; } var initializer = member . initializer ; if ( initializer ) { autoValue = getConstantValueForEnumMemberInitializer ( initializer , enumIsConst ) ; if ( autoValue === undefined ) { if ( enumIsConst ) { error ( initializer , Diagnostics . In_const_enum_declarations_member_initializer_must_be_constant_expression ) ; } else if ( ! ambient ) { checkTypeAssignableTo ( checkExpression ( initializer ) , enumType , initializer , undefined ) ; } } else if ( enumIsConst ) { if ( isNaN ( autoValue ) ) { error ( initializer , Diagnostics . const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN ) ; } else if ( ! isFinite ( autoValue ) ) { error ( initializer , Diagnostics . const_enum_member_initializer_was_evaluated_to_a_non_finite_value ) ; } } } else if ( ambient && ! enumIsConst ) { autoValue = undefined ; } if ( autoValue !== undefined ) { getNodeLinks ( member ) . enumMemberValue = autoValue ++ ; } } ) ; nodeLinks . flags |= NodeCheckFlags . EnumValuesComputed ; } function getConstantValueForEnumMemberInitializer ( initializer , enumIsConst ) { return evalConstant ( initializer ) ; function evalConstant ( e ) { switch ( e . kind ) { case SyntaxKind . PrefixUnaryExpression : var value = evalConstant ( ( < PrefixUnaryExpression > e ) . operand ) ; if ( value === undefined ) { return undefined ; } switch ( ( < PrefixUnaryExpression > e ) . operator ) { case SyntaxKind . PlusToken : return value ; case SyntaxKind . MinusToken : return - value ; case SyntaxKind . TildeToken : return enumIsConst ? ~ value : undefined ; } return undefined ; case SyntaxKind . BinaryExpression : if ( ! enumIsConst ) { return undefined ; } var left = evalConstant ( ( < BinaryExpression > e ) . left ) ; if ( left === undefined ) { return undefined ; } var right = evalConstant ( ( < BinaryExpression > e ) . right ) ; if ( right === undefined ) { return undefined ; } switch ( ( < BinaryExpression > e ) . operator ) { case SyntaxKind . BarToken : return left | right ; case SyntaxKind . AmpersandToken : return left & right ; case SyntaxKind . GreaterThanGreaterThanToken : return left >> right ; case SyntaxKind . GreaterThanGreaterThanGreaterThanToken : return left >>> right ; case SyntaxKind . LessThanLessThanToken : return left << right ; case SyntaxKind . CaretToken : return left ^ right ; case SyntaxKind . AsteriskToken : return left * right ; case SyntaxKind . SlashToken : return left / right ; case SyntaxKind . PlusToken : return left + right ; case SyntaxKind . MinusToken : return left - right ; case SyntaxKind . PercentToken : return left % right ; } return undefined ; case SyntaxKind . NumericLiteral : return + ( < LiteralExpression > e ) . text ; case SyntaxKind . ParenthesizedExpression : return enumIsConst ? evalConstant ( ( < ParenthesizedExpression > e ) . expression ) : undefined ; case SyntaxKind . Identifier : case SyntaxKind . ElementAccessExpression : case SyntaxKind . PropertyAccessExpression : if ( ! enumIsConst ) { return undefined ; } var member = initializer . parent ; var currentType = getTypeOfSymbol ( getSymbolOfNode ( member . parent ) ) ; var enumType ; var propertyName ; if ( e . kind === SyntaxKind . Identifier ) { enumType = currentType ; propertyName = ( < Identifier > e ) . text ; } else { if ( e . kind === SyntaxKind . ElementAccessExpression ) { if ( ( < ElementAccessExpression > e ) . argumentExpression === undefined || ( < ElementAccessExpression > e ) . argumentExpression . kind !== SyntaxKind . StringLiteral ) { return undefined ; } var enumType = getTypeOfNode ( ( < ElementAccessExpression > e ) . expression ) ; propertyName = ( < LiteralExpression > ( < ElementAccessExpression > e ) . argumentExpression ) . text ; } else { var enumType = getTypeOfNode ( ( < PropertyAccessExpression > e ) . expression ) ; propertyName = ( < PropertyAccessExpression > e ) . name . text ; } if ( enumType !== currentType ) { return undefined ; } } if ( propertyName === undefined ) { return undefined ; } var property = getPropertyOfObjectType ( enumType , propertyName ) ; if ( ! property || ! ( property . flags & SymbolFlags . EnumMember ) ) { return undefined ; } var propertyDecl = property . valueDeclaration ; if ( member === propertyDecl ) { return undefined ; } if ( ! isDefinedBefore ( propertyDecl , member ) ) { return undefined ; } return < number > getNodeLinks ( propertyDecl ) . enumMemberValue ; } } } } function checkEnumDeclaration ( node ) { if ( ! fullTypeCheck ) { return ; } checkTypeNameIsReserved ( node . name , Diagnostics . Enum_name_cannot_be_0 ) ; checkCollisionWithCapturedThisVariable ( node , node . name ) ; checkCollisionWithRequireExportsInGeneratedCode ( node , node . name ) ; checkExportsOnMergedDeclarations ( node ) ; computeEnumMemberValues ( node ) ; var enumSymbol = getSymbolOfNode ( node ) ; var firstDeclaration = getDeclarationOfKind ( enumSymbol , node . kind ) ; if ( node === firstDeclaration ) { if ( enumSymbol . declarations . length > 1 ) { var enumIsConst = isConst ( node ) ; forEach ( enumSymbol . declarations , decl => { if ( isConstEnumDeclaration ( decl ) !== enumIsConst ) { error ( decl . name , Diagnostics . Enum_declarations_must_all_be_const_or_non_const ) ; } } ) ; } var seenEnumMissingInitialInitializer = false ; forEach ( enumSymbol . declarations , declaration => { if ( declaration . kind !== SyntaxKind . EnumDeclaration ) { return false ; } var enumDeclaration = < EnumDeclaration > declaration ; if ( ! enumDeclaration . members . length ) { return false ; } var firstEnumMember = enumDeclaration . members [ 0 ] ; if ( ! firstEnumMember . initializer ) { if ( seenEnumMissingInitialInitializer ) { error ( firstEnumMember . name , Diagnostics . In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element ) ; } else { seenEnumMissingInitialInitializer = true ; } } } ) ; } } function getFirstNonAmbientClassOrFunctionDeclaration ( symbol ) { var declarations = symbol . declarations ; for ( var i = 0 ; i < declarations . length ; i ++ ) { var declaration = declarations [ i ] ; if ( ( declaration . kind === SyntaxKind . ClassDeclaration || ( declaration . kind === SyntaxKind . FunctionDeclaration && ( < FunctionLikeDeclaration > declaration ) . body ) ) && ! isInAmbientContext ( declaration ) ) { return declaration ; } } return undefined ; } function checkModuleDeclaration ( node ) { if ( fullTypeCheck ) { checkCollisionWithCapturedThisVariable ( node , node . name ) ; checkCollisionWithRequireExportsInGeneratedCode ( node , node . name ) ; checkExportsOnMergedDeclarations ( node ) ; var symbol = getSymbolOfNode ( node ) ; if ( symbol . flags & SymbolFlags . ValueModule && symbol . declarations . length > 1 && ! isInAmbientContext ( node ) ) { var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration ( symbol ) ; if ( classOrFunc ) { if ( getSourceFileOfNode ( node ) !== getSourceFileOfNode ( classOrFunc ) ) { error ( node . name , Diagnostics . A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged ) ; } else if ( node . pos < classOrFunc . pos ) { error ( node . name , Diagnostics . A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged ) ; } } } if ( node . name . kind === SyntaxKind . StringLiteral ) { if ( ! isGlobalSourceFile ( node . parent ) ) { error ( node . name , Diagnostics . Ambient_external_modules_cannot_be_nested_in_other_modules ) ; } if ( isExternalModuleNameRelative ( node . name . text ) ) { error ( node . name , Diagnostics . Ambient_external_module_declaration_cannot_specify_relative_module_name ) ; } } } checkSourceElement ( node . body ) ; } function getFirstIdentifier ( node ) { while ( node . kind === SyntaxKind . QualifiedName ) { node = ( < QualifiedName > node ) . left ; } return < Identifier > node ; } function checkImportDeclaration ( node ) { checkCollisionWithCapturedThisVariable ( node , node . name ) ; checkCollisionWithRequireExportsInGeneratedCode ( node , node . name ) ; var symbol = getSymbolOfNode ( node ) ; var target ; if ( isInternalModuleImportDeclaration ( node ) ) { target = resolveImport ( symbol ) ; if ( target !== unknownSymbol ) { if ( target . flags & SymbolFlags . Value ) { var moduleName = getFirstIdentifier ( < EntityName > node . moduleReference ) ; if ( resolveEntityName ( node , moduleName , SymbolFlags . Value | SymbolFlags . Namespace ) . flags & SymbolFlags . Namespace ) { checkExpressionOrQualifiedName ( < EntityName > node . moduleReference ) ; } else { error ( moduleName , Diagnostics . Module_0_is_hidden_by_a_local_declaration_with_the_same_name , declarationNameToString ( moduleName ) ) ; } } if ( target . flags & SymbolFlags . Type ) { checkTypeNameIsReserved ( node . name , Diagnostics . Import_name_cannot_be_0 ) ; } } } else { if ( node . parent . kind === SyntaxKind . SourceFile ) { target = resolveImport ( symbol ) ; } else if ( node . parent . kind === SyntaxKind . ModuleBlock && ( < ModuleDeclaration > node . parent . parent ) . name . kind === SyntaxKind . StringLiteral ) { if ( getExternalModuleImportDeclarationExpression ( node ) . kind === SyntaxKind . StringLiteral ) { if ( isExternalModuleNameRelative ( ( < LiteralExpression > getExternalModuleImportDeclarationExpression ( node ) ) . text ) ) { error ( node , Diagnostics . Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name ) ; target = unknownSymbol ; } else { target = resolveImport ( symbol ) ; } } else { target = unknownSymbol ; } } else { target = unknownSymbol ; } } if ( target !== unknownSymbol ) { var excludedMeanings = ( symbol . flags & SymbolFlags . Value ? SymbolFlags . Value : 0 ) | ( symbol . flags & SymbolFlags . Type ? SymbolFlags . Type : 0 ) | ( symbol . flags & SymbolFlags . Namespace ? SymbolFlags . Namespace : 0 ) ; if ( target . flags & excludedMeanings ) { error ( node , Diagnostics . Import_declaration_conflicts_with_local_declaration_of_0 , symbolToString ( symbol ) ) ; } } } function checkExportAssignment ( node ) { var container = node . parent ; if ( container . kind !== SyntaxKind . SourceFile ) { container = container . parent ; } checkTypeOfExportAssignmentSymbol ( getSymbolOfNode ( container ) ) ; } function checkSourceElement ( node ) { if ( ! node ) return ; switch ( node . kind ) { case SyntaxKind . TypeParameter : return checkTypeParameter ( < TypeParameterDeclaration > node ) ; case SyntaxKind . Parameter : return checkParameter ( < ParameterDeclaration > node ) ; case SyntaxKind . Property : return checkPropertyDeclaration ( < PropertyDeclaration > node ) ; case SyntaxKind . FunctionType : case SyntaxKind . ConstructorType : case SyntaxKind . CallSignature : case SyntaxKind . ConstructSignature : case SyntaxKind . IndexSignature : return checkSignatureDeclaration ( < SignatureDeclaration > node ) ; case SyntaxKind . Method : return checkMethodDeclaration ( < MethodDeclaration > node ) ; case SyntaxKind . Constructor : return checkConstructorDeclaration ( < ConstructorDeclaration > node ) ; case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : return checkAccessorDeclaration ( < AccessorDeclaration > node ) ; case SyntaxKind . TypeReference : return checkTypeReference ( < TypeReferenceNode > node ) ; case SyntaxKind . TypeQuery : return checkTypeQuery ( < TypeQueryNode > node ) ; case SyntaxKind . TypeLiteral : return checkTypeLiteral ( < TypeLiteralNode > node ) ; case SyntaxKind . ArrayType : return checkArrayType ( < ArrayTypeNode > node ) ; case SyntaxKind . TupleType : return checkTupleType ( < TupleTypeNode > node ) ; case SyntaxKind . UnionType : return checkUnionType ( < UnionTypeNode > node ) ; case SyntaxKind . ParenthesizedType : return checkSourceElement ( ( < ParenthesizedTypeNode > node ) . type ) ; case SyntaxKind . FunctionDeclaration : return checkFunctionDeclaration ( < FunctionDeclaration > node ) ; case SyntaxKind . Block : case SyntaxKind . ModuleBlock : return checkBlock ( < Block > node ) ; case SyntaxKind . VariableStatement : return checkVariableStatement ( < VariableStatement > node ) ; case SyntaxKind . ExpressionStatement : return checkExpressionStatement ( < ExpressionStatement > node ) ; case SyntaxKind . IfStatement : return checkIfStatement ( < IfStatement > node ) ; case SyntaxKind . DoStatement : return checkDoStatement ( < DoStatement > node ) ; case SyntaxKind . WhileStatement : return checkWhileStatement ( < WhileStatement > node ) ; case SyntaxKind . ForStatement : return checkForStatement ( < ForStatement > node ) ; case SyntaxKind . ForInStatement : return checkForInStatement ( < ForInStatement > node ) ; case SyntaxKind . ContinueStatement : case SyntaxKind . BreakStatement : return checkBreakOrContinueStatement ( < BreakOrContinueStatement > node ) ; case SyntaxKind . ReturnStatement : return checkReturnStatement ( < ReturnStatement > node ) ; case SyntaxKind . WithStatement : return checkWithStatement ( < WithStatement > node ) ; case SyntaxKind . SwitchStatement : return checkSwitchStatement ( < SwitchStatement > node ) ; case SyntaxKind . LabeledStatement : return checkLabeledStatement ( < LabeledStatement > node ) ; case SyntaxKind . ThrowStatement : return checkThrowStatement ( < ThrowStatement > node ) ; case SyntaxKind . TryStatement : return checkTryStatement ( < TryStatement > node ) ; case SyntaxKind . VariableDeclaration : return Debug . fail ( "Checker encountered variable declaration" ) ; case SyntaxKind . ClassDeclaration : return checkClassDeclaration ( < ClassDeclaration > node ) ; case SyntaxKind . InterfaceDeclaration : return checkInterfaceDeclaration ( < InterfaceDeclaration > node ) ; case SyntaxKind . TypeAliasDeclaration : return checkTypeAliasDeclaration ( < TypeAliasDeclaration > node ) ; case SyntaxKind . EnumDeclaration : return checkEnumDeclaration ( < EnumDeclaration > node ) ; case SyntaxKind . ModuleDeclaration : return checkModuleDeclaration ( < ModuleDeclaration > node ) ; case SyntaxKind . ImportDeclaration : return checkImportDeclaration ( < ImportDeclaration > node ) ; case SyntaxKind . ExportAssignment : return checkExportAssignment ( < ExportAssignment > node ) ; } } function checkFunctionExpressionBodies ( node ) { switch ( node . kind ) { case SyntaxKind . FunctionExpression : case SyntaxKind . ArrowFunction : forEach ( ( < FunctionLikeDeclaration > node ) . parameters , checkFunctionExpressionBodies ) ; checkFunctionExpressionOrObjectLiteralMethodBody ( < FunctionExpression > node ) ; break ; case SyntaxKind . Method : forEach ( ( < MethodDeclaration > node ) . parameters , checkFunctionExpressionBodies ) ; if ( isObjectLiteralMethod ( node ) ) { checkFunctionExpressionOrObjectLiteralMethodBody ( < MethodDeclaration > node ) ; } break ; case SyntaxKind . Constructor : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : case SyntaxKind . FunctionDeclaration : forEach ( ( < FunctionLikeDeclaration > node ) . parameters , checkFunctionExpressionBodies ) ; break ; case SyntaxKind . WithStatement : checkFunctionExpressionBodies ( ( < WithStatement > node ) . expression ) ; break ; case SyntaxKind . Parameter : case SyntaxKind . Property : case SyntaxKind . ArrayLiteralExpression : case SyntaxKind . ObjectLiteralExpression : case SyntaxKind . PropertyAssignment : case SyntaxKind . PropertyAccessExpression : case SyntaxKind . ElementAccessExpression : case SyntaxKind . CallExpression : case SyntaxKind . NewExpression : case SyntaxKind . TaggedTemplateExpression : case SyntaxKind . TemplateExpression : case SyntaxKind . TemplateSpan : case SyntaxKind . TypeAssertionExpression : case SyntaxKind . ParenthesizedExpression : case SyntaxKind . TypeOfExpression : case SyntaxKind . VoidExpression : case SyntaxKind . DeleteExpression : case SyntaxKind . PrefixUnaryExpression : case SyntaxKind . PostfixUnaryExpression : case SyntaxKind . BinaryExpression : case SyntaxKind . ConditionalExpression : case SyntaxKind . Block : case SyntaxKind . ModuleBlock : case SyntaxKind . VariableStatement : case SyntaxKind . ExpressionStatement : case SyntaxKind . IfStatement : case SyntaxKind . DoStatement : case SyntaxKind . WhileStatement : case SyntaxKind . ForStatement : case SyntaxKind . ForInStatement : case SyntaxKind . ContinueStatement : case SyntaxKind . BreakStatement : case SyntaxKind . ReturnStatement : case SyntaxKind . SwitchStatement : case SyntaxKind . CaseClause : case SyntaxKind . DefaultClause : case SyntaxKind . LabeledStatement : case SyntaxKind . ThrowStatement : case SyntaxKind . TryStatement : case SyntaxKind . TryBlock : case SyntaxKind . CatchClause : case SyntaxKind . FinallyBlock : case SyntaxKind . VariableDeclaration : case SyntaxKind . ClassDeclaration : case SyntaxKind . EnumDeclaration : case SyntaxKind . EnumMember : case SyntaxKind . SourceFile : forEachChild ( node , checkFunctionExpressionBodies ) ; break ; } } function checkSourceFile ( node ) { var links = getNodeLinks ( node ) ; if ( ! ( links . flags & NodeCheckFlags . TypeChecked ) ) { emitExtends = false ; potentialThisCollisions . length = 0 ; forEach ( node . statements , checkSourceElement ) ; checkFunctionExpressionBodies ( node ) ; if ( isExternalModule ( node ) ) { var symbol = getExportAssignmentSymbol ( node . symbol ) ; if ( symbol && symbol . flags & SymbolFlags . Import ) { getSymbolLinks ( symbol ) . referenced = true ; } } if ( potentialThisCollisions . length ) { forEach ( potentialThisCollisions , checkIfThisIsCapturedInEnclosingScope ) ; potentialThisCollisions . length = 0 ; } if ( emitExtends ) { links . flags |= NodeCheckFlags . EmitExtends ; } links . flags |= NodeCheckFlags . TypeChecked ; } } function getSortedDiagnostics ( ) { Debug . assert ( fullTypeCheck , "diagnostics are available only in the full typecheck mode" ) ; if ( diagnosticsModified ) { diagnostics . sort ( compareDiagnostics ) ; diagnostics = deduplicateSortedDiagnostics ( diagnostics ) ; diagnosticsModified = false ; } return diagnostics ; } function getDiagnostics ( sourceFile ? ) { if ( sourceFile ) { checkSourceFile ( sourceFile ) ; return filter ( getSortedDiagnostics ( ) , d => d . file === sourceFile ) ; } forEach ( program . getSourceFiles ( ) , checkSourceFile ) ; return getSortedDiagnostics ( ) ; } function getDeclarationDiagnostics ( targetSourceFile ) { var resolver = createResolver ( ) ; checkSourceFile ( targetSourceFile ) ; return ts . getDeclarationDiagnostics ( program , resolver , targetSourceFile ) ; } function getGlobalDiagnostics ( ) { return filter ( getSortedDiagnostics ( ) , d => ! d . file ) ; } function isInsideWithStatementBody ( node ) { if ( node ) { while ( node . parent ) { if ( node . parent . kind === SyntaxKind . WithStatement && ( < WithStatement > node . parent ) . statement === node ) { return true ; } node = node . parent ; } } return false ; } function getSymbolsInScope ( location , meaning ) { var symbols = { } ; var memberFlags = 0 ; function copySymbol ( symbol , meaning ) { if ( symbol . flags & meaning ) { var id = symbol . name ; if ( ! isReservedMemberName ( id ) && ! hasProperty ( symbols , id ) ) { symbols [ id ] = symbol ; } } } function copySymbols ( source , meaning ) { if ( meaning ) { for ( var id in source ) { if ( hasProperty ( source , id ) ) { copySymbol ( source [ id ] , meaning ) ; } } } } if ( isInsideWithStatementBody ( location ) ) { return [ ] ; } while ( location ) { if ( location . locals && ! isGlobalSourceFile ( location ) ) { copySymbols ( location . locals , meaning ) ; } switch ( location . kind ) { case SyntaxKind . SourceFile : if ( ! isExternalModule ( < SourceFile > location ) ) break ; case SyntaxKind . ModuleDeclaration : copySymbols ( getSymbolOfNode ( location ) . exports , meaning & SymbolFlags . ModuleMember ) ; break ; case SyntaxKind . EnumDeclaration : copySymbols ( getSymbolOfNode ( location ) . exports , meaning & SymbolFlags . EnumMember ) ; break ; case SyntaxKind . ClassDeclaration : case SyntaxKind . InterfaceDeclaration : if ( ! ( memberFlags & NodeFlags . Static ) ) { copySymbols ( getSymbolOfNode ( location ) . members , meaning & SymbolFlags . Type ) ; } break ; case SyntaxKind . FunctionExpression : if ( ( < FunctionExpression > location ) . name ) { copySymbol ( location . symbol , meaning ) ; } break ; case SyntaxKind . CatchClause : if ( ( < CatchClause > location ) . name . text ) { copySymbol ( location . symbol , meaning ) ; } break ; } memberFlags = location . flags ; location = location . parent ; } copySymbols ( globals , meaning ) ; return mapToArray ( symbols ) ; } function isTypeDeclarationName ( name ) { return name . kind == SyntaxKind . Identifier && isTypeDeclaration ( name . parent ) && ( < Declaration > name . parent ) . name === name ; } function isTypeDeclaration ( node ) { switch ( node . kind ) { case SyntaxKind . TypeParameter : case SyntaxKind . ClassDeclaration : case SyntaxKind . InterfaceDeclaration : case SyntaxKind . TypeAliasDeclaration : case SyntaxKind . EnumDeclaration : return true ; } } function isTypeReferenceIdentifier ( entityName ) { var node = entityName ; while ( node . parent && node . parent . kind === SyntaxKind . QualifiedName ) node = node . parent ; return node . parent && node . parent . kind === SyntaxKind . TypeReference ; } function isTypeNode ( node ) { if ( SyntaxKind . FirstTypeNode <= node . kind && node . kind <= SyntaxKind . LastTypeNode ) { return true ; } switch ( node . kind ) { case SyntaxKind . AnyKeyword : case SyntaxKind . NumberKeyword : case SyntaxKind . StringKeyword : case SyntaxKind . BooleanKeyword : return true ; case SyntaxKind . VoidKeyword : return node . parent . kind !== SyntaxKind . VoidExpression ; case SyntaxKind . StringLiteral : return node . parent . kind === SyntaxKind . Parameter ; case SyntaxKind . Identifier : if ( node . parent . kind === SyntaxKind . QualifiedName && ( < QualifiedName > node . parent ) . right === node ) { node = node . parent ; } case SyntaxKind . QualifiedName : Debug . assert ( node . kind === SyntaxKind . Identifier || node . kind === SyntaxKind . QualifiedName , "'node' was expected to be a qualified name or identifier in 'isTypeNode'." ) ; var parent = node . parent ; if ( parent . kind === SyntaxKind . TypeQuery ) { return false ; } if ( SyntaxKind . FirstTypeNode <= parent . kind && parent . kind <= SyntaxKind . LastTypeNode ) { return true ; } switch ( parent . kind ) { case SyntaxKind . TypeParameter : return node === ( < TypeParameterDeclaration > parent ) . constraint ; case SyntaxKind . Property : case SyntaxKind . Parameter : case SyntaxKind . VariableDeclaration : return node === ( < VariableDeclaration > parent ) . type ; case SyntaxKind . FunctionDeclaration : case SyntaxKind . FunctionExpression : case SyntaxKind . ArrowFunction : case SyntaxKind . Constructor : case SyntaxKind . Method : case SyntaxKind . GetAccessor : case SyntaxKind . SetAccessor : return node === ( < FunctionLikeDeclaration > parent ) . type ; case SyntaxKind . CallSignature : case SyntaxKind . ConstructSignature : case SyntaxKind . IndexSignature : return node === ( < SignatureDeclaration > parent ) . type ; case SyntaxKind . TypeAssertionExpression : return node === ( < TypeAssertion > parent ) . type ; case SyntaxKind . CallExpression : case SyntaxKind . NewExpression : return ( < CallExpression > parent ) . typeArguments && indexOf ( ( < CallExpression > parent ) . typeArguments , node ) >= 0 ; case SyntaxKind . TaggedTemplateExpression : return false ; } } return false ; } function isInRightSideOfImportOrExportAssignment ( node ) { while ( node . parent . kind === SyntaxKind . QualifiedName ) { node = < QualifiedName > node . parent ; } if ( node . parent . kind === SyntaxKind . ImportDeclaration ) { return ( < ImportDeclaration > node . parent ) . moduleReference === node ; } if ( node . parent . kind === SyntaxKind . ExportAssignment ) { return ( < ExportAssignment > node . parent ) . exportName === node ; } return false ; } function isRightSideOfQualifiedNameOrPropertyAccess ( node ) { return ( node . parent . kind === SyntaxKind . QualifiedName && ( < QualifiedName > node . parent ) . right === node ) || ( node . parent . kind === SyntaxKind . PropertyAccessExpression && ( < PropertyAccessExpression > node . parent ) . name === node ) ; } function getSymbolOfEntityNameOrPropertyAccessExpression ( entityName ) { if ( isDeclarationOrFunctionExpressionOrCatchVariableName ( entityName ) ) { return getSymbolOfNode ( entityName . parent ) ; } if ( entityName . parent . kind === SyntaxKind . ExportAssignment ) { return resolveEntityName ( entityName . parent . parent , < Identifier > entityName , SymbolFlags . Value | SymbolFlags . Type | SymbolFlags . Namespace | SymbolFlags . Import ) ; } if ( entityName . kind !== SyntaxKind . PropertyAccessExpression ) { if ( isInRightSideOfImportOrExportAssignment ( < EntityName > entityName ) ) { return getSymbolOfPartOfRightHandSideOfImport ( < EntityName > entityName ) ; } } if ( isRightSideOfQualifiedNameOrPropertyAccess ( entityName ) ) { entityName = < QualifiedName | PropertyAccessExpression > entityName . parent ; } if ( isExpression ( entityName ) ) { if ( getFullWidth ( entityName ) === 0 ) { return undefined ; } if ( entityName . kind === SyntaxKind . Identifier ) { var meaning = SymbolFlags . Value | SymbolFlags . Import ; return resolveEntityName ( entityName , < Identifier > entityName , meaning ) ; } else if ( entityName . kind === SyntaxKind . PropertyAccessExpression ) { var symbol = getNodeLinks ( entityName ) . resolvedSymbol ; if ( ! symbol ) { checkPropertyAccessExpression ( < PropertyAccessExpression > entityName ) ; } return getNodeLinks ( entityName ) . resolvedSymbol ; } else if ( entityName . kind === SyntaxKind . QualifiedName ) { var symbol = getNodeLinks ( entityName ) . resolvedSymbol ; if ( ! symbol ) { checkQualifiedName ( < QualifiedName > entityName ) ; } return getNodeLinks ( entityName ) . resolvedSymbol ; } } else if ( isTypeReferenceIdentifier ( < EntityName > entityName ) ) { var meaning = entityName . parent . kind === SyntaxKind . TypeReference ? SymbolFlags . Type : SymbolFlags . Namespace ; meaning |= SymbolFlags . Import ; return resolveEntityName ( entityName , < EntityName > entityName , meaning ) ; } return undefined ; } function getSymbolInfo ( node ) { if ( isInsideWithStatementBody ( node ) ) { return undefined ; } if ( isDeclarationOrFunctionExpressionOrCatchVariableName ( node ) ) { return getSymbolOfNode ( node . parent ) ; } if ( node . kind === SyntaxKind . Identifier && isInRightSideOfImportOrExportAssignment ( < Identifier > node ) ) { return node . parent . kind === SyntaxKind . ExportAssignment ? getSymbolOfEntityNameOrPropertyAccessExpression ( < Identifier > node ) : getSymbolOfPartOfRightHandSideOfImport ( < Identifier > node ) ; } switch ( node . kind ) { case SyntaxKind . Identifier : case SyntaxKind . PropertyAccessExpression : case SyntaxKind . QualifiedName : return getSymbolOfEntityNameOrPropertyAccessExpression ( < EntityName | PropertyAccessExpression > node ) ; case SyntaxKind . ThisKeyword : case SyntaxKind . SuperKeyword : var type = checkExpression ( < Expression > node ) ; return type . symbol ; case SyntaxKind . ConstructorKeyword : var constructorDeclaration = node . parent ; if ( constructorDeclaration && constructorDeclaration . kind === SyntaxKind . Constructor ) { return ( < ClassDeclaration > constructorDeclaration . parent ) . symbol ; } return undefined ; case SyntaxKind . StringLiteral : if ( isExternalModuleImportDeclaration ( node . parent . parent ) && getExternalModuleImportDeclarationExpression ( node . parent . parent ) === node ) { var importSymbol = getSymbolOfNode ( node . parent . parent ) ; var moduleType = getTypeOfSymbol ( importSymbol ) ; return moduleType ? moduleType . symbol : undefined ; } case SyntaxKind . NumericLiteral : if ( node . parent . kind == SyntaxKind . ElementAccessExpression && ( < ElementAccessExpression > node . parent ) . argumentExpression === node ) { var objectType = checkExpression ( ( < ElementAccessExpression > node . parent ) . expression ) ; if ( objectType === unknownType ) return undefined ; var apparentType = getApparentType ( objectType ) ; if ( apparentType === unknownType ) return undefined ; return getPropertyOfType ( apparentType , ( < LiteralExpression > node ) . text ) ; } break ; } return undefined ; } function getShorthandAssignmentValueSymbol ( location ) { if ( location && location . kind === SyntaxKind . ShorthandPropertyAssignment ) { return resolveEntityName ( location , ( < ShorthandPropertyAssignment > location ) . name , SymbolFlags . Value ) ; } return undefined ; } function getTypeOfNode ( node ) { if ( isInsideWithStatementBody ( node ) ) { return unknownType ; } if ( isExpression ( node ) ) { return getTypeOfExpression ( < Expression > node ) ; } if ( isTypeNode ( node ) ) { return getTypeFromTypeNode ( < TypeNode > node ) ; } if ( isTypeDeclaration ( node ) ) { var symbol = getSymbolOfNode ( node ) ; return getDeclaredTypeOfSymbol ( symbol ) ; } if ( isTypeDeclarationName ( node ) ) { var symbol = getSymbolInfo ( node ) ; return symbol && getDeclaredTypeOfSymbol ( symbol ) ; } if ( isDeclaration ( node ) ) { var symbol = getSymbolOfNode ( node ) ; return getTypeOfSymbol ( symbol ) ; } if ( isDeclarationOrFunctionExpressionOrCatchVariableName ( node ) ) { var symbol = getSymbolInfo ( node ) ; return symbol && getTypeOfSymbol ( symbol ) ; } if ( isInRightSideOfImportOrExportAssignment ( < Identifier > node ) ) { var symbol = getSymbolInfo ( node ) ; var declaredType = symbol && getDeclaredTypeOfSymbol ( symbol ) ; return declaredType !== unknownType ? declaredType : getTypeOfSymbol ( symbol ) ; } return unknownType ; } function getTypeOfExpression ( expr ) { if ( isRightSideOfQualifiedNameOrPropertyAccess ( expr ) ) { expr = < Expression > expr . parent ; } return checkExpression ( expr ) ; } function getAugmentedPropertiesOfType ( type ) { var type = getApparentType ( type ) ; var propsByName = createSymbolTable ( getPropertiesOfType ( type ) ) ; if ( getSignaturesOfType ( type , SignatureKind . Call ) . length || getSignaturesOfType ( type , SignatureKind . Construct ) . length ) { forEach ( getPropertiesOfType ( globalFunctionType ) , p => { if ( ! hasProperty ( propsByName , p . name ) ) { propsByName [ p . name ] = p ; } } ) ; } return getNamedMembers ( propsByName ) ; } function getRootSymbols ( symbol ) { if ( symbol . flags & SymbolFlags . UnionProperty ) { var symbols = [ ] ; var name = symbol . name ; forEach ( getSymbolLinks ( symbol ) . unionType . types , t => { symbols . push ( getPropertyOfType ( t , name ) ) ; } ) ; return symbols ; } else if ( symbol . flags & SymbolFlags . Transient ) { var target = getSymbolLinks ( symbol ) . target ; if ( target ) { return [ target ] ; } } return [ symbol ] ; } function isExternalModuleSymbol ( symbol ) { return symbol . flags & SymbolFlags . ValueModule && symbol . declarations . length === 1 && symbol . declarations [ 0 ] . kind === SyntaxKind . SourceFile ; } function isNodeDescendentOf ( node , ancestor ) { while ( node ) { if ( node === ancestor ) return true ; node = node . parent ; } return false ; } function isUniqueLocalName ( name , container ) { for ( var node = container ; isNodeDescendentOf ( node , container ) ; node = node . nextContainer ) { if ( node . locals && hasProperty ( node . locals , name ) ) { var symbolWithRelevantName = node . locals [ name ] ; if ( symbolWithRelevantName . flags & ( SymbolFlags . Value | SymbolFlags . ExportValue ) ) { return false ; } if ( symbolWithRelevantName . flags & SymbolFlags . Import ) { var importDeclarationWithRelevantName = < ImportDeclaration > getDeclarationOfKind ( symbolWithRelevantName , SyntaxKind . ImportDeclaration ) ; if ( isReferencedImportDeclaration ( importDeclarationWithRelevantName ) ) { return false ; } } } } return true ; } function getLocalNameOfContainer ( container ) { var links = getNodeLinks ( container ) ; if ( ! links . localModuleName ) { var prefix = "" ; var name = unescapeIdentifier ( container . name . text ) ; while ( ! isUniqueLocalName ( escapeIdentifier ( prefix + name ) , container ) ) { prefix += "_" ; } links . localModuleName = prefix + getTextOfNode ( container . name ) ; } return links . localModuleName ; } function getLocalNameForSymbol ( symbol , location ) { var node = location ; while ( node ) { if ( ( node . kind === SyntaxKind . ModuleDeclaration || node . kind === SyntaxKind . EnumDeclaration ) && getSymbolOfNode ( node ) === symbol ) { return getLocalNameOfContainer ( < ModuleDeclaration | EnumDeclaration > node ) ; } node = node . parent ; } Debug . fail ( "getLocalNameForSymbol failed" ) ; } function getExpressionNamePrefix ( node ) { var symbol = getNodeLinks ( node ) . resolvedSymbol ; if ( symbol ) { var exportSymbol = getExportSymbolOfValueSymbolIfExported ( symbol ) ; if ( symbol !== exportSymbol && ! ( exportSymbol . flags & SymbolFlags . ExportHasLocal ) ) { symbol = exportSymbol ; } if ( symbol . parent ) { return isExternalModuleSymbol ( symbol . parent ) ? "exports" : getLocalNameForSymbol ( getParentOfSymbol ( symbol ) , node . parent ) ; } } } function getExportAssignmentName ( node ) { var symbol = getExportAssignmentSymbol ( getSymbolOfNode ( node ) ) ; return symbol && symbolIsValue ( symbol ) && ! isConstEnumSymbol ( symbol ) ? symbolToString ( symbol ) : undefined ; } function isTopLevelValueImportWithEntityName ( node ) { if ( node . parent . kind !== SyntaxKind . SourceFile || ! isInternalModuleImportDeclaration ( node ) ) { return false ; } return isImportResolvedToValue ( getSymbolOfNode ( node ) ) ; } function hasSemanticErrors ( sourceFile ? ) { return getDiagnostics ( sourceFile ) . length > 0 || getGlobalDiagnostics ( ) . length > 0 ; } function isEmitBlocked ( sourceFile ? ) { return program . getDiagnostics ( sourceFile ) . length !== 0 || hasEarlyErrors ( sourceFile ) || ( compilerOptions . noEmitOnError && getDiagnostics ( sourceFile ) . length !== 0 ) ; } function hasEarlyErrors ( sourceFile ? ) { return forEach ( getDiagnostics ( sourceFile ) , d => d . isEarly ) ; } function isImportResolvedToValue ( symbol ) { var target = resolveImport ( symbol ) ; return target !== unknownSymbol && target . flags & SymbolFlags . Value && ! isConstEnumOrConstEnumOnlyModule ( target ) ; } function isConstEnumOrConstEnumOnlyModule ( s ) { return isConstEnumSymbol ( s ) || s . constEnumOnlyModule ; } function isReferencedImportDeclaration ( node ) { var symbol = getSymbolOfNode ( node ) ; if ( getSymbolLinks ( symbol ) . referenced ) { return true ; } if ( node . flags & NodeFlags . Export ) { return isImportResolvedToValue ( symbol ) ; } return false ; } function isImplementationOfOverload ( node ) { if ( node . body ) { var symbol = getSymbolOfNode ( node ) ; var signaturesOfSymbol = getSignaturesOfSymbol ( symbol ) ; return signaturesOfSymbol . length > 1 || ( signaturesOfSymbol . length === 1 && signaturesOfSymbol [ 0 ] . declaration !== node ) ; } return false ; } function getNodeCheckFlags ( node ) { return getNodeLinks ( node ) . flags ; } function getEnumMemberValue ( node ) { computeEnumMemberValues ( < EnumDeclaration > node . parent ) ; return getNodeLinks ( node ) . enumMemberValue ; } function getConstantValue ( node ) { var symbol = getNodeLinks ( node ) . resolvedSymbol ; if ( symbol && ( symbol . flags & SymbolFlags . EnumMember ) ) { var declaration = symbol . valueDeclaration ; var constantValue ; if ( declaration . kind === SyntaxKind . EnumMember && ( constantValue = getNodeLinks ( declaration ) . enumMemberValue ) !== undefined ) { return constantValue ; } } return undefined ; } function writeTypeOfDeclaration ( declaration , enclosingDeclaration , flags , writer ) { var symbol = getSymbolOfNode ( declaration ) ; var type = symbol && ! ( symbol . flags & ( SymbolFlags . TypeLiteral | SymbolFlags . CallSignature | SymbolFlags . ConstructSignature ) ) ? getTypeOfSymbol ( symbol ) : unknownType ; getSymbolDisplayBuilder ( ) . buildTypeDisplay ( type , writer , enclosingDeclaration , flags ) ; } function writeReturnTypeOfSignatureDeclaration ( signatureDeclaration , enclosingDeclaration , flags , writer ) { var signature = getSignatureFromDeclaration ( signatureDeclaration ) ; getSymbolDisplayBuilder ( ) . buildTypeDisplay ( getReturnTypeOfSignature ( signature ) , writer , enclosingDeclaration , flags ) ; } function createResolver ( ) { return { getProgram : ( ) => program , getLocalNameOfContainer , getExpressionNamePrefix , getExportAssignmentName , isReferencedImportDeclaration , getNodeCheckFlags , getEnumMemberValue , isTopLevelValueImportWithEntityName , hasSemanticErrors , isEmitBlocked , isDeclarationVisible , isImplementationOfOverload , writeTypeOfDeclaration , writeReturnTypeOfSignatureDeclaration , isSymbolAccessible , isEntityNameVisible , getConstantValue , } ; } function invokeEmitter ( targetSourceFile ? ) { var resolver = createResolver ( ) ; return emitFiles ( resolver , targetSourceFile ) ; } function initializeTypeChecker ( ) { forEach ( program . getSourceFiles ( ) , file => { bindSourceFile ( file ) ; forEach ( file . semanticDiagnostics , addDiagnostic ) ; } ) ; forEach ( program . getSourceFiles ( ) , file => { if ( ! isExternalModule ( file ) ) { extendSymbolTable ( globals , file . locals ) ; } } ) ; getSymbolLinks ( undefinedSymbol ) . type = undefinedType ; getSymbolLinks ( argumentsSymbol ) . type = getGlobalType ( "IArguments" ) ; getSymbolLinks ( unknownSymbol ) . type = unknownType ; globals [ undefinedSymbol . name ] = undefinedSymbol ; globalArraySymbol = getGlobalSymbol ( "Array" ) ; globalArrayType = getTypeOfGlobalSymbol ( globalArraySymbol , 1 ) ; globalObjectType = getGlobalType ( "Object" ) ; globalFunctionType = getGlobalType ( "Function" ) ; globalStringType = getGlobalType ( "String" ) ; globalNumberType = getGlobalType ( "Number" ) ; globalBooleanType = getGlobalType ( "Boolean" ) ; globalRegExpType = getGlobalType ( "RegExp" ) ; globalTemplateStringsArrayType = compilerOptions . target >= ScriptTarget . ES6 ? getGlobalType ( "TemplateStringsArray" ) : unknownType ; } initializeTypeChecker ( ) ; return checker ; } }