Introduce TypeUtils (#42122)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/42122

This diff introduces the `TypeUtils` directory where we can put platform-specific, context-independent type transformations.

Changelog: [Internal]

Reviewed By: cipolleschi

Differential Revision: D52291837

fbshipit-source-id: 561b9c494aab5bfee3b3c668d3346bbd320e5266
This commit is contained in:
Dmitry Rykun
2024-01-03 08:58:30 -08:00
committed by Facebook GitHub Bot
parent 327df8a719
commit 82f8cf1836
9 changed files with 187 additions and 135 deletions
@@ -434,7 +434,7 @@ namespace JS {
struct Builder {
struct Input {
std::optional<bool> D;
id<NSObject> _Nullable A;
id<NSObject> _Nullable A;
std::optional<JS::NativeOptionalObjectTurboModule::ConstantsE::Builder> E;
NSString *F;
};
@@ -1780,7 +1780,7 @@ namespace JS {
struct Builder {
struct Input {
std::optional<bool> D;
id<NSObject> _Nullable A;
id<NSObject> _Nullable A;
std::optional<JS::NativeOptionalObjectTurboModule::ConstantsE::Builder> E;
NSString *F;
};
@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall react_native
*/
function wrapOptional(type: string, isRequired: boolean): string {
return isRequired ? type : `std::optional<${type}>`;
}
module.exports = {
wrapOptional,
};
@@ -0,0 +1,27 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall react_native
*/
const objectTypeForPrimitiveType = {
boolean: 'Boolean',
double: 'Double',
float: 'Float',
int: 'Integer',
};
function wrapOptional(type: string, isRequired: boolean): string {
return isRequired
? type
: `@Nullable ${objectTypeForPrimitiveType[type] ?? type}`;
}
module.exports = {
wrapOptional,
};
@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall react_native
*/
function wrapOptional(type: string, isRequired: boolean): string {
return isRequired ? type : `${type} _Nullable`;
}
module.exports = {
wrapOptional,
};
@@ -27,6 +27,7 @@ import type {
import type {AliasResolver} from './Utils';
const {unwrapNullable} = require('../../parsers/parsers-commons');
const {wrapOptional} = require('../TypeUtils/Cxx');
const {getEnumName, toSafeCppString} = require('../Utils');
const {indent} = require('../Utils');
const {
@@ -139,26 +140,21 @@ function translatePrimitiveJSTypeToCpp(
const [typeAnnotation, nullable] = unwrapNullable<NativeModuleTypeAnnotation>(
nullableTypeAnnotation,
);
const isRequired = !optional && !nullable;
const isRecursiveType = isDirectRecursiveMember(
parentObjectAliasName,
nullableTypeAnnotation,
);
const isRequired = (!optional && !nullable) || isRecursiveType;
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
realTypeAnnotation = resolveAlias(realTypeAnnotation.name);
}
function wrap(type: string) {
return isRequired || isRecursiveType ? type : `std::optional<${type}>`;
}
switch (realTypeAnnotation.type) {
case 'ReservedTypeAnnotation':
switch (realTypeAnnotation.name) {
case 'RootTag':
return wrap('double');
return wrapOptional('double', isRequired);
default:
(realTypeAnnotation.name: empty);
throw new Error(createErrorMessage(realTypeAnnotation.name));
@@ -166,49 +162,49 @@ function translatePrimitiveJSTypeToCpp(
case 'VoidTypeAnnotation':
return 'void';
case 'StringTypeAnnotation':
return wrap('jsi::String');
return wrapOptional('jsi::String', isRequired);
case 'NumberTypeAnnotation':
return wrap('double');
return wrapOptional('double', isRequired);
case 'DoubleTypeAnnotation':
return wrap('double');
return wrapOptional('double', isRequired);
case 'FloatTypeAnnotation':
return wrap('double');
return wrapOptional('double', isRequired);
case 'Int32TypeAnnotation':
return wrap('int');
return wrapOptional('int', isRequired);
case 'BooleanTypeAnnotation':
return wrap('bool');
return wrapOptional('bool', isRequired);
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap('jsi::Value');
return wrapOptional('jsi::Value', isRequired);
case 'StringTypeAnnotation':
return wrap('jsi::String');
return wrapOptional('jsi::String', isRequired);
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'GenericObjectTypeAnnotation':
return wrap('jsi::Object');
return wrapOptional('jsi::Object', isRequired);
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap('double');
return wrapOptional('double', isRequired);
case 'ObjectTypeAnnotation':
return wrap('jsi::Object');
return wrapOptional('jsi::Object', isRequired);
case 'StringTypeAnnotation':
return wrap('jsi::String');
return wrapOptional('jsi::String', isRequired);
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'ObjectTypeAnnotation':
return wrap('jsi::Object');
return wrapOptional('jsi::Object', isRequired);
case 'ArrayTypeAnnotation':
return wrap('jsi::Array');
return wrapOptional('jsi::Array', isRequired);
case 'FunctionTypeAnnotation':
return wrap('jsi::Function');
return wrapOptional('jsi::Function', isRequired);
case 'PromiseTypeAnnotation':
return wrap('jsi::Value');
return wrapOptional('jsi::Value', isRequired);
case 'MixedTypeAnnotation':
return wrap('jsi::Value');
return wrapOptional('jsi::Value', isRequired);
default:
(realTypeAnnotation.type: empty);
throw new Error(createErrorMessage(realTypeAnnotation.type));
@@ -22,6 +22,7 @@ import type {
import type {AliasResolver} from './Utils';
const {unwrapNullable} = require('../../parsers/parsers-commons');
const {wrapOptional} = require('../TypeUtils/Java');
const {createAliasResolver, getModules} = require('./Utils');
type FilesOutput = Map<string, string>;
@@ -111,13 +112,8 @@ function translateFunctionParamToJavaType(
const [typeAnnotation, nullable] =
unwrapNullable<NativeModuleParamTypeAnnotation>(nullableTypeAnnotation);
const isRequired = !optional && !nullable;
function wrapNullable(javaType: string, nullableType?: string) {
if (!isRequired) {
imports.add('javax.annotation.Nullable');
return `@Nullable ${nullableType ?? javaType}`;
}
return javaType;
if (!isRequired) {
imports.add('javax.annotation.Nullable');
}
// FIXME: support class alias for args
@@ -130,41 +126,41 @@ function translateFunctionParamToJavaType(
case 'ReservedTypeAnnotation':
switch (realTypeAnnotation.name) {
case 'RootTag':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
default:
(realTypeAnnotation.name: empty);
throw new Error(createErrorMessage(realTypeAnnotation.name));
}
case 'StringTypeAnnotation':
return wrapNullable('String');
return wrapOptional('String', isRequired);
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'FloatTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'DoubleTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'Int32TypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'BooleanTypeAnnotation':
return wrapNullable('boolean', 'Boolean');
return wrapOptional('boolean', isRequired);
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'StringTypeAnnotation':
return wrapNullable('String');
return wrapOptional('String', isRequired);
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
return wrapNullable('ReadableMap');
return wrapOptional('ReadableMap', isRequired);
case 'StringTypeAnnotation':
return wrapNullable('String');
return wrapOptional('String', isRequired);
default:
throw new Error(
`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`,
@@ -172,17 +168,17 @@ function translateFunctionParamToJavaType(
}
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
return wrapNullable('ReadableMap');
return wrapOptional('ReadableMap', isRequired);
case 'GenericObjectTypeAnnotation':
// Treat this the same as ObjectTypeAnnotation for now.
imports.add('com.facebook.react.bridge.ReadableMap');
return wrapNullable('ReadableMap');
return wrapOptional('ReadableMap', isRequired);
case 'ArrayTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableArray');
return wrapNullable('ReadableArray');
return wrapOptional('ReadableArray', isRequired);
case 'FunctionTypeAnnotation':
imports.add('com.facebook.react.bridge.Callback');
return wrapNullable('Callback');
return wrapOptional('Callback', isRequired);
default:
(realTypeAnnotation.type: 'MixedTypeAnnotation');
throw new Error(createErrorMessage(realTypeAnnotation.type));
@@ -200,14 +196,12 @@ function translateFunctionReturnTypeToJavaType(
nullableReturnTypeAnnotation,
);
function wrapNullable(javaType: string, nullableType?: string) {
if (nullable) {
imports.add('javax.annotation.Nullable');
return `@Nullable ${nullableType ?? javaType}`;
}
return javaType;
if (nullable) {
imports.add('javax.annotation.Nullable');
}
const isRequired = !nullable;
// FIXME: support class alias for args
let realTypeAnnotation = returnTypeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {
@@ -218,7 +212,7 @@ function translateFunctionReturnTypeToJavaType(
case 'ReservedTypeAnnotation':
switch (realTypeAnnotation.name) {
case 'RootTag':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
default:
(realTypeAnnotation.name: empty);
throw new Error(createErrorMessage(realTypeAnnotation.name));
@@ -228,35 +222,35 @@ function translateFunctionReturnTypeToJavaType(
case 'PromiseTypeAnnotation':
return 'void';
case 'StringTypeAnnotation':
return wrapNullable('String');
return wrapOptional('String', isRequired);
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'FloatTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'DoubleTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'Int32TypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'BooleanTypeAnnotation':
return wrapNullable('boolean', 'Boolean');
return wrapOptional('boolean', isRequired);
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'StringTypeAnnotation':
return wrapNullable('String');
return wrapOptional('String', isRequired);
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
return wrapOptional('double', isRequired);
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return wrapNullable('WritableMap');
return wrapOptional('WritableMap', isRequired);
case 'StringTypeAnnotation':
return wrapNullable('String');
return wrapOptional('String', isRequired);
default:
throw new Error(
`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`,
@@ -264,13 +258,13 @@ function translateFunctionReturnTypeToJavaType(
}
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return wrapNullable('WritableMap');
return wrapOptional('WritableMap', isRequired);
case 'GenericObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return wrapNullable('WritableMap');
return wrapOptional('WritableMap', isRequired);
case 'ArrayTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableArray');
return wrapNullable('WritableArray');
return wrapOptional('WritableArray', isRequired);
default:
(realTypeAnnotation.type: 'MixedTypeAnnotation');
throw new Error(createErrorMessage(realTypeAnnotation.type));
@@ -15,6 +15,10 @@ import type {ConstantsStruct, StructTypeAnnotation} from '../StructCollector';
import type {StructSerilizationOutput} from './serializeStruct';
const {unwrapNullable} = require('../../../../parsers/parsers-commons');
const {wrapOptional: wrapCxxOptional} = require('../../../TypeUtils/Cxx');
const {
wrapOptional: wrapObjCOptional,
} = require('../../../TypeUtils/Objective-C');
const {capitalize} = require('../../../Utils');
const {getNamespacedStructName, getSafePropertyName} = require('../Utils');
@@ -78,15 +82,12 @@ function toObjCType(
): string {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
const isRequired = !nullable && !isOptional;
const wrapOptional = (type: string) => {
return isRequired ? type : `std::optional<${type}>`;
};
switch (typeAnnotation.type) {
case 'ReservedTypeAnnotation':
switch (typeAnnotation.name) {
case 'RootTag':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
default:
(typeAnnotation.name: empty);
throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`);
@@ -94,19 +95,19 @@ function toObjCType(
case 'StringTypeAnnotation':
return 'NSString *';
case 'NumberTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'FloatTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'Int32TypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'DoubleTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'BooleanTypeAnnotation':
return wrapOptional('bool');
return wrapCxxOptional('bool', isRequired);
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'StringTypeAnnotation':
return 'NSString *';
default:
@@ -115,17 +116,18 @@ function toObjCType(
);
}
case 'GenericObjectTypeAnnotation':
return isRequired ? 'id<NSObject> ' : 'id<NSObject> _Nullable ';
return wrapObjCOptional('id<NSObject>', isRequired);
case 'ArrayTypeAnnotation':
if (typeAnnotation.elementType == null) {
return isRequired ? 'id<NSObject> ' : 'id<NSObject> _Nullable ';
return wrapObjCOptional('id<NSObject>', isRequired);
}
return wrapOptional(
return wrapCxxOptional(
`std::vector<${toObjCType(
hasteModuleName,
typeAnnotation.elementType,
)}>`,
isRequired,
);
case 'TypeAliasTypeAnnotation':
const structName = capitalize(typeAnnotation.name);
@@ -133,7 +135,7 @@ function toObjCType(
hasteModuleName,
structName,
);
return wrapOptional(`${namespacedStructName}::Builder`);
return wrapCxxOptional(`${namespacedStructName}::Builder`, isRequired);
default:
(typeAnnotation.type: empty);
throw new Error(
@@ -15,6 +15,10 @@ import type {RegularStruct, StructTypeAnnotation} from '../StructCollector';
import type {StructSerilizationOutput} from './serializeStruct';
const {unwrapNullable} = require('../../../../parsers/parsers-commons');
const {wrapOptional: wrapCxxOptional} = require('../../../TypeUtils/Cxx');
const {
wrapOptional: wrapObjCOptional,
} = require('../../../TypeUtils/Objective-C');
const {capitalize} = require('../../../Utils');
const {getNamespacedStructName, getSafePropertyName} = require('../Utils');
@@ -69,15 +73,12 @@ function toObjCType(
): string {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
const isRequired = !nullable && !isOptional;
const wrapOptional = (type: string) => {
return isRequired ? type : `std::optional<${type}>`;
};
switch (typeAnnotation.type) {
case 'ReservedTypeAnnotation':
switch (typeAnnotation.name) {
case 'RootTag':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
default:
(typeAnnotation.name: empty);
throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`);
@@ -85,19 +86,19 @@ function toObjCType(
case 'StringTypeAnnotation':
return 'NSString *';
case 'NumberTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'FloatTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'Int32TypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'DoubleTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'BooleanTypeAnnotation':
return wrapOptional('bool');
return wrapCxxOptional('bool', isRequired);
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapOptional('double');
return wrapCxxOptional('double', isRequired);
case 'StringTypeAnnotation':
return 'NSString *';
default:
@@ -106,16 +107,17 @@ function toObjCType(
);
}
case 'GenericObjectTypeAnnotation':
return isRequired ? 'id<NSObject> ' : 'id<NSObject> _Nullable';
return wrapObjCOptional('id<NSObject>', isRequired);
case 'ArrayTypeAnnotation':
if (typeAnnotation.elementType == null) {
return isRequired ? 'id<NSObject> ' : 'id<NSObject> _Nullable';
return wrapObjCOptional('id<NSObject>', isRequired);
}
return wrapOptional(
return wrapCxxOptional(
`facebook::react::LazyVector<${toObjCType(
hasteModuleName,
typeAnnotation.elementType,
)}>`,
isRequired,
);
case 'TypeAliasTypeAnnotation':
const structName = capitalize(typeAnnotation.name);
@@ -123,7 +125,7 @@ function toObjCType(
hasteModuleName,
structName,
);
return wrapOptional(namespacedStructName);
return wrapCxxOptional(namespacedStructName, isRequired);
default:
(typeAnnotation.type: empty);
throw new Error(
@@ -24,6 +24,7 @@ const {
unwrapNullable,
wrapNullable,
} = require('../../../parsers/parsers-commons');
const {wrapOptional} = require('../../TypeUtils/Objective-C');
const {capitalize} = require('../../Utils');
const {getNamespacedStructName} = require('./Utils');
const invariant = require('invariant');
@@ -188,11 +189,7 @@ function getParamObjCType(
): $ReadOnly<{objCType: string, isStruct: boolean}> {
const {name: paramName, typeAnnotation: nullableTypeAnnotation} = param;
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
const notRequired = param.optional || nullable;
function wrapIntoNullableIfNeeded(generatedType: string) {
return nullable ? `${generatedType} _Nullable` : generatedType;
}
const isRequired = !param.optional && !nullable;
const isStruct = (objCType: string) => ({
isStruct: true,
@@ -220,7 +217,7 @@ function getParamObjCType(
* type Animal = {};
* Array<Animal> => NSArray<JS::NativeSampleTurboModule::Animal *>, etc.
*/
return notStruct(wrapIntoNullableIfNeeded('NSArray *'));
return notStruct(wrapOptional('NSArray *', !nullable));
}
}
@@ -251,7 +248,7 @@ function getParamObjCType(
case 'ReservedTypeAnnotation':
switch (structTypeAnnotation.name) {
case 'RootTag':
return notStruct(notRequired ? 'NSNumber *' : 'double');
return notStruct(isRequired ? 'double' : 'NSNumber *');
default:
(structTypeAnnotation.name: empty);
throw new Error(
@@ -259,30 +256,30 @@ function getParamObjCType(
);
}
case 'StringTypeAnnotation':
return notStruct(wrapIntoNullableIfNeeded('NSString *'));
return notStruct(wrapOptional('NSString *', !nullable));
case 'NumberTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
return notStruct(isRequired ? 'double' : 'NSNumber *');
case 'FloatTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
return notStruct(isRequired ? 'double' : 'NSNumber *');
case 'DoubleTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
return notStruct(isRequired ? 'double' : 'NSNumber *');
case 'Int32TypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
return notStruct(isRequired ? 'double' : 'NSNumber *');
case 'BooleanTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'BOOL');
return notStruct(isRequired ? 'BOOL' : 'NSNumber *');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
return notStruct(isRequired ? 'double' : 'NSNumber *');
case 'StringTypeAnnotation':
return notStruct(wrapIntoNullableIfNeeded('NSString *'));
return notStruct(wrapOptional('NSString *', !nullable));
default:
throw new Error(
`Unsupported enum type for param "${paramName}" in ${methodName}. Found: ${typeAnnotation.type}`,
);
}
case 'GenericObjectTypeAnnotation':
return notStruct(wrapIntoNullableIfNeeded('NSDictionary *'));
return notStruct(wrapOptional('NSDictionary *', !nullable));
default:
(structTypeAnnotation.type: empty);
throw new Error(
@@ -296,10 +293,7 @@ function getReturnObjCType(
nullableTypeAnnotation: Nullable<NativeModuleReturnTypeAnnotation>,
): string {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function wrapIntoNullableIfNeeded(generatedType: string) {
return nullable ? `${generatedType} _Nullable` : generatedType;
}
const isRequired = !nullable;
switch (typeAnnotation.type) {
case 'VoidTypeAnnotation':
@@ -307,24 +301,25 @@ function getReturnObjCType(
case 'PromiseTypeAnnotation':
return 'void';
case 'ObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
return wrapOptional('NSDictionary *', isRequired);
case 'TypeAliasTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
return wrapOptional('NSDictionary *', isRequired);
case 'ArrayTypeAnnotation':
if (typeAnnotation.elementType == null) {
return wrapIntoNullableIfNeeded('NSArray<id<NSObject>> *');
return wrapOptional('NSArray<id<NSObject>> *', isRequired);
}
return wrapIntoNullableIfNeeded(
return wrapOptional(
`NSArray<${getReturnObjCType(
methodName,
typeAnnotation.elementType,
)}> *`,
isRequired,
);
case 'ReservedTypeAnnotation':
switch (typeAnnotation.name) {
case 'RootTag':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
default:
(typeAnnotation.name: empty);
throw new Error(
@@ -334,23 +329,23 @@ function getReturnObjCType(
case 'StringTypeAnnotation':
// TODO: Can NSString * returns not be _Nullable?
// In the legacy codegen, we don't surround NSSTring * with _Nullable
return wrapIntoNullableIfNeeded('NSString *');
return wrapOptional('NSString *', isRequired);
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'FloatTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'DoubleTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'Int32TypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'BooleanTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'StringTypeAnnotation':
return wrapIntoNullableIfNeeded('NSString *');
return wrapOptional('NSString *', isRequired);
default:
throw new Error(
`Unsupported enum return type for ${methodName}. Found: ${typeAnnotation.type}`,
@@ -359,20 +354,20 @@ function getReturnObjCType(
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
return wrapOptional('NSNumber *', isRequired);
case 'ObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
return wrapOptional('NSDictionary *', isRequired);
case 'StringTypeAnnotation':
// TODO: Can NSString * returns not be _Nullable?
// In the legacy codegen, we don't surround NSSTring * with _Nullable
return wrapIntoNullableIfNeeded('NSString *');
return wrapOptional('NSString *', isRequired);
default:
throw new Error(
`Unsupported union return type for ${methodName}, found: ${typeAnnotation.memberType}"`,
);
}
case 'GenericObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
return wrapOptional('NSDictionary *', isRequired);
default:
(typeAnnotation.type: 'MixedTypeAnnotation');
throw new Error(