From 59b8ee86c8a2dc6eaa21c2941b9e6c57e98e6490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Osadnik?= Date: Mon, 8 Jul 2019 03:14:42 -0700 Subject: [PATCH] Prepare generic mechanism for extracting types from external type definitions Summary: This diff a adds generic mechansm for extracting types from types' difinitions defined in other part of the file. Reviewed By: TheSavior Differential Revision: D16131742 fbshipit-source-id: 006b6980fa9f6a064d5bb8734ba2740b802b6989 --- .../flow/__test_fixtures__/fixtures.js | 32 ++++++++++++++ .../__snapshots__/parser-test.js.snap | 42 +++++++++++++++++++ .../src/parsers/flow/index.js | 2 +- .../src/parsers/flow/methods.js | 30 +++++++++---- 4 files changed, 96 insertions(+), 10 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 18c1c8b32b2..ecd7ea341bf 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 @@ -60,6 +60,37 @@ export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; +const NATIVE_MODULE_WITH_WITH_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 + * @format + */ + +'use strict'; + +import type {TurboModule} from '../RCTExport'; +import * as TurboModuleRegistry from '../TurboModuleRegistry'; + +type NumNum = number; +export type Num = (arg: NumNum) => void; +type Num2 = Num; +export type Void = void + +export interface Spec extends TurboModule { + // Exported methods. + +getNumber: Num2; + +getVoid: () => Void; +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); + +`; + const EVENT_DEFINITION = ` boolean_required: boolean, boolean_optional_key?: boolean, @@ -600,6 +631,7 @@ export default codegenNativeComponent('Module'); `; module.exports = { + NATIVE_MODULE_WITH_WITH_ALIASES, NATIVE_MODULE_WITH_BASIC_PARAM_TYPES, EMPTY_NATIVE_MODULE, ALL_PROP_TYPES_NO_EVENTS, 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 7860aa583e0..9efe51c22a5 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 @@ -3386,6 +3386,48 @@ Object { } `; +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_WITH_ALIASES 1`] = ` +Object { + "modules": Object { + "SampleTurboModule": Object { + "nativeModules": Object { + "SampleTurboModule": Object { + "properties": Array [ + Object { + "name": "getNumber", + "typeAnnotation": Object { + "params": Array [ + Object { + "name": "arg", + "typeAnnotation": Object { + "type": "NumberTypeAnnotation", + }, + }, + ], + "returnTypeAnnotation": Object { + "type": "VoidTypeAnnotation", + }, + "type": "FunctionTypeAnnotation", + }, + }, + Object { + "name": "getVoid", + "typeAnnotation": Object { + "params": Array [], + "returnTypeAnnotation": Object { + "type": "VoidTypeAnnotation", + }, + "type": "FunctionTypeAnnotation", + }, + }, + ], + }, + }, + }, + }, +} +`; + exports[`RN Codegen Flow Parser can generate fixture NO_PROPS_EVENTS_ONLY_DEPRECATED_VIEW_CONFIG_NAME_OPTION 1`] = ` Object { "modules": Object { diff --git a/packages/react-native-codegen/src/parsers/flow/index.js b/packages/react-native-codegen/src/parsers/flow/index.js index 14c689d9882..e4ee1c25eab 100644 --- a/packages/react-native-codegen/src/parsers/flow/index.js +++ b/packages/react-native-codegen/src/parsers/flow/index.js @@ -240,7 +240,7 @@ function processString(contents: string): SchemaBuilderConfig { const {interfaceName, moduleName} = findModuleConfig(ast); const moduleProperties = getModuleProperties(types, interfaceName); - const properties = getMethods(moduleProperties); + const properties = getMethods(moduleProperties, types); return {configType, properties, filename: moduleName, moduleName}; } } diff --git a/packages/react-native-codegen/src/parsers/flow/methods.js b/packages/react-native-codegen/src/parsers/flow/methods.js index 5eadb2c3a59..d7055d90ce1 100644 --- a/packages/react-native-codegen/src/parsers/flow/methods.js +++ b/packages/react-native-codegen/src/parsers/flow/methods.js @@ -17,6 +17,13 @@ import type { FunctionTypeAnnotationReturn, } from '../../CodegenSchema.js'; +function getValueFromTypes(value, types) { + if (value.type === 'GenericTypeAnnotation' && types[value.id.name]) { + return getValueFromTypes(types[value.id.name].right, types); + } + return value; +} + function wrapPrimitiveIntoTypeAnnotation( methodName: string, type: @@ -43,17 +50,16 @@ function wrapPrimitiveIntoTypeAnnotation( function getTypeAnnotationForParam( name: string, param, + types: $ReadOnlyArray, ): FunctionTypeAnnotationParam { - const type = param.typeAnnotation.type; + const type = getValueFromTypes(param.typeAnnotation, types).type; const paramName = param.name.name; - // TODO handle more types const typeAnnotation = wrapPrimitiveIntoTypeAnnotation(name, type, paramName); return { name: paramName, typeAnnotation, }; } - function getReturnTypeAnnotation( methodName: string, type, @@ -73,9 +79,13 @@ function getReturnTypeAnnotation( ); } } -function buildMethodSchema(property: MethodAST): MethodTypeShape { + +function buildMethodSchema( + property: MethodAST, + types: $ReadOnlyArray, +): MethodTypeShape { const name: string = property.key.name; - const value = property.value; + const value = getValueFromTypes(property.value, types); if (value.type !== 'FunctionTypeAnnotation') { throw new Error( `Only methods are supported as module properties. Found ${ @@ -83,14 +93,13 @@ function buildMethodSchema(property: MethodAST): MethodTypeShape { } in ${property.key.name}`, ); } - const params = value.params.map(param => - getTypeAnnotationForParam(name, param), + getTypeAnnotationForParam(name, param, types), ); const returnTypeAnnotation = getReturnTypeAnnotation( name, - value.returnType.type, + getValueFromTypes(value.returnType, types).type, ); return { name, @@ -104,13 +113,16 @@ function buildMethodSchema(property: MethodAST): MethodTypeShape { // $FlowFixMe there's no flowtype for ASTs type MethodAST = Object; +// $FlowFixMe there's no flowtype for ASTs +type TypesAST = Object; function getMethods( typeDefinition: $ReadOnlyArray, + types: $ReadOnlyArray, ): $ReadOnlyArray { return typeDefinition .filter(property => property.type === 'ObjectTypeProperty') - .map(buildMethodSchema) + .map(property => buildMethodSchema(property, types)) .filter(Boolean); }