/**
 * Copyright (c) 2016-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */ import * as Maybe from './maybe' ; import * as ObjC from './objc' ; import * as ObjCTypeUtils from './objc-type-utils' ; import * as ObjectGeneration from './object-generation' ; import * as ObjectSpec from './object-spec' ; import * as ObjectSpecCodeUtils from './object-spec-code-utils' ; const KNOWN_SYSTEM_TYPE_IMPORT_INFO = { bool : null , BOOL : null , double : null , float : null , id : null , CGFloat : { file : 'CGBase.h' , isPublic : true , requiresCPlusPlus : false , library : 'CoreGraphics' } , CGPoint : { file : 'CGGeometry.h' , isPublic : true , requiresCPlusPlus : false , library : 'CoreGraphics' } , CGRect : { file : 'CGGeometry.h' , isPublic : true , requiresCPlusPlus : false , library : 'CoreGraphics' } , CGSize : { file : 'CGGeometry.h' , isPublic : true , requiresCPlusPlus : false , library : 'CoreGraphics' } , int : null , int32_t : null , int64_t : null , long : null , SEL : null , UIColor : { file : 'UIKit.h' , isPublic : true , requiresCPlusPlus : false , library : 'UIKit' } , UIEdgeInsets : { file : 'UIGeometry.h' , isPublic : true , requiresCPlusPlus : false , library : 'UIKit' } , UIFont : { file : 'UIKit.h' , isPublic : true , requiresCPlusPlus : false , library : 'UIKit' } , UIImage : { file : 'UIKit.h' , isPublic : true , requiresCPlusPlus : false , library : 'UIKit' } , uint64_t : null , uint32_t : null , uintptr_t : null , Class : null , dispatch_block_t : null } ; function isFoundationType ( typeName ) { return ( typeName . indexOf ( 'NS' ) === 0 && typeName != 'NSLayoutAttribute' && typeName != 'NSTextAlignment' ) ; } export function isSystemType ( typeName ) { return ( isFoundationType ( typeName ) || ( typeName in KNOWN_SYSTEM_TYPE_IMPORT_INFO && KNOWN_SYSTEM_TYPE_IMPORT_INFO [ typeName ] == null ) ) ; } function typeLookupHasName ( typeName , typeLookup ) { return typeName === typeLookup . name ; } export function shouldIncludeImportForType ( typeLookups , typeName ) { return ( ! isSystemType ( typeName ) && typeLookups . filter ( ( lookup ) => typeLookupHasName ( typeName , lookup ) ) . length == 0 ) ; } function typeDefinitionImportForKnownSystemType ( typeName ) { return typeName in KNOWN_SYSTEM_TYPE_IMPORT_INFO ? KNOWN_SYSTEM_TYPE_IMPORT_INFO [ typeName ] : null ; } function * protocolForwardDeclarations ( conformingProtocol , referencedGenericTypes ) { if ( conformingProtocol != null ) { yield ObjC . ForwardDeclaration . ForwardProtocolDeclaration ( conformingProtocol ) ; } for ( const t of referencedGenericTypes ) { yield * protocolForwardDeclarations ( t . conformingProtocol , t . referencedGenericTypes ) ; } } function * classForwardDeclarations ( typeName , referencedGenericTypes , typeLookups ) { if ( ! isSystemType ( typeName ) ) { if ( ! typeLookups . some ( ( t ) => t . name === typeName && ! t . canForwardDeclare ) ) { yield ObjC . ForwardDeclaration . ForwardClassDeclaration ( typeName ) ; } } for ( const t of referencedGenericTypes ) { yield * classForwardDeclarations ( t . name , t . referencedGenericTypes , typeLookups ) ; } } export function forwardDeclarationsForAttributeType ( typeName , underlyingType , conformingProtocol , referencedGenericTypes , typeLookups ) { const forwardDeclarations = [ ... protocolForwardDeclarations ( conformingProtocol , referencedGenericTypes ) , ] ; if ( underlyingType === 'NSObject' ) { forwardDeclarations . push ( ... classForwardDeclarations ( typeName , referencedGenericTypes , typeLookups ) ) ; } return forwardDeclarations ; } /**
 * Applies only to attributes with underlyingType of NSObject that are not
 * system types. System types and non-NSObjects are always publicly imported.
 */ export enum ObjectImportMode { /** Generate imports in the header file. */ public , /**
     * Generate imports in the implementation file.
     * Used if you forward-declare the type in the header.
     */ private , /** Generate no import at all, unless it's a system type. */ none } function * classImports ( typeName , underlyingType , conformingProtocol , referencedGenericTypes , libraryTypeIsDefinedIn , fileTypeIsDefinedIn , objectLibrary , importMode , typeLookups ) { if ( conformingProtocol != null && importMode != ObjectImportMode . none ) { const lookup = typeLookups . find ( ( t ) => t . name === conformingProtocol ) ; if ( lookup != null ) { yield { library : lookup ?. library ?? objectLibrary , file : `${ lookup ?. file ?? conformingProtocol }.h` , isPublic : lookup ?. canForwardDeclare === false || importMode === ObjectImportMode . public , requiresCPlusPlus : false } ; } } if ( isFoundationType ( typeName ) ) { } else if ( typeName in KNOWN_SYSTEM_TYPE_IMPORT_INFO ) { const knownImport = KNOWN_SYSTEM_TYPE_IMPORT_INFO [ typeName ] ; if ( knownImport != null ) { yield knownImport ; } } else { const lookup = typeLookups . find ( ( t ) => t . name === typeName ) ; if ( underlyingType === 'NSObject' && importMode == ObjectImportMode . none && lookup ?. canForwardDeclare !== false ) { } else { yield { library : libraryTypeIsDefinedIn ?? lookup ?. library ?? objectLibrary , file : `${ fileTypeIsDefinedIn ?? lookup ?. file ?? typeName }.h` , isPublic : underlyingType !== 'NSObject' || lookup ?. canForwardDeclare === false || importMode === ObjectImportMode . public , requiresCPlusPlus : false } ; } } for ( const t of referencedGenericTypes ) { yield * classImports ( t . name , 'NSObject' , t . conformingProtocol , t . referencedGenericTypes , null , null , objectLibrary , importMode , typeLookups ) ; } } /**
 * Returns the imports that should be generated for an attribute, including
 * all referenced generic types. Takes care of looking up each type in
 * typeLookups and adjusting the import accordingly if it's found.
 * */ export function importsForAttributeType ( typeName , underlyingType , conformingProtocol , referencedGenericTypes , libraryTypeIsDefinedIn , fileTypeIsDefinedIn , objectLibrary , importMode , typeLookups ) { return [ ... classImports ( typeName , underlyingType , conformingProtocol , referencedGenericTypes , libraryTypeIsDefinedIn , fileTypeIsDefinedIn , objectLibrary , importMode , typeLookups ) , ] ; } export function importForAttribute ( typeName , underlyingType , libraryTypeIsDefinedIn , fileTypeIsDefinedIn , objectLibrary , isPublic ) { const builtInImport = typeDefinitionImportForKnownSystemType ( typeName ) ; if ( builtInImport != null ) { return builtInImport ; } const requiresPublicImport = isPublic || underlyingType != 'NSObject' ; return { library : libraryTypeIsDefinedIn != null ? libraryTypeIsDefinedIn : objectLibrary , file : `${ fileTypeIsDefinedIn != null ? fileTypeIsDefinedIn : typeName }.h` , isPublic : requiresPublicImport , requiresCPlusPlus : false } ; } export function importForTypeLookup ( defaultLibrary , isPublic , typeLookup ) { return { file : Maybe . match ( function Just ( file ) : string { return file + '.h' ; } , function Nothing ( ) { return typeLookup . name + '.h' ; } , typeLookup . file ) , isPublic : isPublic , requiresCPlusPlus : false , library : Maybe . match ( function Just ( library ) : string | null { return typeLookup . library ; } , function Nothing ( ) : string | null { return defaultLibrary ; } , typeLookup . library ) } ; }