/**
 * 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 Either from './either' ; import * as Error from './error' ; import * as Maybe from './maybe' ; import * as ObjC from './objc' ; import * as AlgebraicType from './algebraic-type' ; import * as ObjectGeneration from './object-generation' ; import * as ObjectGenerationParsingUtils from './object-generation-parsing-utils' ; import * as ObjectMonaParser from './js/object-mona-parser/object-mona-parser' ; function underlyingTypeForType ( providedUnderlyingType , typeReference ) { const underlyingType = ObjectGenerationParsingUtils . possiblyUndefinedStringToMaybe ( providedUnderlyingType ) ; return Maybe . match ( function Just ( type ) { return underlyingType ; } , function Nothing ( ) { return typeReference . indexOf ( '*' ) !== - 1 ? 'NSObject' : null ; } , underlyingType ) ; } function subtypeAttributeTypeFromParsedAttribtueType ( type , annotations ) { return { fileTypeIsDefinedIn : ObjectGenerationParsingUtils . valueFromImportAnnotationFromAnnotations ( annotations , 'file' ) , libraryTypeIsDefinedIn : ObjectGenerationParsingUtils . valueFromImportAnnotationFromAnnotations ( annotations , 'library' ) , name : type . name , reference : type . reference , underlyingType : underlyingTypeForType ( type . underlyingType , type . reference ) , conformingProtocol : ObjectGenerationParsingUtils . possiblyUndefinedStringToMaybe ( type . conformingProtocol ) , referencedGenericTypes : type . referencedGenericTypes . map ( referencedGenericTypeFromParsedAttributeType ) } ; } function subtypeAttributeFromParseResultAttribute ( attribute ) { return { annotations : ObjectGenerationParsingUtils . foundAnnotationFromParsedAnnotations ( attribute . annotations ) , name : attribute . name , comments : attribute . comments , type : subtypeAttributeTypeFromParsedAttribtueType ( attribute . type , attribute . annotations ) , nullability : ObjectGenerationParsingUtils . nullabilityFromParseResultAnnotations ( attribute . annotations ) } ; } /**
 * Very similar to subtypeAttributeTypeFromParsedAttribtueType,
 * but referenced generic types do not have annotations.
 */ function referencedGenericTypeFromParsedAttributeType ( type ) { return { name : type . name , conformingProtocol : ObjectGenerationParsingUtils . possiblyUndefinedStringToMaybe ( type . conformingProtocol ) , referencedGenericTypes : type . referencedGenericTypes . map ( referencedGenericTypeFromParsedAttributeType ) } ; } function subtypeFromParsedSubtype ( subtype ) { return subtype . attributeValue ? AlgebraicType . Subtype . SingleAttributeSubtypeDefinition ( subtypeAttributeFromParseResultAttribute ( subtype . attributeValue ) ) : AlgebraicType . Subtype . NamedAttributeCollectionDefinition ( { name : subtype . namedCollectionValue . typeName , comments : subtype . namedCollectionValue . comments , attributes : subtype . namedCollectionValue . attributes . map ( subtypeAttributeFromParseResultAttribute ) , annotations : ObjectGenerationParsingUtils . foundAnnotationFromParsedAnnotations ( subtype . namedCollectionValue . annotations ) } ) ; } function algebraicTypeFromParsedType ( type ) { return { annotations : ObjectGenerationParsingUtils . foundAnnotationFromParsedAnnotations ( type . annotations ) , comments : type . comments , name : type . typeName , includes : type . includes , excludes : type . excludes , libraryName : ObjectGenerationParsingUtils . libraryNameFromAnnotations ( type . annotations ) , typeLookups : Either . match ( function ( errors ) { return [ ] ; } , function ( typeLookups ) { return typeLookups ; } , ObjectGenerationParsingUtils . typeLookupsFromRawAnnotations ( type . annotations ) ) , subtypes : type . subtypes . map ( subtypeFromParsedSubtype ) } ; } export function parse ( input ) { const result = ObjectMonaParser . parseAlgebraicType ( input ) ; if ( result . isValid ) { const type = algebraicTypeFromParsedType ( result . type ) ; return Either . Right < Error . Error [ ] , AlgebraicType . Type > ( type ) ; } else { return Either . Left < Error . Error [ ] , AlgebraicType . Type > ( [ Error . Error ( result . errorReason ) , ] ) ; } }