Skip to content

Commit

Permalink
react-native-code-gen Add Union Type support for Java/ObjC TurboModul…
Browse files Browse the repository at this point in the history
…es (#35312)

Summary:
Pull Request resolved: #35312

Changelog:
[General][Added] react-native-code-gen Add Union Type support for Java/ObjC TurboModules

Reviewed By: javache

Differential Revision: D41216605

fbshipit-source-id: d411abed66c694d855ede40725667cbc7067538f
  • Loading branch information
christophpurrer authored and facebook-github-bot committed Nov 15, 2022
1 parent 72d3da1 commit 2eccd59
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ function translateFunctionParamToJavaType(
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
return wrapNullable('ReadableMap');
case 'StringTypeAnnotation':
return wrapNullable('String');
default:
throw new Error(
`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
return wrapNullable('ReadableMap');
Expand All @@ -162,10 +176,7 @@ function translateFunctionParamToJavaType(
imports.add('com.facebook.react.bridge.Callback');
return wrapNullable('Callback');
default:
(realTypeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(realTypeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
}
Expand Down Expand Up @@ -229,6 +240,20 @@ function translateFunctionReturnTypeToJavaType(
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return wrapNullable('WritableMap');
case 'StringTypeAnnotation':
return wrapNullable('String');
default:
throw new Error(
`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return wrapNullable('WritableMap');
Expand All @@ -239,10 +264,7 @@ function translateFunctionReturnTypeToJavaType(
imports.add('com.facebook.react.bridge.WritableArray');
return wrapNullable('WritableArray');
default:
(realTypeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(realTypeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
}
Expand Down Expand Up @@ -294,6 +316,19 @@ function getFalsyReturnStatementFromReturnType(
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return nullable ? 'return null;' : 'return 0;';
case 'ObjectTypeAnnotation':
return 'return null;';
case 'StringTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
default:
throw new Error(
`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'StringTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
case 'ObjectTypeAnnotation':
Expand All @@ -303,10 +338,7 @@ function getFalsyReturnStatementFromReturnType(
case 'ArrayTypeAnnotation':
return 'return null;';
default:
(realTypeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(realTypeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@ function translateReturnTypeToKind(
`Unknown enum prop type for returning value, found: ${realTypeAnnotation.type}"`,
);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'ObjectTypeAnnotation':
return 'ObjectKind';
case 'StringTypeAnnotation':
return 'StringKind';
default:
throw new Error(
`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'DoubleTypeAnnotation':
Expand All @@ -182,10 +195,7 @@ function translateReturnTypeToKind(
case 'ArrayTypeAnnotation':
return 'ArrayKind';
default:
(realTypeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(realTypeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(
`Unknown prop type for returning value, found: ${realTypeAnnotation.type}"`,
);
Expand Down Expand Up @@ -234,6 +244,19 @@ function translateParamTypeToJniType(
`Unknown enum prop type for method arg, found: ${realTypeAnnotation.type}"`,
);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'ObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/ReadableMap;';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
default:
throw new Error(
`Unsupported union prop value, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'NumberTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'DoubleTypeAnnotation':
Expand All @@ -251,10 +274,7 @@ function translateParamTypeToJniType(
case 'FunctionTypeAnnotation':
return 'Lcom/facebook/react/bridge/Callback;';
default:
(realTypeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(realTypeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(
`Unknown prop type for method arg, found: ${realTypeAnnotation.type}"`,
);
Expand Down Expand Up @@ -300,6 +320,19 @@ function translateReturnTypeToJniType(
`Unknown enum prop type for method return type, found: ${realTypeAnnotation.type}"`,
);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'ObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/WritableMap;';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
default:
throw new Error(
`Unsupported union member type, found: ${realTypeAnnotation.memberType}"`,
);
}
case 'NumberTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'DoubleTypeAnnotation':
Expand All @@ -317,10 +350,7 @@ function translateReturnTypeToJniType(
case 'ArrayTypeAnnotation':
return 'Lcom/facebook/react/bridge/WritableArray;';
default:
(realTypeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(realTypeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(
`Unknown prop type for method return type, found: ${realTypeAnnotation.type}"`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,25 @@ function getReturnObjCType(
`Unsupported enum return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'ObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
case 'StringTypeAnnotation':
// TODO: Can NSString * returns not be _Nullable?
// In the legacy codegen, we don't surround NSSTring * with _Nullable
return wrapIntoNullableIfNeeded('NSString *');
default:
throw new Error(
`Unsupported union return type for ${methodName}, found: ${typeAnnotation.memberType}"`,
);
}
case 'GenericObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
default:
(typeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(typeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
Expand Down Expand Up @@ -413,11 +425,21 @@ function getReturnJSType(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'ObjectTypeAnnotation':
return 'ObjectKind';
case 'StringTypeAnnotation':
return 'StringKind';
default:
throw new Error(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
}
default:
(typeAnnotation.type:
| 'EnumDeclaration'
| 'MixedTypeAnnotation'
| 'UnionTypeAnnotation');
(typeAnnotation.type: 'EnumDeclaration' | 'MixedTypeAnnotation');
throw new Error(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,35 @@ export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;

const NATIVE_MODULE_WITH_UNION = `
/**
* 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-local
* @format
*/
'use strict';
import type {TurboModule} from '../RCTExport';
import * as TurboModuleRegistry from '../TurboModuleRegistry';
export type ChooseInt = 1 | 2 | 3;
export type ChooseFloat = 1.44 | 2.88 | 5.76;
export type ChooseObject = {} | {low: string};
export type ChooseString = 'One' | 'Two' | 'Three';
export interface Spec extends TurboModule {
+getUnion: (chooseInt: ChooseInt, chooseFloat: ChooseFloat, chooseObject: ChooseObject, chooseString: ChooseString) => ChooseObject;
}
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;

const ANDROID_ONLY_NATIVE_MODULE = `
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
Expand Down Expand Up @@ -671,6 +700,7 @@ module.exports = {
NATIVE_MODULE_WITH_ARRAY_WITH_ALIAS,
NATIVE_MODULE_WITH_BASIC_PARAM_TYPES,
NATIVE_MODULE_WITH_CALLBACK,
NATIVE_MODULE_WITH_UNION,
EMPTY_NATIVE_MODULE,
ANDROID_ONLY_NATIVE_MODULE,
IOS_ONLY_NATIVE_MODULE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,69 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_SIMPLE_O
}"
`;

exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION 1`] = `
"{
'modules': {
'NativeSampleTurboModule': {
'type': 'NativeModule',
'aliases': {},
'spec': {
'properties': [
{
'name': 'getUnion',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'ObjectTypeAnnotation'
},
'params': [
{
'name': 'chooseInt',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'NumberTypeAnnotation'
}
},
{
'name': 'chooseFloat',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'NumberTypeAnnotation'
}
},
{
'name': 'chooseObject',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'ObjectTypeAnnotation'
}
},
{
'name': 'chooseString',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
}
}
]
}
}
]
},
'moduleNames': [
'SampleTurboModule'
]
}
}
}"
`;

exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNSAFE_OBJECT 1`] = `
"{
'modules': {
Expand Down

0 comments on commit 2eccd59

Please sign in to comment.