Skip to content

Commit

Permalink
Parse and collect enum members in module specs
Browse files Browse the repository at this point in the history
Summary:
> **Notice**: This commit does not change any behaviour.

Parse and collect enum members in module specs instead of the current behaviour of parsing enum members as 'string' / 'number' and ignoring the member names.

This commit would allow us to generate native Enums corresponding to the schema's enums.

Prior to this commit, enum params were parsed as:
```
                {
                  'name': 'qualityParam',
                  'optional': false,
                  'typeAnnotation': {
                    'type': 'EnumDeclaration',
                    'memberType': 'StringTypeAnnotation'
                  }
                },
```

The name of the enum type and the members of the enum type were ignored.

After this commit, parsed modules would hold a new object member called `enumMap` that would look like this:
```

      'enumMap': {
        'QualityEnum': {
          'type': 'EnumDeclaration',
          'name': 'QualityEnum',
          'memberType': 'StringTypeAnnotation',
          'members': [
            {
              'name': 'SD',
              'value': 'sd'
            },
            {
              'name': 'HD',
              'value': 'hd'
            }
          ]
        },
        // ...
      }
```
And enum params would be exported as:
```
	        {
                  'name': 'qualityParam',
                  'optional': false,
                  'typeAnnotation': {
                    'name': 'NativeModuleEnumTypeAnnotation',
                    'type': 'EnumDeclaration',
                    'memberType': 'StringTypeAnnotation'
                  }
                },
```

Combining the two new outputs would allow us to generate Native enums in the Native generators.

Changelog: [Internal] Parse and collect enum members in module specs

Differential Revision: https://www.internalfb.com/diff/D42778258?entry_point=27

fbshipit-source-id: b68597ff3dd6485a604d5bffdf1c60f1d1bfa15b
  • Loading branch information
Vitali Zaidman authored and facebook-github-bot committed Feb 1, 2023
1 parent 1f5976c commit d0aec9a
Show file tree
Hide file tree
Showing 20 changed files with 861 additions and 169 deletions.
26 changes: 25 additions & 1 deletion packages/react-native-codegen/src/CodegenSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ export type NullableTypeAnnotation<+T: NativeModuleTypeAnnotation> = $ReadOnly<{
export type NativeModuleSchema = $ReadOnly<{
type: 'NativeModule',
aliasMap: NativeModuleAliasMap,
enumMap: NativeModuleEnumMap,
spec: NativeModuleSpec,
moduleName: string,
// Use for modules that are not used on other platforms.
Expand All @@ -239,6 +240,10 @@ export type NativeModulePropertyShape = NamedShape<
Nullable<NativeModuleFunctionTypeAnnotation>,
>;

export type NativeModuleEnumMap = $ReadOnly<{
[enumName: string]: NativeModuleEnumDeclarationWithMembers,
}>;

export type NativeModuleAliasMap = $ReadOnly<{
[aliasName: string]: NativeModuleObjectTypeAnnotation,
}>;
Expand Down Expand Up @@ -287,11 +292,30 @@ export type NativeModuleBooleanTypeAnnotation = $ReadOnly<{
type: 'BooleanTypeAnnotation',
}>;

export type NativeModuleEnumMembers = $ReadOnlyArray<
$ReadOnly<{
name: string,
value: string,
}>,
>;

export type NativeModuleMemberType =
| 'NumberTypeAnnotation'
| 'StringTypeAnnotation';

export type NativeModuleEnumDeclaration = $ReadOnly<{
name: string,
type: 'EnumDeclaration',
memberType: 'NumberTypeAnnotation' | 'StringTypeAnnotation',
memberType: NativeModuleMemberType,
}>;

export type NativeModuleEnumDeclarationWithMembers = {
name: string,
type: 'EnumDeclarationWithMembers',
memberType: NativeModuleMemberType,
members: NativeModuleEnumMembers,
};

export type NativeModuleGenericObjectTypeAnnotation = $ReadOnly<{
type: 'GenericObjectTypeAnnotation',
}>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const SCHEMA_WITH_TM_AND_FC: SchemaType = {
NativeCalculator: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const EMPTY_NATIVE_MODULES: SchemaType = {
NativeSampleTurboModule: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [],
},
Expand All @@ -30,6 +31,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
NativeSampleTurboModule: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -342,6 +344,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = {
NativeSampleTurboModule: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [
{
Expand All @@ -362,6 +365,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = {
NativeSampleTurboModule2: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -399,6 +403,7 @@ const COMPLEX_OBJECTS: SchemaType = {
NativeSampleTurboModule: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -854,6 +859,7 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = {
],
},
},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -1138,6 +1144,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = {
],
},
},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -1333,6 +1340,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = {
type: 'ObjectTypeAnnotation',
},
},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -1508,6 +1516,7 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
],
},
},
enumMap: {},
spec: {
properties: [
{
Expand Down Expand Up @@ -1648,6 +1657,7 @@ const SAMPLE_WITH_UPPERCASE_NAME: SchemaType = {
modules: {
NativeSampleTurboModule: {
type: 'NativeModule',
enumMap: {},
aliasMap: {},
spec: {
properties: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ describe('parseObjectProperty', () => {
const moduleName = 'testModuleName';
const types = {['wrongName']: 'wrongType'};
const aliasMap = {};
const enumMap = {};
const tryParse = () => null;
const cxxOnly = false;
const nullable = true;
Expand Down Expand Up @@ -305,6 +306,7 @@ describe('parseObjectProperty', () => {
moduleName,
types,
aliasMap,
enumMap,
tryParse,
cxxOnly,
nullable,
Expand Down Expand Up @@ -338,6 +340,7 @@ describe('parseObjectProperty', () => {
moduleName,
types,
aliasMap,
enumMap,
tryParse,
cxxOnly,
nullable,
Expand Down Expand Up @@ -375,6 +378,7 @@ describe('buildSchemaFromConfigType', () => {
const moduleSchemaMock = {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {properties: []},
moduleName: '',
};
Expand Down Expand Up @@ -743,6 +747,7 @@ describe('buildSchema', () => {
fileName: {
type: 'NativeModule',
aliasMap: {},
enumMap: {},
spec: {
properties: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const {
emitStringish,
emitMixed,
typeAliasResolution,
typeEnumResolution,
} = require('../parsers-primitives.js');
const {MockedParser} = require('../parserMock');
const {emitUnion} = require('../parsers-primitives');
Expand Down Expand Up @@ -264,14 +265,14 @@ describe('typeAliasResolution', () => {
],
};

describe('when typeAliasResolutionStatus is successful', () => {
const typeAliasResolutionStatus = {successful: true, aliasName: 'Foo'};
describe('when typeResolution is successful', () => {
const typeResolution = {successful: true, type: 'alias', name: 'Foo'};

describe('when nullable is true', () => {
it('returns nullable TypeAliasTypeAnnotation and map it in aliasMap', () => {
const aliasMap = {};
const result = typeAliasResolution(
typeAliasResolutionStatus,
typeResolution,
objectTypeAnnotation,
aliasMap,
true,
Expand All @@ -292,7 +293,7 @@ describe('typeAliasResolution', () => {
it('returns non nullable TypeAliasTypeAnnotation and map it in aliasMap', () => {
const aliasMap = {};
const result = typeAliasResolution(
typeAliasResolutionStatus,
typeResolution,
objectTypeAnnotation,
aliasMap,
false,
Expand All @@ -307,14 +308,14 @@ describe('typeAliasResolution', () => {
});
});

describe('when typeAliasResolutionStatus is not successful', () => {
const typeAliasResolutionStatus = {successful: false};
describe('when typeResolution is not successful', () => {
const typeResolution = {successful: false};

describe('when nullable is true', () => {
it('returns nullable ObjectTypeAnnotation', () => {
const aliasMap = {};
const result = typeAliasResolution(
typeAliasResolutionStatus,
typeResolution,
objectTypeAnnotation,
aliasMap,
true,
Expand All @@ -332,7 +333,7 @@ describe('typeAliasResolution', () => {
it('returns non nullable ObjectTypeAnnotation', () => {
const aliasMap = {};
const result = typeAliasResolution(
typeAliasResolutionStatus,
typeResolution,
objectTypeAnnotation,
aliasMap,
false,
Expand All @@ -345,6 +346,91 @@ describe('typeAliasResolution', () => {
});
});

describe('typeEnumResolution', () => {
const strMembers = [
{
name: 'Hello',
value: 'hello',
},
{
name: 'Goodbye',
value: 'goodbye',
},
];

const numMembers = [
{
name: 'On',
value: '1',
},
{
name: 'Off',
value: '0',
},
];

describe('when typeResolution is successful', () => {
describe('when nullable is true', () => {
it('returns nullable EnumDeclaration and map it in enumMap', () => {
const enumMap = {};
const result = typeEnumResolution(
true /* nullable */,
'Foo' /* name */,
'StringTypeAnnotation',
strMembers,
enumMap,
);

expect(enumMap).toEqual({
Foo: {
type: 'EnumDeclarationWithMembers',
name: 'Foo',
memberType: 'StringTypeAnnotation',
members: strMembers,
},
});

expect(result).toEqual({
type: 'NullableTypeAnnotation',
typeAnnotation: {
name: 'Foo',
type: 'EnumDeclaration',
memberType: 'StringTypeAnnotation',
},
});
});
});

describe('when nullable is false', () => {
it('returns non nullable TypeAliasTypeAnnotation and map it in aliasMap', () => {
const enumMap = {};
const result = typeEnumResolution(
false /* nullable */,
'Foo' /* name */,
'NumberTypeAnnotation',
numMembers,
enumMap,
);

expect(enumMap).toEqual({
Foo: {
type: 'EnumDeclarationWithMembers',
name: 'Foo',
memberType: 'NumberTypeAnnotation',
members: numMembers,
},
});

expect(result).toEqual({
name: 'Foo',
type: 'EnumDeclaration',
memberType: 'NumberTypeAnnotation',
});
});
});
});
});

describe('emitPromise', () => {
const moduleName = 'testModuleName';

Expand All @@ -362,6 +448,8 @@ describe('emitPromise', () => {
{},
/* aliasMap: {...NativeModuleAliasMap} */
{},
/* enumMap: {...NativeModuleEnumMap} */
{},
/* tryParse: ParserErrorCapturer */
// $FlowFixMe[missing-local-annot]
function <T>(_: () => T) {
Expand Down Expand Up @@ -991,6 +1079,8 @@ describe('emitArrayType', () => {
{},
/* aliasMap: {...NativeModuleAliasMap} */
{},
/* enumMap: {...NativeModuleEnumMap} */
{},
/* cxxOnly: boolean */
false,
nullable,
Expand Down
Loading

0 comments on commit d0aec9a

Please sign in to comment.