From be07435e6a53678cb4e6ca7d7525a7a1505db469 Mon Sep 17 00:00:00 2001 From: Cameron Bourke Date: Mon, 17 Jun 2019 09:01:41 -0700 Subject: [PATCH] Allow type exports from the typed native component Summary: ## Context At the moment, the codegen process does not expect any types defined in a native component (*NativeComponent.js) to be exported. For example, the `NativeProps` type may be defined as: ``` // RCTSegmentedControlNativeComponent.js type NativeProps = $ReadOnly<{| ... onChange?: ?(event: BubblingEvent) => mixed, |}>; ``` However, it would be helpful to be able to reuse `NativeProps` in the user facing component: ``` // SegmentedControlIOS.js type Props = $ReadOnly<{| ...NativeProps onValueChange?: ?(value: number) => mixed, |}>; ``` ## Changes - updates the `getTypes` function to unwrap the type declaration inside exported declarations - add test to verify that exported types are parsed as expected Reviewed By: rickhanlonii Differential Revision: D15851693 fbshipit-source-id: a9cd375c69cbb8fe9a38be3d2a681227444fb33d --- .../flow/__test_fixtures__/fixtures.js | 40 ++ .../__snapshots__/parser-test.js.snap | 372 ++++++++++++++++++ .../src/parsers/flow/index.js | 12 +- 3 files changed, 419 insertions(+), 5 deletions(-) diff --git a/packages/react-native-codegen/src/parsers/flow/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/__test_fixtures__/fixtures.js index 604efb0ec02..b993455aaff 100644 --- a/packages/react-native-codegen/src/parsers/flow/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/__test_fixtures__/fixtures.js @@ -551,6 +551,45 @@ type ModuleProps = $ReadOnly<{| export default codegenNativeComponent('Module'); `; +const PROPS_AND_EVENTS_TYPES_EXPORTED = ` +/** + * 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. + * + * @format + * @flow + */ + +'use strict'; + +const codegenNativeComponent = require('codegenNativeComponent'); + +import type { + BubblingEvent, + DirectEvent, +} from 'CodegenTypes'; + +import type {ViewProps} from 'ViewPropTypes'; + +export type EventInFile = $ReadOnly<{| + ${EVENT_DEFINITION} +|}>; + +export type ModuleProps = $ReadOnly<{| + ...ViewProps, + + // No props + + // Events defined inline + onBubblingEventDefinedInline: (event: BubblingEvent) => void, + onDirectEventDefinedInline: (event: DirectEvent) => void, +|}>; + +export default codegenNativeComponent('Module'); +`; + module.exports = { ALL_PROP_TYPES_NO_EVENTS, ARRAY_PROP_TYPES_NO_EVENTS, @@ -559,4 +598,5 @@ module.exports = { EVENTS_DEFINED_IN_FILE_WITH_ALL_TYPES, EVENTS_DEFINED_AS_NULL_IN_FILE, EVENTS_DEFINED_AS_NULL_INLINE, + PROPS_AND_EVENTS_TYPES_EXPORTED, }; diff --git a/packages/react-native-codegen/src/parsers/flow/__tests__/__snapshots__/parser-test.js.snap b/packages/react-native-codegen/src/parsers/flow/__tests__/__snapshots__/parser-test.js.snap index 65c620d7162..bfce6c25a94 100644 --- a/packages/react-native-codegen/src/parsers/flow/__tests__/__snapshots__/parser-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/__tests__/__snapshots__/parser-test.js.snap @@ -3968,3 +3968,375 @@ Object { }, } `; + +exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPORTED 1`] = ` +Object { + "modules": Object { + "Module": Object { + "components": Object { + "Module": Object { + "events": Array [ + Object { + "bubblingType": "bubble", + "name": "onBubblingEventDefinedInline", + "optional": false, + "typeAnnotation": Object { + "argument": Object { + "properties": Array [ + Object { + "name": "boolean_required", + "optional": false, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "boolean_optional_key", + "optional": true, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "boolean_optional_value", + "optional": true, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "boolean_optional_both", + "optional": true, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "string_required", + "optional": false, + "type": "StringTypeAnnotation", + }, + Object { + "name": "string_optional_key", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "string_optional_value", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "string_optional_both", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "float_required", + "optional": false, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "float_optional_key", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "float_optional_value", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "float_optional_both", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "int32_required", + "optional": false, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "int32_optional_key", + "optional": true, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "int32_optional_value", + "optional": true, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "int32_optional_both", + "optional": true, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "object_required", + "optional": false, + "properties": Array [ + Object { + "name": "boolean_required", + "optional": false, + "type": "BooleanTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_optional_key", + "optional": true, + "properties": Array [ + Object { + "name": "string_optional_key", + "optional": true, + "type": "StringTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_optional_value", + "optional": true, + "properties": Array [ + Object { + "name": "float_optional_value", + "optional": true, + "type": "FloatTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_optional_both", + "optional": true, + "properties": Array [ + Object { + "name": "int32_optional_both", + "optional": true, + "type": "Int32TypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_required_nested_2_layers", + "optional": false, + "properties": Array [ + Object { + "name": "object_optional_nested_1_layer", + "optional": true, + "properties": Array [ + Object { + "name": "boolean_required", + "optional": false, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "string_optional_key", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "float_optional_value", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "int32_optional_both", + "optional": true, + "type": "Int32TypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + "type": "EventTypeAnnotation", + }, + }, + Object { + "bubblingType": "direct", + "name": "onDirectEventDefinedInline", + "optional": false, + "typeAnnotation": Object { + "argument": Object { + "properties": Array [ + Object { + "name": "boolean_required", + "optional": false, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "boolean_optional_key", + "optional": true, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "boolean_optional_value", + "optional": true, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "boolean_optional_both", + "optional": true, + "type": "BooleanTypeAnnotation", + }, + Object { + "name": "string_required", + "optional": false, + "type": "StringTypeAnnotation", + }, + Object { + "name": "string_optional_key", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "string_optional_value", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "string_optional_both", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "float_required", + "optional": false, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "float_optional_key", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "float_optional_value", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "float_optional_both", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "int32_required", + "optional": false, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "int32_optional_key", + "optional": true, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "int32_optional_value", + "optional": true, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "int32_optional_both", + "optional": true, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "object_required", + "optional": false, + "properties": Array [ + Object { + "name": "boolean_required", + "optional": false, + "type": "BooleanTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_optional_key", + "optional": true, + "properties": Array [ + Object { + "name": "string_optional_key", + "optional": true, + "type": "StringTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_optional_value", + "optional": true, + "properties": Array [ + Object { + "name": "float_optional_value", + "optional": true, + "type": "FloatTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_optional_both", + "optional": true, + "properties": Array [ + Object { + "name": "int32_optional_both", + "optional": true, + "type": "Int32TypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + Object { + "name": "object_required_nested_2_layers", + "optional": false, + "properties": Array [ + Object { + "name": "object_optional_nested_1_layer", + "optional": true, + "properties": Array [ + Object { + "name": "boolean_required", + "optional": false, + "type": "Int32TypeAnnotation", + }, + Object { + "name": "string_optional_key", + "optional": true, + "type": "StringTypeAnnotation", + }, + Object { + "name": "float_optional_value", + "optional": true, + "type": "FloatTypeAnnotation", + }, + Object { + "name": "int32_optional_both", + "optional": true, + "type": "Int32TypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + ], + "type": "ObjectTypeAnnotation", + }, + "type": "EventTypeAnnotation", + }, + }, + ], + "extendsProps": Array [ + Object { + "knownTypeName": "ReactNativeCoreViewProps", + "type": "ReactNativeBuiltInType", + }, + ], + "props": Array [], + }, + }, + }, + }, +} +`; diff --git a/packages/react-native-codegen/src/parsers/flow/index.js b/packages/react-native-codegen/src/parsers/flow/index.js index bf1129bcb15..bab3dd10a53 100644 --- a/packages/react-native-codegen/src/parsers/flow/index.js +++ b/packages/react-native-codegen/src/parsers/flow/index.js @@ -57,12 +57,14 @@ function findConfig(ast) { } function getTypes(ast) { - return ast.body - .filter(node => node.type === 'TypeAlias') - .reduce((types, node) => { + return ast.body.reduce((types, node) => { + if (node.type === 'ExportNamedDeclaration') { + types[node.declaration.id.name] = node.declaration; + } else if (node.type === 'TypeAlias') { types[node.id.name] = node; - return types; - }, {}); + } + return types; + }, {}); } function getPropProperties(propsTypeName, types) {