Parse string unions as StringLiteralUnionTypeAnnotation (#46845)

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

Previously, the parser was throwing away the values of a string union when storing it in the schema. It would only store the union as

```
{
  type: 'UnionTypeAnnotation',
  memberType: 'StringTypeAnnotation'
}
```

We now track the string literals through the parser and store them in the schema:

```
{
  type: 'StringLiteralUnionTypeAnnotation',
  types: [
    {
      type: 'StringLiteralTypeAnnotation'
      value: 'light'
    },
    {
      type: 'StringLiteralTypeAnnotation'
      value: 'dark'
    },
  ],
}
```

We aren't changing the generators, those still just output "string". They could eventually be made smarter.

The value of this is that the compat checker can now error when the union changes.

Changelog: [Internal]

Reviewed By: yungsters

Differential Revision: D63917685

fbshipit-source-id: 34a10e1f1910d2935837a3659f66049fd4473134
This commit is contained in:
Eli White
2024-10-07 16:56:04 -07:00
committed by Facebook GitHub Bot
parent 1ffef5669c
commit a669de1dd2
26 changed files with 351 additions and 57 deletions
+7
View File
@@ -295,6 +295,11 @@ export interface NativeModuleStringLiteralTypeAnnotation {
readonly value: string;
}
export interface NativeModuleStringLiteralUnionTypeAnnotation {
readonly type: 'StringLiteralUnionTypeAnnotation';
readonly types: NativeModuleStringLiteralTypeAnnotation[];
}
export interface NativeModuleNumberTypeAnnotation {
readonly type: 'NumberTypeAnnotation';
}
@@ -377,6 +382,7 @@ export type NativeModuleEventEmitterBaseTypeAnnotation =
| NativeModuleNumberTypeAnnotation
| NativeModuleStringTypeAnnotation
| NativeModuleStringLiteralTypeAnnotation
| NativeModuleStringLiteralUnionTypeAnnotation
| NativeModuleTypeAliasTypeAnnotation
| NativeModuleGenericObjectTypeAnnotation
| VoidTypeAnnotation;
@@ -391,6 +397,7 @@ export type NativeModuleEventEmitterTypeAnnotation =
export type NativeModuleBaseTypeAnnotation =
| NativeModuleStringTypeAnnotation
| NativeModuleStringLiteralTypeAnnotation
| NativeModuleStringLiteralUnionTypeAnnotation
| NativeModuleNumberTypeAnnotation
| NativeModuleInt32TypeAnnotation
| NativeModuleDoubleTypeAnnotation
+7
View File
@@ -46,6 +46,11 @@ export type StringLiteralTypeAnnotation = $ReadOnly<{
value: string,
}>;
export type StringLiteralUnionTypeAnnotation = $ReadOnly<{
type: 'StringLiteralUnionTypeAnnotation',
types: $ReadOnlyArray<StringLiteralTypeAnnotation>,
}>;
export type StringEnumTypeAnnotation = $ReadOnly<{
type: 'StringEnumTypeAnnotation',
options: $ReadOnlyArray<string>,
@@ -363,6 +368,7 @@ type NativeModuleEventEmitterBaseTypeAnnotation =
| NativeModuleNumberTypeAnnotation
| StringTypeAnnotation
| StringLiteralTypeAnnotation
| StringLiteralUnionTypeAnnotation
| NativeModuleTypeAliasTypeAnnotation
| NativeModuleGenericObjectTypeAnnotation
| VoidTypeAnnotation;
@@ -377,6 +383,7 @@ export type NativeModuleEventEmitterTypeAnnotation =
export type NativeModuleBaseTypeAnnotation =
| StringTypeAnnotation
| StringLiteralTypeAnnotation
| StringLiteralUnionTypeAnnotation
| NativeModuleNumberTypeAnnotation
| Int32TypeAnnotation
| DoubleTypeAnnotation
@@ -163,6 +163,8 @@ function serializeArg(
return wrap(val => `${val}.asString(rt)`);
case 'StringLiteralTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'StringLiteralUnionTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
case 'BooleanTypeAnnotation':
return wrap(val => `${val}.asBool()`);
case 'EnumDeclaration':
@@ -175,6 +175,8 @@ function translatePrimitiveJSTypeToCpp(
return wrapOptional('jsi::String', isRequired);
case 'StringLiteralTypeAnnotation':
return wrapOptional('jsi::String', isRequired);
case 'StringLiteralUnionTypeAnnotation':
return wrapOptional('jsi::String', isRequired);
case 'NumberTypeAnnotation':
return wrapOptional('double', isRequired);
case 'DoubleTypeAnnotation':
@@ -133,6 +133,8 @@ function translateEventEmitterTypeToJavaType(
return 'String';
case 'StringLiteralTypeAnnotation':
return 'String';
case 'StringLiteralUnionTypeAnnotation':
return 'String';
case 'NumberTypeAnnotation':
case 'FloatTypeAnnotation':
case 'DoubleTypeAnnotation':
@@ -197,6 +199,8 @@ function translateFunctionParamToJavaType(
return wrapOptional('String', isRequired);
case 'StringLiteralTypeAnnotation':
return wrapOptional('String', isRequired);
case 'StringLiteralUnionTypeAnnotation':
return wrapOptional('String', isRequired);
case 'NumberTypeAnnotation':
return wrapOptional('double', isRequired);
case 'FloatTypeAnnotation':
@@ -289,6 +293,8 @@ function translateFunctionReturnTypeToJavaType(
return wrapOptional('String', isRequired);
case 'StringLiteralTypeAnnotation':
return wrapOptional('String', isRequired);
case 'StringLiteralUnionTypeAnnotation':
return wrapOptional('String', isRequired);
case 'NumberTypeAnnotation':
return wrapOptional('double', isRequired);
case 'FloatTypeAnnotation':
@@ -401,6 +407,8 @@ function getFalsyReturnStatementFromReturnType(
return nullable ? 'return null;' : 'return "";';
case 'StringLiteralTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
case 'StringLiteralUnionTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
case 'ObjectTypeAnnotation':
return 'return null;';
case 'GenericObjectTypeAnnotation':
@@ -167,6 +167,8 @@ function translateReturnTypeToKind(
return 'StringKind';
case 'StringLiteralTypeAnnotation':
return 'StringKind';
case 'StringLiteralUnionTypeAnnotation':
return 'StringKind';
case 'BooleanTypeAnnotation':
return 'BooleanKind';
case 'EnumDeclaration':
@@ -248,6 +250,8 @@ function translateParamTypeToJniType(
return 'Ljava/lang/String;';
case 'StringLiteralTypeAnnotation':
return 'Ljava/lang/String;';
case 'StringLiteralUnionTypeAnnotation':
return 'Ljava/lang/String;';
case 'BooleanTypeAnnotation':
return !isRequired ? 'Ljava/lang/Boolean;' : 'Z';
case 'EnumDeclaration':
@@ -326,6 +330,8 @@ function translateReturnTypeToJniType(
return 'Ljava/lang/String;';
case 'StringLiteralTypeAnnotation':
return 'Ljava/lang/String;';
case 'StringLiteralUnionTypeAnnotation':
return 'Ljava/lang/String;';
case 'BooleanTypeAnnotation':
return nullable ? 'Ljava/lang/Boolean;' : 'Z';
case 'EnumDeclaration':
@@ -23,6 +23,7 @@ import type {
NativeModuleObjectTypeAnnotation,
StringTypeAnnotation,
StringLiteralTypeAnnotation,
StringLiteralUnionTypeAnnotation,
NativeModuleTypeAliasTypeAnnotation,
Nullable,
ReservedTypeAnnotation,
@@ -60,6 +61,7 @@ export type StructProperty = $ReadOnly<{
export type StructTypeAnnotation =
| StringTypeAnnotation
| StringLiteralTypeAnnotation
| StringLiteralUnionTypeAnnotation
| NativeModuleNumberTypeAnnotation
| Int32TypeAnnotation
| DoubleTypeAnnotation
@@ -96,6 +96,8 @@ function toObjCType(
return 'NSString *';
case 'StringLiteralTypeAnnotation':
return 'NSString *';
case 'StringLiteralUnionTypeAnnotation':
return 'NSString *';
case 'NumberTypeAnnotation':
return wrapCxxOptional('double', isRequired);
case 'FloatTypeAnnotation':
@@ -177,6 +179,8 @@ function toObjCValue(
return value;
case 'StringLiteralTypeAnnotation':
return value;
case 'StringLiteralUnionTypeAnnotation':
return value;
case 'NumberTypeAnnotation':
return wrapPrimitive('double');
case 'FloatTypeAnnotation':
@@ -87,6 +87,8 @@ function toObjCType(
return 'NSString *';
case 'StringLiteralTypeAnnotation':
return 'NSString *';
case 'StringLiteralUnionTypeAnnotation':
return 'NSString *';
case 'NumberTypeAnnotation':
return wrapCxxOptional('double', isRequired);
case 'FloatTypeAnnotation':
@@ -167,6 +169,8 @@ function toObjCValue(
return RCTBridgingTo('String');
case 'StringLiteralTypeAnnotation':
return RCTBridgingTo('String');
case 'StringLiteralUnionTypeAnnotation':
return RCTBridgingTo('String');
case 'NumberTypeAnnotation':
return RCTBridgingTo('Double');
case 'FloatTypeAnnotation':
@@ -22,6 +22,8 @@ function getEventEmitterTypeObjCType(
return 'NSString *_Nonnull';
case 'StringLiteralTypeAnnotation':
return 'NSString *_Nonnull';
case 'StringLiteralUnionTypeAnnotation':
return 'NSString *_Nonnull';
case 'NumberTypeAnnotation':
return 'NSNumber *_Nonnull';
case 'BooleanTypeAnnotation':
@@ -259,6 +259,8 @@ function getParamObjCType(
return notStruct(wrapOptional('NSString *', !nullable));
case 'StringLiteralTypeAnnotation':
return notStruct(wrapOptional('NSString *', !nullable));
case 'StringLiteralUnionTypeAnnotation':
return notStruct(wrapOptional('NSString *', !nullable));
case 'NumberTypeAnnotation':
return notStruct(isRequired ? 'double' : 'NSNumber *');
case 'FloatTypeAnnotation':
@@ -336,6 +338,10 @@ function getReturnObjCType(
// TODO: Can NSString * returns not be _Nullable?
// In the legacy codegen, we don't surround NSSTring * with _Nullable
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':
return wrapOptional('NSNumber *', isRequired);
case 'FloatTypeAnnotation':
@@ -404,6 +410,8 @@ function getReturnJSType(
return 'StringKind';
case 'StringLiteralTypeAnnotation':
return 'StringKind';
case 'StringLiteralUnionTypeAnnotation':
return 'StringKind';
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'FloatTypeAnnotation':
@@ -2316,6 +2316,23 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
memberType: 'StringTypeAnnotation',
},
},
{
name: 'y-literal',
optional: false,
typeAnnotation: {
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation',
value: 'foo',
},
{
type: 'StringLiteralTypeAnnotation',
value: 'bar',
},
],
},
},
{
name: 'z',
optional: false,
@@ -2626,6 +2643,23 @@ const UNION_MODULE: SchemaType = {
memberType: 'StringTypeAnnotation',
},
},
{
name: 'chooseStringLiteral',
optional: false,
typeAnnotation: {
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation',
value: 'foo',
},
{
type: 'StringLiteralTypeAnnotation',
value: 'bar',
},
],
},
},
],
},
},
@@ -216,7 +216,8 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi:
rt,
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt)
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asString(rt),
count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asObject(rt)
);
}
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
@@ -309,7 +310,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared
methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject};
methodMap_[\\"getSet\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getSet};
methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString};
methodMap_[\\"getUnion\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion};
methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion};
methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue};
methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback};
methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise};
@@ -764,13 +765,14 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi:
count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(),
count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asNumber(),
count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt),
count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asString(rt)
count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asString(rt),
count <= 4 ? throw jsi::JSError(rt, \\"Expected argument in position 4 to be passed\\") : args[4].asString(rt)
);
}
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule(\\"SampleTurboModule\\", jsInvoker) {
methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion};
methodMap_[\\"getUnion\\"] = MethodMetadata {5, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion};
}
@@ -693,7 +693,7 @@ public:
virtual jsi::Object getObject(jsi::Runtime &rt, jsi::Object arg) = 0;
virtual jsi::Array getSet(jsi::Runtime &rt, jsi::Array arg) = 0;
virtual jsi::String getString(jsi::Runtime &rt, jsi::String arg) = 0;
virtual jsi::String getUnion(jsi::Runtime &rt, double x, jsi::String y, jsi::Object z) = 0;
virtual jsi::String getUnion(jsi::Runtime &rt, double x, jsi::String y, jsi::String y-literal, jsi::Object z) = 0;
virtual jsi::Object getValue(jsi::Runtime &rt, double x, jsi::String y, jsi::Object z) = 0;
virtual void getValueWithCallback(jsi::Runtime &rt, jsi::Function callback) = 0;
virtual jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) = 0;
@@ -855,13 +855,13 @@ private:
return bridging::callFromJs<jsi::String>(
rt, &T::getString, jsInvoker_, instance_, std::move(arg));
}
jsi::String getUnion(jsi::Runtime &rt, double x, jsi::String y, jsi::Object z) override {
jsi::String getUnion(jsi::Runtime &rt, double x, jsi::String y, jsi::String y-literal, jsi::Object z) override {
static_assert(
bridging::getParameterCount(&T::getUnion) == 4,
\\"Expected getUnion(...) to have 4 parameters\\");
bridging::getParameterCount(&T::getUnion) == 5,
\\"Expected getUnion(...) to have 5 parameters\\");
return bridging::callFromJs<jsi::String>(
rt, &T::getUnion, jsInvoker_, instance_, std::move(x), std::move(y), std::move(z));
rt, &T::getUnion, jsInvoker_, instance_, std::move(x), std::move(y), std::move(y-literal), std::move(z));
}
jsi::Object getValue(jsi::Runtime &rt, double x, jsi::String y, jsi::Object z) override {
static_assert(
@@ -2520,7 +2520,7 @@ protected:
NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
public:
virtual jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString) = 0;
virtual jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString, jsi::String chooseStringLiteral) = 0;
};
@@ -2551,13 +2551,13 @@ private:
}
jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString) override {
jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString, jsi::String chooseStringLiteral) override {
static_assert(
bridging::getParameterCount(&T::getUnion) == 5,
\\"Expected getUnion(...) to have 5 parameters\\");
bridging::getParameterCount(&T::getUnion) == 6,
\\"Expected getUnion(...) to have 6 parameters\\");
return bridging::callFromJs<jsi::Object>(
rt, &T::getUnion, jsInvoker_, instance_, std::move(chooseInt), std::move(chooseFloat), std::move(chooseObject), std::move(chooseString));
rt, &T::getUnion, jsInvoker_, instance_, std::move(chooseInt), std::move(chooseFloat), std::move(chooseObject), std::move(chooseString), std::move(chooseStringLiteral));
}
private:
@@ -1292,7 +1292,8 @@ Map {
- (NSDictionary *)getUnion:(double)chooseInt
chooseFloat:(double)chooseFloat
chooseObject:(NSDictionary *)chooseObject
chooseString:(NSString *)chooseString;
chooseString:(NSString *)chooseString
chooseStringLiteral:(NSString *)chooseStringLiteral;
@end
@@ -678,7 +678,7 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo
@ReactMethod(isBlockingSynchronousMethod = true)
@DoNotStrip
public abstract WritableMap getUnion(double chooseInt, double chooseFloat, ReadableMap chooseObject, String chooseString);
public abstract WritableMap getUnion(double chooseInt, double chooseFloat, ReadableMap chooseObject, String chooseString, String chooseStringLiteral);
}
",
}
@@ -571,12 +571,12 @@ namespace facebook::react {
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
static jmethodID cachedMethodId = nullptr;
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getUnion\\", \\"(DDLcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;)Lcom/facebook/react/bridge/WritableMap;\\", args, count, cachedMethodId);
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getUnion\\", \\"(DDLcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;Ljava/lang/String;)Lcom/facebook/react/bridge/WritableMap;\\", args, count, cachedMethodId);
}
NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) {
methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion};
methodMap_[\\"getUnion\\"] = MethodMetadata {5, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion};
}
std::shared_ptr<TurboModule> union_module_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams &params) {
@@ -784,13 +784,13 @@ Map {
namespace facebook::react {
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getUnion\\", @selector(getUnion:chooseFloat:chooseObject:chooseString:), args, count);
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getUnion\\", @selector(getUnion:chooseFloat:chooseObject:chooseString:chooseStringLiteral:), args, count);
}
NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams &params)
: ObjCTurboModule(params) {
methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion};
methodMap_[\\"getUnion\\"] = MethodMetadata {5, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion};
}
} // namespace facebook::react
@@ -862,8 +862,8 @@ describe('emitUnion', () => {
const typeAnnotation = {
type: 'UnionTypeAnnotation',
types: [
{type: 'StringLiteralTypeAnnotation'},
{type: 'StringLiteralTypeAnnotation'},
{type: 'StringLiteralTypeAnnotation', value: 'foo'},
{type: 'StringLiteralTypeAnnotation', value: 'bar'},
],
};
describe('when nullable is true', () => {
@@ -878,8 +878,17 @@ describe('emitUnion', () => {
const expected = {
type: 'NullableTypeAnnotation',
typeAnnotation: {
type: 'UnionTypeAnnotation',
memberType: 'StringTypeAnnotation',
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation',
value: 'foo',
},
{
type: 'StringLiteralTypeAnnotation',
value: 'bar',
},
],
},
};
@@ -897,8 +906,17 @@ describe('emitUnion', () => {
);
const expected = {
type: 'UnionTypeAnnotation',
memberType: 'StringTypeAnnotation',
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation',
value: 'foo',
},
{
type: 'StringLiteralTypeAnnotation',
value: 'bar',
},
],
};
expect(result).toEqual(expected);
@@ -955,8 +973,8 @@ describe('emitUnion', () => {
const typeAnnotation = {
type: 'UnionTypeAnnotation',
types: [
{type: 'NumberLiteralTypeAnnotation'},
{type: 'StringLiteralTypeAnnotation'},
{type: 'NumberLiteralTypeAnnotation', value: 'foo'},
{type: 'StringLiteralTypeAnnotation', value: 'bar'},
{type: 'ObjectTypeAnnotation'},
],
};
@@ -1002,11 +1020,11 @@ describe('emitUnion', () => {
types: [
{
type: 'TSLiteralType',
literal: {type: 'NumericLiteral'},
literal: {type: 'NumericLiteral', value: 4},
},
{
type: 'TSLiteralType',
literal: {type: 'NumericLiteral'},
literal: {type: 'NumericLiteral', value: 5},
},
],
};
@@ -1056,11 +1074,11 @@ describe('emitUnion', () => {
types: [
{
type: 'TSLiteralType',
literal: {type: 'StringLiteral'},
literal: {type: 'StringLiteral', value: 'foo'},
},
{
type: 'TSLiteralType',
literal: {type: 'StringLiteral'},
literal: {type: 'StringLiteral', value: 'bar'},
},
],
};
@@ -1076,8 +1094,17 @@ describe('emitUnion', () => {
const expected = {
type: 'NullableTypeAnnotation',
typeAnnotation: {
type: 'UnionTypeAnnotation',
memberType: 'StringTypeAnnotation',
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation',
value: 'foo',
},
{
type: 'StringLiteralTypeAnnotation',
value: 'bar',
},
],
},
};
@@ -1095,8 +1122,17 @@ describe('emitUnion', () => {
);
const expected = {
type: 'UnionTypeAnnotation',
memberType: 'StringTypeAnnotation',
type: 'StringLiteralUnionTypeAnnotation',
types: [
{
type: 'StringLiteralTypeAnnotation',
value: 'foo',
},
{
type: 'StringLiteralTypeAnnotation',
value: 'bar',
},
],
};
expect(result).toEqual(expected);
@@ -1162,11 +1198,11 @@ describe('emitUnion', () => {
types: [
{
type: 'TSLiteralType',
literal: {type: 'NumericLiteral'},
literal: {type: 'NumericLiteral', value: 4},
},
{
type: 'TSLiteralType',
literal: {type: 'StringLiteral'},
literal: {type: 'StringLiteral', value: 'foo'},
},
{
type: 'TSLiteralType',
@@ -396,8 +396,21 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
'name': 'chooseString',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'One'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Two'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Three'
}
]
}
}
]
@@ -2286,8 +2299,21 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION 1`
'name': 'chooseString',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'One'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Two'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Three'
}
]
}
}
]
@@ -2317,8 +2343,17 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION_RE
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'light'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'dark'
}
]
},
'params': []
}
@@ -2336,8 +2371,17 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION_RE
'name': 'strings',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'light'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'dark'
}
]
}
}
]
@@ -2602,8 +2646,25 @@ exports[`RN Codegen Flow Parser can generate fixture PROMISE_WITH_COMMONLY_USED_
'returnTypeAnnotation': {
'type': 'PromiseTypeAnnotation',
'elementType': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Spring'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Summer'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Autumn'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Winter'
}
]
}
},
'params': []
@@ -117,6 +117,12 @@ class FlowParser implements Parser {
return [...new Set(membersTypes.map(remapLiteral))];
}
getStringLiteralUnionTypeAnnotationStringLiterals(
membersTypes: $FlowFixMe[],
): string[] {
return membersTypes.map((item: $FlowFixMe) => item.value);
}
parseFile(filename: string): SchemaType {
const contents = fs.readFileSync(filename, 'utf8');
+8
View File
@@ -146,6 +146,14 @@ export interface Parser {
remapUnionTypeAnnotationMemberNames(
types: $FlowFixMe,
): UnionTypeAnnotationMemberType[];
/**
* Given a union annotation members types, it returns an array of string literals.
* @parameter membersTypes: union annotation members types
* @returns: an array of string literals.
*/
getStringLiteralUnionTypeAnnotationStringLiterals(
types: $FlowFixMe,
): string[];
/**
* Given the name of a file, it returns a Schema.
* @parameter filename: the name of the file.
@@ -109,6 +109,12 @@ export class MockedParser implements Parser {
return [];
}
getStringLiteralUnionTypeAnnotationStringLiterals(
membersTypes: $FlowFixMe[],
): string[] {
return [];
}
parseFile(filename: string): SchemaType {
return schemaMock;
}
@@ -35,6 +35,7 @@ import type {
ReservedTypeAnnotation,
StringTypeAnnotation,
StringLiteralTypeAnnotation,
StringLiteralUnionTypeAnnotation,
VoidTypeAnnotation,
} from '../CodegenSchema';
import type {Parser} from './parser';
@@ -409,7 +410,14 @@ function emitUnion(
hasteModuleName: string,
typeAnnotation: $FlowFixMe,
parser: Parser,
): Nullable<NativeModuleUnionTypeAnnotation> {
): Nullable<
NativeModuleUnionTypeAnnotation | StringLiteralUnionTypeAnnotation,
> {
// 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,
);
@@ -423,12 +431,42 @@ function emitUnion(
);
}
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(
nullable: boolean,
hasteModuleName: string,
typeAnnotation: $FlowFixMe,
parser: Parser,
): Nullable<StringLiteralUnionTypeAnnotation> {
const stringLiterals =
parser.getStringLiteralUnionTypeAnnotationStringLiterals(
typeAnnotation.types,
);
return wrapNullable(nullable, {
type: 'StringLiteralUnionTypeAnnotation',
types: stringLiterals.map(stringLiteral => ({
type: 'StringLiteralTypeAnnotation',
value: stringLiteral,
})),
});
}
function translateArrayTypeAnnotation(
hasteModuleName: string,
types: TypeDeclarationMap,
@@ -387,8 +387,21 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
'name': 'chooseString',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'One'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Two'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Three'
}
]
}
}
]
@@ -2764,8 +2777,21 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UN
'name': 'chooseString',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'One'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Two'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'Three'
}
]
}
}
]
@@ -2795,8 +2821,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UN
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'light'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'dark'
}
]
},
'params': []
}
@@ -2814,8 +2849,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UN
'name': 'strings',
'optional': false,
'typeAnnotation': {
'type': 'UnionTypeAnnotation',
'memberType': 'StringTypeAnnotation'
'type': 'StringLiteralUnionTypeAnnotation',
'types': [
{
'type': 'StringLiteralTypeAnnotation',
'value': 'light'
},
{
'type': 'StringLiteralTypeAnnotation',
'value': 'dark'
}
]
}
}
]
@@ -117,6 +117,12 @@ class TypeScriptParser implements Parser {
return [...new Set(membersTypes.map(remapLiteral))];
}
getStringLiteralUnionTypeAnnotationStringLiterals(
membersTypes: $FlowFixMe[],
): string[] {
return membersTypes.map((item: $FlowFixMe) => item.literal.value);
}
parseFile(filename: string): SchemaType {
const contents = fs.readFileSync(filename, 'utf8');