@react-native/codegen
Advanced tools
@@ -321,6 +321,4 @@ /** | ||
| export interface StringLiteralUnionTypeAnnotation { | ||
| readonly type: 'StringLiteralUnionTypeAnnotation'; | ||
| readonly types: StringLiteralTypeAnnotation[]; | ||
| } | ||
| export type StringLiteralUnionTypeAnnotation = | ||
| UnionTypeAnnotation<StringLiteralTypeAnnotation>; | ||
@@ -387,7 +385,2 @@ export interface NativeModuleNumberTypeAnnotation { | ||
| export type UnionTypeAnnotationMemberType = | ||
| | 'NumberTypeAnnotation' | ||
| | 'ObjectTypeAnnotation' | ||
| | 'StringTypeAnnotation'; | ||
| export type NativeModuleUnionTypeAnnotationMemberType = | ||
@@ -402,6 +395,4 @@ | NativeModuleObjectTypeAnnotation | ||
| export interface NativeModuleUnionTypeAnnotation { | ||
| readonly type: 'UnionTypeAnnotation'; | ||
| readonly memberType: UnionTypeAnnotationMemberType; | ||
| } | ||
| export type NativeModuleUnionTypeAnnotation = | ||
| UnionTypeAnnotation<NativeModuleUnionTypeAnnotationMemberType>; | ||
@@ -408,0 +399,0 @@ export interface NativeModuleMixedTypeAnnotation { |
@@ -13,3 +13,3 @@ /** | ||
| const {getEnumName, toSafeCppString} = require('../Utils'); | ||
| const {getEnumName, parseValidUnionType, toSafeCppString} = require('../Utils'); | ||
| function toIntEnumValueName(propName, value) { | ||
@@ -46,3 +46,36 @@ return `${toSafeCppString(propName)}${value}`; | ||
| return `std::vector<${getCppTypeForAnnotation(typeElement.type)}>`; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeElement); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return `std::vector<${getCppTypeForAnnotation('BooleanTypeAnnotation')}>`; | ||
| case 'number': | ||
| // Have type-upgraded Number to Double in this case to match the Int32TypeAnnotation, FloatTypeAnnotation & DoubleTypeAnnotation | ||
| return `std::vector<${getCppTypeForAnnotation('DoubleTypeAnnotation')}>`; | ||
| case 'object': | ||
| if (!structParts) { | ||
| throw new Error( | ||
| `Trying to generate the event emitter for an Array of ${typeElement.type} without informations to generate the generic type`, | ||
| ); | ||
| } | ||
| return `std::vector<${generateEventStructName(structParts)}>`; | ||
| case 'string': | ||
| if ( | ||
| typeElement.types.every( | ||
| ({type}) => type === 'StringLiteralTypeAnnotation', | ||
| ) | ||
| ) { | ||
| if (!structParts) { | ||
| throw new Error( | ||
| `Trying to generate the event emitter for an Array of ${typeElement.type} without informations to generate the generic type`, | ||
| ); | ||
| } | ||
| return `std::vector<${generateEventStructName(structParts)}>`; | ||
| } | ||
| // Unions of strings and string literals are treated as just strings | ||
| return `std::vector<${getCppTypeForAnnotation('StringTypeAnnotation')}>`; | ||
| default: | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
| case 'ObjectTypeAnnotation': | ||
@@ -49,0 +82,0 @@ if (!structParts) { |
@@ -14,2 +14,3 @@ /** | ||
| const {indent} = require('../Utils'); | ||
| const {parseValidUnionType} = require('../Utils'); | ||
| const {IncludeTemplate, generateEventStructName} = require('./CppHelpers'); | ||
@@ -150,3 +151,7 @@ | ||
| ); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(elementType); | ||
| if (validUnionType !== 'string') { | ||
| throw new Error('Invalid since it is a union of non strings'); | ||
| } | ||
| return setValueAtIndex( | ||
@@ -247,3 +252,7 @@ propertyName, | ||
| ); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| if (validUnionType !== 'string') { | ||
| throw new Error('Invalid since it is a union of non strings'); | ||
| } | ||
| return generateSetter( | ||
@@ -250,0 +259,0 @@ parentPropertyName, |
@@ -13,3 +13,3 @@ /** | ||
| const {indent, toSafeCppString} = require('../Utils'); | ||
| const {indent, parseValidUnionType, toSafeCppString} = require('../Utils'); | ||
| const { | ||
@@ -71,4 +71,4 @@ generateEventStructName, | ||
| function getNativeTypeFromAnnotation(componentName, eventProperty, nameParts) { | ||
| const {type} = eventProperty.typeAnnotation; | ||
| switch (type) { | ||
| const {typeAnnotation} = eventProperty; | ||
| switch (typeAnnotation.type) { | ||
| case 'BooleanTypeAnnotation': | ||
@@ -80,4 +80,9 @@ case 'StringTypeAnnotation': | ||
| case 'MixedTypeAnnotation': | ||
| return getCppTypeForAnnotation(type); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return getCppTypeForAnnotation(typeAnnotation.type); | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| if (validUnionType !== 'string') { | ||
| throw new Error('Invalid since it is a union of non strings'); | ||
| } | ||
| return generateEventStructName([...nameParts, eventProperty.name]); | ||
| case 'ObjectTypeAnnotation': | ||
@@ -97,4 +102,6 @@ return generateEventStructName([...nameParts, eventProperty.name]); | ||
| default: | ||
| type; | ||
| throw new Error(`Received invalid event property type ${type}`); | ||
| typeAnnotation.type; | ||
| throw new Error( | ||
| `Received invalid event property type ${typeAnnotation.type}`, | ||
| ); | ||
| } | ||
@@ -136,3 +143,7 @@ } | ||
| ); | ||
| } else if (elementType.type === 'StringLiteralUnionTypeAnnotation') { | ||
| } else if (elementType.type === 'UnionTypeAnnotation') { | ||
| const validUnionType = parseValidUnionType(elementType); | ||
| if (validUnionType !== 'string') { | ||
| throw new Error('Invalid since it is a union of non strings'); | ||
| } | ||
| generateEnum( | ||
@@ -188,3 +199,7 @@ structs, | ||
| return; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| if (validUnionType !== 'string') { | ||
| throw new Error('Invalid since it is a union of non strings'); | ||
| } | ||
| generateEnum( | ||
@@ -191,0 +206,0 @@ structs, |
@@ -15,4 +15,9 @@ /** | ||
| const {wrapOptional} = require('../TypeUtils/Cxx'); | ||
| const {getEnumName, toPascalCase, toSafeCppString} = require('../Utils'); | ||
| const { | ||
| getEnumName, | ||
| parseValidUnionType, | ||
| toPascalCase, | ||
| toSafeCppString, | ||
| } = require('../Utils'); | ||
| const { | ||
| createAliasResolver, | ||
@@ -64,4 +69,2 @@ getModules, | ||
| return wrap(val => `${val}.asString(rt)`); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return wrap(val => `${val}.asString(rt)`); | ||
| case 'BooleanTypeAnnotation': | ||
@@ -99,13 +102,15 @@ return wrap(val => `${val}.asBool()`); | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return wrap(val => `${val}.asBool()`); | ||
| case 'number': | ||
| return wrap(val => `${val}.asNumber()`); | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| return wrap(val => `${val}.asObject(rt)`); | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return wrap(val => `${val}.asString(rt)`); | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union member type for param "${arg.name}, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -209,4 +214,2 @@ case 'ObjectTypeAnnotation': | ||
| return wrapOptional('jsi::String', isRequired); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return wrapOptional('jsi::String', isRequired); | ||
| case 'NumberTypeAnnotation': | ||
@@ -238,11 +241,15 @@ return wrapOptional('double', isRequired); | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return wrapOptional('bool', isRequired); | ||
| case 'number': | ||
| return wrapOptional('double', isRequired); | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| return wrapOptional('jsi::Object', isRequired); | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return wrapOptional('jsi::String', isRequired); | ||
| default: | ||
| throw new Error(createErrorMessage(realTypeAnnotation.type)); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -249,0 +256,0 @@ case 'ObjectTypeAnnotation': |
@@ -15,3 +15,3 @@ /** | ||
| const {wrapOptional} = require('../TypeUtils/Java'); | ||
| const {toPascalCase} = require('../Utils'); | ||
| const {parseValidUnionType, toPascalCase} = require('../Utils'); | ||
| const {createAliasResolver, getModules} = require('./Utils'); | ||
@@ -77,4 +77,4 @@ function FileTemplate(config) { | ||
| function translateEventEmitterTypeToJavaType(eventEmitter, imports) { | ||
| const type = eventEmitter.typeAnnotation.typeAnnotation.type; | ||
| switch (type) { | ||
| const typeAnnotation = eventEmitter.typeAnnotation.typeAnnotation; | ||
| switch (typeAnnotation.type) { | ||
| case 'StringTypeAnnotation': | ||
@@ -84,4 +84,18 @@ return 'String'; | ||
| return 'String'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'String'; | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return 'boolean'; | ||
| case 'number': | ||
| return 'double'; | ||
| case 'object': | ||
| imports.add('com.facebook.react.bridge.ReadableMap'); | ||
| return 'ReadableMap'; | ||
| case 'string': | ||
| return 'String'; | ||
| default: | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
| case 'NumberTypeAnnotation': | ||
@@ -113,3 +127,3 @@ case 'NumberLiteralTypeAnnotation': | ||
| default: | ||
| type; | ||
| typeAnnotation.type; | ||
| throw new Error( | ||
@@ -151,4 +165,2 @@ `Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`, | ||
| return wrapOptional('String', isRequired); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return wrapOptional('String', isRequired); | ||
| case 'NumberTypeAnnotation': | ||
@@ -178,14 +190,16 @@ return wrapOptional('double', isRequired); | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return wrapOptional('boolean', isRequired); | ||
| case 'number': | ||
| return wrapOptional('double', isRequired); | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| imports.add('com.facebook.react.bridge.ReadableMap'); | ||
| return wrapOptional('ReadableMap', isRequired); | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return wrapOptional('String', isRequired); | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -246,4 +260,2 @@ case 'ObjectTypeAnnotation': | ||
| return wrapOptional('String', isRequired); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return wrapOptional('String', isRequired); | ||
| case 'NumberTypeAnnotation': | ||
@@ -273,14 +285,16 @@ return wrapOptional('double', isRequired); | ||
| case 'UnionTypeAnnotation': | ||
| switch (realTypeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return wrapOptional('boolean', isRequired); | ||
| case 'number': | ||
| return wrapOptional('double', isRequired); | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| imports.add('com.facebook.react.bridge.WritableMap'); | ||
| return wrapOptional('WritableMap', isRequired); | ||
| case 'StringTypeAnnotation': | ||
| return wrapOptional('ReadableMap', isRequired); | ||
| case 'string': | ||
| return wrapOptional('String', isRequired); | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -350,13 +364,15 @@ case 'ObjectTypeAnnotation': | ||
| case 'UnionTypeAnnotation': | ||
| switch (realTypeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return nullable ? 'return null;' : 'return false;'; | ||
| case 'number': | ||
| return nullable ? 'return null;' : 'return 0;'; | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| return 'return null;'; | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return nullable ? 'return null;' : 'return "";'; | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -367,4 +383,2 @@ case 'StringTypeAnnotation': | ||
| return nullable ? 'return null;' : 'return "";'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return nullable ? 'return null;' : 'return "";'; | ||
| case 'ObjectTypeAnnotation': | ||
@@ -371,0 +385,0 @@ return 'return null;'; |
@@ -14,2 +14,3 @@ /** | ||
| const {unwrapNullable} = require('../../parsers/parsers-commons'); | ||
| const {parseValidUnionType} = require('../Utils'); | ||
| const {createAliasResolver, getModules} = require('./Utils'); | ||
@@ -109,4 +110,2 @@ const HostFunctionTemplate = ({ | ||
| return 'StringKind'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'StringKind'; | ||
| case 'BooleanTypeAnnotation': | ||
@@ -128,13 +127,15 @@ return 'BooleanKind'; | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return 'BooleanKind'; | ||
| case 'number': | ||
| return 'NumberKind'; | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| return 'ObjectKind'; | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return 'StringKind'; | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -189,4 +190,2 @@ case 'NumberTypeAnnotation': | ||
| return 'Ljava/lang/String;'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'Ljava/lang/String;'; | ||
| case 'BooleanTypeAnnotation': | ||
@@ -208,13 +207,15 @@ return !isRequired ? 'Ljava/lang/Boolean;' : 'Z'; | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return !isRequired ? 'Ljava/lang/Boolean;' : 'Z'; | ||
| case 'number': | ||
| return !isRequired ? 'Ljava/lang/Double;' : 'D'; | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| return 'Lcom/facebook/react/bridge/ReadableMap;'; | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return 'Ljava/lang/String;'; | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union prop value, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -269,4 +270,2 @@ case 'NumberTypeAnnotation': | ||
| return 'Ljava/lang/String;'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'Ljava/lang/String;'; | ||
| case 'BooleanTypeAnnotation': | ||
@@ -288,13 +287,15 @@ return nullable ? 'Ljava/lang/Boolean;' : 'Z'; | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(realTypeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return nullable ? 'Ljava/lang/Boolean;' : 'Z'; | ||
| case 'number': | ||
| return nullable ? 'Ljava/lang/Double;' : 'D'; | ||
| case 'ObjectTypeAnnotation': | ||
| return 'Lcom/facebook/react/bridge/WritableMap;'; | ||
| case 'StringTypeAnnotation': | ||
| case 'object': | ||
| return 'Lcom/facebook/react/bridge/ReadableMap;'; | ||
| case 'string': | ||
| return 'Ljava/lang/String;'; | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union member type, found: ${realTypeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -301,0 +302,0 @@ case 'NumberTypeAnnotation': |
@@ -83,4 +83,5 @@ /** | ||
| return 'NSString *'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'NSString *'; | ||
| case 'UnionTypeAnnotation': | ||
| // TODO(T247151345): Implement proper heterogeneous union support. This is unsafe. | ||
| return 'NSObject *'; | ||
| case 'NumberTypeAnnotation': | ||
@@ -164,3 +165,3 @@ return wrapCxxOptional('double', isRequired); | ||
| return value; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| case 'UnionTypeAnnotation': | ||
| return value; | ||
@@ -167,0 +168,0 @@ case 'NumberTypeAnnotation': |
@@ -71,4 +71,5 @@ /** | ||
| return 'NSString *'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'NSString *'; | ||
| case 'UnionTypeAnnotation': | ||
| // TODO(T247151345): Implement proper heterogeneous union support. This is unsafe. | ||
| return 'NSObject *'; | ||
| case 'NumberTypeAnnotation': | ||
@@ -153,4 +154,6 @@ return wrapCxxOptional('double', isRequired); | ||
| return RCTBridgingTo('String'); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return RCTBridgingTo('String'); | ||
| case 'UnionTypeAnnotation': | ||
| return !isRequired | ||
| ? `!RCTNilIfNull(${value}) ? std::optional<NSObject *>{} : std::optional<NSObject *>(${value})` | ||
| : value; | ||
| case 'NumberTypeAnnotation': | ||
@@ -157,0 +160,0 @@ return RCTBridgingTo('Double'); |
@@ -11,6 +11,6 @@ /** | ||
| const {toPascalCase} = require('../../Utils'); | ||
| const {parseValidUnionType, toPascalCase} = require('../../Utils'); | ||
| function getEventEmitterTypeObjCType(eventEmitter) { | ||
| const type = eventEmitter.typeAnnotation.typeAnnotation.type; | ||
| switch (type) { | ||
| const typeAnnotation = eventEmitter.typeAnnotation.typeAnnotation; | ||
| switch (typeAnnotation.type) { | ||
| case 'StringTypeAnnotation': | ||
@@ -20,4 +20,17 @@ return 'NSString *_Nonnull'; | ||
| return 'NSString *_Nonnull'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'NSString *_Nonnull'; | ||
| case 'UnionTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return 'BOOL'; | ||
| case 'number': | ||
| return 'NSNumber *_Nonnull'; | ||
| case 'object': | ||
| return 'NSDictionary *'; | ||
| case 'string': | ||
| return 'NSString *_Nonnull'; | ||
| default: | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
| case 'NumberTypeAnnotation': | ||
@@ -44,3 +57,3 @@ case 'NumberLiteralTypeAnnotation': | ||
| default: | ||
| type; | ||
| typeAnnotation.type; | ||
| throw new Error( | ||
@@ -47,0 +60,0 @@ `Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`, |
@@ -18,3 +18,3 @@ /** | ||
| const {wrapOptional} = require('../../TypeUtils/Objective-C'); | ||
| const {capitalize} = require('../../Utils'); | ||
| const {capitalize, parseValidUnionType} = require('../../Utils'); | ||
| const {getNamespacedStructName} = require('./Utils'); | ||
@@ -214,4 +214,5 @@ const invariant = require('invariant'); | ||
| return notStruct(wrapOptional('NSString *', !nullable)); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return notStruct(wrapOptional('NSString *', !nullable)); | ||
| case 'UnionTypeAnnotation': | ||
| // TODO(T247151345): Implement proper heterogeneous union support. This is unsafe. | ||
| return notStruct(wrapOptional('NSObject *', !nullable)); | ||
| case 'NumberTypeAnnotation': | ||
@@ -289,6 +290,2 @@ return notStruct(isRequired ? 'double' : 'NSNumber *'); | ||
| return wrapOptional('NSString *', isRequired); | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| // TODO: Can NSString * returns not be _Nullable? | ||
| // In the legacy codegen, we don't surround NSSTring * with _Nullable | ||
| return wrapOptional('NSString *', isRequired); | ||
| case 'NumberTypeAnnotation': | ||
@@ -320,8 +317,11 @@ return wrapOptional('NSNumber *', isRequired); | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return wrapOptional('NSNumber *', isRequired); | ||
| case 'ObjectTypeAnnotation': | ||
| case 'number': | ||
| return wrapOptional('NSNumber *', isRequired); | ||
| case 'object': | ||
| return wrapOptional('NSDictionary *', isRequired); | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| // TODO: Can NSString * returns not be _Nullable? | ||
@@ -331,5 +331,4 @@ // In the legacy codegen, we don't surround NSSTring * with _Nullable | ||
| default: | ||
| throw new Error( | ||
| `Unsupported union return type for ${methodName}, found: ${typeAnnotation.memberType}"`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member type`); | ||
| } | ||
@@ -364,4 +363,2 @@ case 'GenericObjectTypeAnnotation': | ||
| return 'StringKind'; | ||
| case 'StringLiteralUnionTypeAnnotation': | ||
| return 'StringKind'; | ||
| case 'NumberTypeAnnotation': | ||
@@ -395,13 +392,15 @@ return 'NumberKind'; | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'NumberTypeAnnotation': | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return 'BooleanKind'; | ||
| case 'number': | ||
| return 'NumberKind'; | ||
| case 'ObjectTypeAnnotation': | ||
| case 'object': | ||
| return 'ObjectKind'; | ||
| case 'StringTypeAnnotation': | ||
| case 'string': | ||
| return 'StringKind'; | ||
| default: | ||
| throw new Error( | ||
| `Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`, | ||
| ); | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member types`); | ||
| } | ||
@@ -408,0 +407,0 @@ default: |
@@ -44,3 +44,7 @@ /** | ||
| } = require('../../../parsers/parsers-commons'); | ||
| const {capitalize} = require('../../Utils'); | ||
| const { | ||
| HeterogeneousUnionError, | ||
| capitalize, | ||
| parseValidUnionType, | ||
| } = require('../../Utils'); | ||
| class StructCollector { | ||
@@ -93,23 +97,33 @@ constructor() { | ||
| case 'UnionTypeAnnotation': | ||
| switch (typeAnnotation.memberType) { | ||
| case 'StringTypeAnnotation': | ||
| return wrapNullable(nullable, { | ||
| type: 'StringTypeAnnotation', | ||
| }); | ||
| case 'NumberTypeAnnotation': | ||
| return wrapNullable(nullable, { | ||
| type: 'NumberTypeAnnotation', | ||
| }); | ||
| case 'ObjectTypeAnnotation': | ||
| // This isn't smart enough to actually know how to generate the | ||
| // options on the native side. So we just treat it as an unknown object type | ||
| return wrapNullable(nullable, { | ||
| type: 'GenericObjectTypeAnnotation', | ||
| }); | ||
| default: | ||
| typeAnnotation.memberType; | ||
| throw new Error( | ||
| 'Union types are unsupported in structs' + | ||
| JSON.stringify(typeAnnotation), | ||
| ); | ||
| try { | ||
| const validUnionType = parseValidUnionType(typeAnnotation); | ||
| switch (validUnionType) { | ||
| case 'boolean': | ||
| return wrapNullable(nullable, { | ||
| type: 'BooleanTypeAnnotation', | ||
| }); | ||
| case 'number': | ||
| return wrapNullable(nullable, { | ||
| type: 'NumberTypeAnnotation', | ||
| }); | ||
| case 'object': | ||
| // This isn't smart enough to actually know how to generate the | ||
| // options on the native side. So we just treat it as an unknown object type | ||
| return wrapNullable(nullable, { | ||
| type: 'GenericObjectTypeAnnotation', | ||
| }); | ||
| case 'string': | ||
| return wrapNullable(nullable, { | ||
| type: 'StringTypeAnnotation', | ||
| }); | ||
| default: | ||
| validUnionType; | ||
| throw new Error(`Unsupported union member types`); | ||
| } | ||
| } catch (ex) { | ||
| // TODO(T247151345): Implement proper heterogeneous union support. | ||
| if (ex instanceof HeterogeneousUnionError) { | ||
| return wrapNullable(nullable, typeAnnotation); | ||
| } | ||
| throw ex; | ||
| } | ||
@@ -116,0 +130,0 @@ default: { |
@@ -41,8 +41,57 @@ /** | ||
| } | ||
| const NumberTypes = ['NumberTypeAnnotation', 'NumberLiteralTypeAnnotation']; | ||
| const StringTypes = ['StringTypeAnnotation', 'StringLiteralTypeAnnotation']; | ||
| const ObjectTypes = ['ObjectTypeAnnotation']; | ||
| const BooleanTypes = ['BooleanTypeAnnotation', 'BooleanLiteralTypeAnnotation']; | ||
| const ValidUnionTypes = [ | ||
| ...NumberTypes, | ||
| ...ObjectTypes, | ||
| ...StringTypes, | ||
| ...BooleanTypes, | ||
| ]; | ||
| class HeterogeneousUnionError extends Error { | ||
| constructor() { | ||
| super(`Non-homogenous union member types`); | ||
| } | ||
| } | ||
| function parseValidUnionType(annotation) { | ||
| const isUnionOfType = types => { | ||
| return annotation.types.every(memberTypeAnnotation => | ||
| types.includes(memberTypeAnnotation.type), | ||
| ); | ||
| }; | ||
| if (isUnionOfType(BooleanTypes)) { | ||
| return 'boolean'; | ||
| } | ||
| if (isUnionOfType(NumberTypes)) { | ||
| return 'number'; | ||
| } | ||
| if (isUnionOfType(ObjectTypes)) { | ||
| return 'object'; | ||
| } | ||
| if (isUnionOfType(StringTypes)) { | ||
| return 'string'; | ||
| } | ||
| const invalidTypes = annotation.types.filter(member => { | ||
| return !ValidUnionTypes.includes(member.type); | ||
| }); | ||
| // Check if union members are all supported but not homogeneous | ||
| // (e.g., mix of number and boolean) | ||
| if (invalidTypes.length === 0) { | ||
| throw new HeterogeneousUnionError(); | ||
| } else { | ||
| throw new Error( | ||
| `Unsupported union member types: ${invalidTypes.join(', ')}"`, | ||
| ); | ||
| } | ||
| } | ||
| module.exports = { | ||
| capitalize, | ||
| indent, | ||
| parseValidUnionType, | ||
| toPascalCase, | ||
| toSafeCppString, | ||
| getEnumName, | ||
| HeterogeneousUnionError, | ||
| }; |
@@ -258,3 +258,3 @@ /** | ||
| // Right now they are partially treated as UnionTypeAnnotation | ||
| UnionTypeAnnotation: 'UnionTypeAnnotation', | ||
| // UnionTypeAnnotation: 'UnionTypeAnnotation', | ||
| }; | ||
@@ -261,0 +261,0 @@ if (type in TypeMap) { |
@@ -269,16 +269,2 @@ /** | ||
| /** | ||
| * Union parsing errors | ||
| */ | ||
| class UnsupportedUnionTypeAnnotationParserError extends ParserError { | ||
| constructor(nativeModuleName, arrayElementTypeAST, types) { | ||
| super( | ||
| nativeModuleName, | ||
| arrayElementTypeAST, | ||
| `Union members must be of the same type, but multiple types were found ${types.join(', ')}'.`, | ||
| ); | ||
| } | ||
| } | ||
| /** | ||
| * Module parsing errors | ||
@@ -361,3 +347,2 @@ */ | ||
| UnsupportedEnumDeclarationParserError, | ||
| UnsupportedUnionTypeAnnotationParserError, | ||
| UnsupportedModuleEventEmitterTypePropertyParserError, | ||
@@ -364,0 +349,0 @@ UnsupportedModuleEventEmitterPropertyParserError, |
@@ -110,3 +110,3 @@ /** | ||
| return { | ||
| type: 'StringLiteralUnionTypeAnnotation', | ||
| type: 'UnionTypeAnnotation', | ||
| types: typeAnnotation.types.map(option => ({ | ||
@@ -113,0 +113,0 @@ type: 'StringLiteralTypeAnnotation', |
@@ -223,3 +223,14 @@ /** | ||
| case 'UnionTypeAnnotation': { | ||
| return emitUnion(nullable, hasteModuleName, typeAnnotation, parser); | ||
| return emitUnion( | ||
| nullable, | ||
| hasteModuleName, | ||
| typeAnnotation, | ||
| types, | ||
| aliasMap, | ||
| enumMap, | ||
| tryParse, | ||
| cxxOnly, | ||
| translateTypeAnnotation, | ||
| parser, | ||
| ); | ||
| } | ||
@@ -226,0 +237,0 @@ case 'NumberLiteralTypeAnnotation': { |
@@ -134,5 +134,2 @@ /** | ||
| } | ||
| getStringLiteralUnionTypeAnnotationStringLiterals(membersTypes) { | ||
| return membersTypes.map(item => item.value); | ||
| } | ||
| parseFile(filename) { | ||
@@ -139,0 +136,0 @@ const contents = fs.readFileSync(filename, 'utf8'); |
@@ -115,5 +115,2 @@ /** | ||
| } | ||
| getStringLiteralUnionTypeAnnotationStringLiterals(membersTypes) { | ||
| return []; | ||
| } | ||
| parseFile(filename) { | ||
@@ -120,0 +117,0 @@ /* $FlowFixMe[incompatible-type] Natural Inference rollout. See |
@@ -18,8 +18,4 @@ /** | ||
| } = require('./error-utils'); | ||
| const {ParserError, UnsupportedTypeAnnotationParserError} = require('./errors'); | ||
| const { | ||
| ParserError, | ||
| UnsupportedTypeAnnotationParserError, | ||
| UnsupportedUnionTypeAnnotationParserError, | ||
| } = require('./errors'); | ||
| const { | ||
| assertGenericTypeAnnotationHasExactlyOneTypeParameter, | ||
@@ -324,50 +320,47 @@ translateFunctionTypeAnnotation, | ||
| } | ||
| function emitUnion(nullable, hasteModuleName, typeAnnotation, parser) { | ||
| // Get all the literals by type | ||
| // Verify they are all the same | ||
| // If string, persist as StringLiteralUnionType | ||
| // If number, persist as NumberTypeAnnotation (TODO: Number literal) | ||
| const unionTypes = parser.remapUnionTypeAnnotationMemberNames( | ||
| typeAnnotation.types, | ||
| ); | ||
| // Only support unionTypes of the same kind | ||
| if (unionTypes.length > 1) { | ||
| throw new UnsupportedUnionTypeAnnotationParserError( | ||
| hasteModuleName, | ||
| typeAnnotation, | ||
| unionTypes, | ||
| ); | ||
| } | ||
| if (unionTypes[0] === 'StringTypeAnnotation') { | ||
| // Reprocess as a string literal union | ||
| return emitStringLiteralUnion( | ||
| nullable, | ||
| hasteModuleName, | ||
| typeAnnotation, | ||
| parser, | ||
| ); | ||
| } | ||
| return wrapNullable(nullable, { | ||
| type: 'UnionTypeAnnotation', | ||
| memberType: unionTypes[0], | ||
| }); | ||
| } | ||
| function emitStringLiteralUnion( | ||
| function emitUnion( | ||
| nullable, | ||
| hasteModuleName, | ||
| typeAnnotation, | ||
| types, | ||
| aliasMap, | ||
| enumMap, | ||
| tryParse, | ||
| cxxOnly, | ||
| translateTypeAnnotation, | ||
| parser, | ||
| ) { | ||
| const stringLiterals = | ||
| parser.getStringLiteralUnionTypeAnnotationStringLiterals( | ||
| typeAnnotation.types, | ||
| const unparsedMemberTypes = typeAnnotation.types; | ||
| const memberTypes = unparsedMemberTypes.map(memberType => { | ||
| const memberTypeAnnotation = translateTypeAnnotation( | ||
| hasteModuleName, | ||
| memberType, | ||
| types, | ||
| aliasMap, | ||
| enumMap, | ||
| tryParse, | ||
| cxxOnly, | ||
| parser, | ||
| ); | ||
| switch (memberTypeAnnotation.type) { | ||
| case 'StringTypeAnnotation': | ||
| case 'NumberTypeAnnotation': | ||
| case 'BooleanTypeAnnotation': | ||
| case 'NumberLiteralTypeAnnotation': | ||
| case 'StringLiteralTypeAnnotation': | ||
| case 'BooleanLiteralTypeAnnotation': | ||
| case 'ObjectTypeAnnotation': | ||
| case 'TypeAliasTypeAnnotation': | ||
| return memberTypeAnnotation; | ||
| default: | ||
| throw new UnsupportedTypeAnnotationParserError( | ||
| hasteModuleName, | ||
| memberType, | ||
| parser.language(), | ||
| ); | ||
| } | ||
| }); | ||
| return wrapNullable(nullable, { | ||
| type: 'StringLiteralUnionTypeAnnotation', | ||
| types: stringLiterals.map(stringLiteral => ({ | ||
| type: 'StringLiteralTypeAnnotation', | ||
| value: stringLiteral, | ||
| })), | ||
| type: 'UnionTypeAnnotation', | ||
| types: memberTypes, | ||
| }); | ||
@@ -547,2 +540,3 @@ } | ||
| MixedTypeAnnotation: cxxOnly ? emitMixed : emitGenericObject, | ||
| UnsafeMixed: cxxOnly ? emitMixed : emitGenericObject, | ||
| }; | ||
@@ -614,3 +608,3 @@ const typeAnnotationName = parser.convertKeywordToTypeAnnotation( | ||
| typeAnnotation: { | ||
| type: 'StringLiteralUnionTypeAnnotation', | ||
| type: 'UnionTypeAnnotation', | ||
| types: typeAnnotation.types.map(option => ({ | ||
@@ -617,0 +611,0 @@ type: 'StringLiteralTypeAnnotation', |
@@ -118,3 +118,3 @@ /** | ||
| return { | ||
| type: 'StringLiteralUnionTypeAnnotation', | ||
| type: 'UnionTypeAnnotation', | ||
| types: typeAnnotation.types.map(option => ({ | ||
@@ -121,0 +121,0 @@ type: 'StringLiteralTypeAnnotation', |
@@ -383,3 +383,14 @@ /** | ||
| case 'TSUnionType': { | ||
| return emitUnion(nullable, hasteModuleName, typeAnnotation, parser); | ||
| return emitUnion( | ||
| nullable, | ||
| hasteModuleName, | ||
| typeAnnotation, | ||
| types, | ||
| aliasMap, | ||
| enumMap, | ||
| tryParse, | ||
| cxxOnly, | ||
| translateTypeAnnotation, | ||
| parser, | ||
| ); | ||
| } | ||
@@ -386,0 +397,0 @@ case 'TSLiteralType': { |
@@ -138,5 +138,2 @@ /** | ||
| } | ||
| getStringLiteralUnionTypeAnnotationStringLiterals(membersTypes) { | ||
| return membersTypes.map(item => item.literal.value); | ||
| } | ||
| parseFile(filename) { | ||
@@ -143,0 +140,0 @@ const contents = fs.readFileSync(filename, 'utf8'); |
+1
-1
| { | ||
| "name": "@react-native/codegen", | ||
| "version": "0.84.0-nightly-20251204-5bb3a6d68", | ||
| "version": "0.84.0-nightly-20251205-95cc1e767", | ||
| "description": "Code generation tools for React Native", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1102737
0.82%16926
0.86%