Skip to content

Commit

Permalink
Codegen: List type aliases in modules schema
Browse files Browse the repository at this point in the history
Summary:
The current parser behavior flattens out any object type aliases into ObjectTypeAnnotations. Generators can treat these as regular objects and generate the applicable native code. This, however, can lead to repetition whenever an object type alias is re-used in the same native module.

I propose we treat these as a special case, using a TypeAliasTypeAnnotation to denote them as type aliases. Generators can look up the actual signature for a given object alias by referring to the "aliases" array that is provided in the schema.

**Proposed schema change:**

Adds an "aliases" key to each module in the schema:

```
export type NativeModuleShape = $ReadOnly<{|
  properties: $ReadOnlyArray<NativeModuleMethodTypeShape>,
  aliases: $ReadOnlyArray<{|
    name: string,
    typeAnnotation:
      | $ReadOnly<{|
          type: 'ObjectTypeAnnotation',
          properties: $ReadOnlyArray<ObjectParamTypeAnnotation>,
        |}>
      | $ReadOnly<TypeAliasTypeAnnotation>,
  |}>,
|}>;
```

Example:
```
{
  modules: {
    SampleTurboModule: {
      nativeModules: {
        SampleTurboModule: {
          aliases: [],
          properties: [],
        },
      },
    },
  },
}
```

Method parameters will now support the new 'TypeAliasTypeAnnotation' wherever a param might have used a 'ObjectTypeAnnotation':

```
export type TypeAliasTypeAnnotation = $ReadOnly<{|
  type: 'TypeAliasTypeAnnotation',
  name: string,
|}>;
```

Changelog: [Internal]

Reviewed By: RSNara

Differential Revision: D22200700

fbshipit-source-id: 15684620783c752f2fb482ba4b88d1fd1cc07540
  • Loading branch information
hramos authored and facebook-github-bot committed Jul 1, 2020
1 parent 0cef464 commit e261f02
Show file tree
Hide file tree
Showing 14 changed files with 402 additions and 31 deletions.
27 changes: 23 additions & 4 deletions packages/react-native-codegen/src/CodegenSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export type StringTypeAnnotation = $ReadOnly<{|
type: 'StringTypeAnnotation',
|}>;

export type TypeAliasTypeAnnotation = $ReadOnly<{|
type: 'TypeAliasTypeAnnotation',
name: string,
|}>;

export type EventObjectPropertyType =
| $ReadOnly<{|
type: 'BooleanTypeAnnotation',
Expand Down Expand Up @@ -223,19 +228,25 @@ export type FunctionTypeAnnotationParamTypeAnnotation =
|}>
| $ReadOnly<{|
type: 'ArrayTypeAnnotation',
elementType: ?FunctionTypeAnnotationParamTypeAnnotation,
elementType:
| ?FunctionTypeAnnotationParamTypeAnnotation
| ?TypeAliasTypeAnnotation,
|}>
| $ReadOnly<{|
type: 'ObjectTypeAnnotation',
properties: ?$ReadOnlyArray<ObjectParamTypeAnnotation>,
|}>;

export type FunctionTypeAnnotationReturnArrayElementType = FunctionTypeAnnotationParamTypeAnnotation;
export type FunctionTypeAnnotationReturnArrayElementType =
| FunctionTypeAnnotationParamTypeAnnotation
| TypeAliasTypeAnnotation;

export type ObjectParamTypeAnnotation = $ReadOnly<{|
optional: boolean,
name: string,
typeAnnotation?: FunctionTypeAnnotationParamTypeAnnotation, // TODO (T67898313): Workaround for NativeLinking's use of union type, typeAnnotations should not be optional
typeAnnotation?:
| FunctionTypeAnnotationParamTypeAnnotation
| TypeAliasTypeAnnotation, // TODO (T67898313): Workaround for NativeLinking's use of union type, typeAnnotations should not be optional
|}>;

export type FunctionTypeAnnotationReturn =
Expand Down Expand Up @@ -265,7 +276,9 @@ export type FunctionTypeAnnotationReturn =
export type FunctionTypeAnnotationParam = $ReadOnly<{|
nullable: boolean,
name: string,
typeAnnotation: FunctionTypeAnnotationParamTypeAnnotation,
typeAnnotation:
| FunctionTypeAnnotationParamTypeAnnotation
| TypeAliasTypeAnnotation,
|}>;

export type FunctionTypeAnnotation = $ReadOnly<{|
Expand All @@ -280,7 +293,13 @@ export type NativeModuleMethodTypeShape = $ReadOnly<{|
typeAnnotation: FunctionTypeAnnotation,
|}>;

export type ObjectTypeAliasTypeShape = $ReadOnly<{|
type: 'ObjectTypeAnnotation',
properties: $ReadOnlyArray<ObjectParamTypeAnnotation>,
|}>;

export type NativeModuleShape = $ReadOnly<{|
aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>,
properties: $ReadOnlyArray<NativeModuleMethodTypeShape>,
|}>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function traverseArg(arg, index): string {
default:
(typeAnnotation.name: empty);
throw new Error(
`Unknown prop type for "${arg.name}, found: ${typeAnnotation.name}"`,
`Unknown prop type for "${arg.name}", found: "${typeAnnotation.name}"`,
);
}
case 'StringTypeAnnotation':
Expand All @@ -91,6 +91,7 @@ function traverseArg(arg, index): string {
case 'FunctionTypeAnnotation':
return `std::move(${wrap('.getObject(rt).getFunction(rt)')})`;
case 'GenericObjectTypeAnnotation':
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'ObjectTypeAnnotation':
return wrap('.getObject(rt)');
case 'AnyTypeAnnotation':
Expand All @@ -99,7 +100,7 @@ function traverseArg(arg, index): string {
// TODO (T65847278): Figure out why this does not work.
// (typeAnnotation.type: empty);
throw new Error(
`Unknown prop type for "${arg.name}, found: ${typeAnnotation.type}"`,
`Unknown prop type for "${arg.name}", found: "${typeAnnotation.type}"`,
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ function translatePrimitiveJSTypeToCpp(
return 'int';
case 'BooleanTypeAnnotation':
return 'bool';
// case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'GenericObjectTypeAnnotation':
case 'ObjectTypeAnnotation':
return 'jsi::Object';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ function translatePrimitiveJSTypeToObjCType(
return nullable ? 'NSNumber *' : 'double';
case 'BooleanTypeAnnotation':
return nullable ? 'NSNumber * _Nullable' : 'BOOL';
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'GenericObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
case 'ArrayTypeAnnotation':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ function getElementTypeForArray(
return 'double';
case 'ObjectTypeAnnotation':
return getNamespacedStructName(name, property) + 'Element';
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'GenericObjectTypeAnnotation':
// TODO(T67565166): Generic objects are not type safe and should be disallowed in the schema. This case should throw an error once it is disallowed in schema.
console.error(
Expand Down Expand Up @@ -228,6 +229,7 @@ function getInlineMethodImplementation(
return `RCTBridgingToBool(${element})`;
case 'ObjectTypeAnnotation':
return `${getNamespacedStructName(name, property)}Element(${element})`;
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'GenericObjectTypeAnnotation':
return element;
case 'AnyObjectTypeAnnotation':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ function getBuilderInputFieldDeclaration(
property.name,
)}::Builder`,
);
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'GenericObjectTypeAnnotation':
case 'AnyTypeAnnotation':
if (property.optional) {
Expand Down Expand Up @@ -185,6 +186,7 @@ function getObjectProperty(property: ObjectParamTypeAnnotation): string {
case 'BooleanTypeAnnotation':
return boolGetter(property.name, property.optional);
case 'StringTypeAnnotation':
case 'TypeAliasTypeAnnotation': // TODO: Handle aliases
case 'GenericObjectTypeAnnotation':
case 'AnyTypeAnnotation':
return safeGetter(property.name, property.optional);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const EMPTY_NATIVE_MODULES: SchemaType = {
SampleTurboModule: {
nativeModules: {
SampleTurboModule: {
aliases: {},
properties: [],
},
},
Expand All @@ -29,6 +30,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
SampleTurboModule: {
nativeModules: {
SampleTurboModule: {
aliases: {},
properties: [
{
name: 'getConstants',
Expand Down Expand Up @@ -291,6 +293,7 @@ const TWO_MODULES_SAME_FILE: SchemaType = {
NativeSampleTurboModule: {
nativeModules: {
SampleTurboModule: {
aliases: {},
properties: [
{
name: 'voidFunc',
Expand All @@ -307,6 +310,7 @@ const TWO_MODULES_SAME_FILE: SchemaType = {
],
},
Sample2TurboModule: {
aliases: {},
properties: [
{
name: 'voidFunc',
Expand All @@ -332,6 +336,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = {
NativeSampleTurboModule: {
nativeModules: {
SampleTurboModule: {
aliases: {},
properties: [
{
name: 'voidFunc',
Expand All @@ -352,6 +357,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = {
NativeSampleTurboModule2: {
nativeModules: {
Sample2TurboModule: {
aliases: {},
properties: [
{
name: 'getConstants',
Expand Down Expand Up @@ -390,6 +396,7 @@ const COMPLEX_OBJECTS: SchemaType = {
NativeSampleTurboModule: {
nativeModules: {
SampleTurboModule: {
aliases: {},
properties: [
{
name: 'difficult',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,54 @@ type Num2 = Num;
export type Void = void;
export type A = number;
export type B = number;
export type ObjectAlias = {|
x: number,
y: number,
label: string,
truthy: boolean,
|}
export interface Spec extends TurboModule {
// Exported methods.
+getNumber: Num2;
+getVoid: () => Void;
+getArray: (a: Array<A>) => {| a: B |};
+getStringFromAlias: (a: ObjectAlias) => string;
}
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;

const NATIVE_MODULE_WITH_NESTED_ALIASES = `
/**
* Copyright (c) Facebook, Inc. and its 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';
type Bar = {|
z: number
|};
type Foo = {|
bar1: Bar,
bar2: Bar,
|};
export interface Spec extends TurboModule {
// Exported methods.
foo1: (x: Foo) => void;
foo2: (x: Foo) => void;
}
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
Expand Down Expand Up @@ -459,6 +501,7 @@ module.exports = {
NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE,
NATIVE_MODULE_WITH_FLOAT_AND_INT32,
NATIVE_MODULE_WITH_ALIASES,
NATIVE_MODULE_WITH_NESTED_ALIASES,
NATIVE_MODULE_WITH_PROMISE,
NATIVE_MODULE_WITH_COMPLEX_OBJECTS,
NATIVE_MODULE_WITH_COMPLEX_OBJECTS_WITH_NULLABLE_KEY,
Expand Down
Loading

0 comments on commit e261f02

Please sign in to comment.