From 1375d6f9c8bb61b71308454e84d41f3f6bc3f3c0 Mon Sep 17 00:00:00 2001 From: "Zihan Chen (MSFT)" <53799235+ZihanChen-MSFT@users.noreply.github.com> Date: Wed, 11 Jan 2023 14:48:55 -0800 Subject: [PATCH 1/6] Add interface test case for typescript module --- .../__tests__/checkModuleSnaps-test.js | 1 + .../modules/__test_fixtures__/fixtures.js | 34 +++++++ ...script-module-parser-snapshot-test.js.snap | 91 +++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/packages/react-native-codegen/src/parsers/consistency/__tests__/checkModuleSnaps-test.js b/packages/react-native-codegen/src/parsers/consistency/__tests__/checkModuleSnaps-test.js index e14a6523156a73..e90d3d22d30c0e 100644 --- a/packages/react-native-codegen/src/parsers/consistency/__tests__/checkModuleSnaps-test.js +++ b/packages/react-native-codegen/src/parsers/consistency/__tests__/checkModuleSnaps-test.js @@ -22,6 +22,7 @@ const tsExtraCases = [ 'NATIVE_MODULE_WITH_ARRAY2_WITH_UNION_AND_TOUPLE', 'NATIVE_MODULE_WITH_BASIC_ARRAY2', 'NATIVE_MODULE_WITH_COMPLEX_ARRAY2', + 'NATIVE_MODULE_WITH_NESTED_INTERFACES', ]; const ignoredCases = []; diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js index 6e71b23714936d..4cd9c780d1023a 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js @@ -195,6 +195,39 @@ export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; +const NATIVE_MODULE_WITH_NESTED_INTERFACES = ` +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + + +import type {TurboModule} from '../RCTExport'; +import * as TurboModuleRegistry from '../TurboModuleRegistry'; + +interface Bar { + z: number +}; + +interface Foo { + bar1: Bar, + bar2: Bar, +}; + +export interface Spec extends TurboModule { + // Exported methods. + foo1: (x: Foo) => Foo; + foo2: (x: Foo) => void; +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); + +`; + const NATIVE_MODULE_WITH_FLOAT_AND_INT32 = ` /** * Copyright (c) Meta Platforms, Inc. and affiliates. @@ -704,6 +737,7 @@ module.exports = { NATIVE_MODULE_WITH_FLOAT_AND_INT32, NATIVE_MODULE_WITH_ALIASES, NATIVE_MODULE_WITH_NESTED_ALIASES, + NATIVE_MODULE_WITH_NESTED_INTERFACES, NATIVE_MODULE_WITH_PROMISE, NATIVE_MODULE_WITH_COMPLEX_OBJECTS, NATIVE_MODULE_WITH_COMPLEX_OBJECTS_WITH_NULLABLE_KEY, diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index 9d9dc39a4d411b..4717a7f5c96f0f 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -1503,6 +1503,97 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NE }" `; +exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NESTED_INTERFACES 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': { + 'Bar': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'z', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + ] + }, + 'Foo': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'bar1', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Bar' + } + }, + { + 'name': 'bar2', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Bar' + } + } + ] + } + }, + 'spec': { + 'properties': [ + { + 'name': 'foo1', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Foo' + }, + 'params': [ + { + 'name': 'x', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Foo' + } + } + ] + } + }, + { + 'name': 'foo2', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'x', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Foo' + } + } + ] + } + } + ] + }, + 'moduleName': 'SampleTurboModule' + } + } +}" +`; + exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NULLABLE_PARAM 1`] = ` "{ 'modules': { From 62f632e910a4cb880f3212412335cbc334d87a7b Mon Sep 17 00:00:00 2001 From: "Zihan Chen (MSFT)" <53799235+ZihanChen-MSFT@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:02:03 -0800 Subject: [PATCH 2/6] Recognize interface --- .../src/parsers/typescript/utils.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/react-native-codegen/src/parsers/typescript/utils.js b/packages/react-native-codegen/src/parsers/typescript/utils.js index 83e2f8bd2def75..c6f4869bac1516 100644 --- a/packages/react-native-codegen/src/parsers/typescript/utils.js +++ b/packages/react-native-codegen/src/parsers/typescript/utils.js @@ -90,12 +90,17 @@ function resolveTypeAnnotation( break; } - invariant( - resolvedTypeAnnotation.type === 'TSTypeAliasDeclaration', - `GenericTypeAnnotation '${node.typeName.name}' must resolve to a TSTypeAliasDeclaration. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`, - ); - - node = resolvedTypeAnnotation.typeAnnotation; + switch (resolvedTypeAnnotation.type) + { + case 'TSTypeAliasDeclaration': + node = resolvedTypeAnnotation.typeAnnotation; + break; + case 'TSInterfaceDeclaration': + node = resolvedTypeAnnotation; + break; + default: + throw new Error(`GenericTypeAnnotation '${node.typeName.name}' must resolve to a TSTypeAliasDeclaration or a TSInterfaceDeclaration. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`); + } } else { break; } From 23030727d1e63487f7caa2f4dd2983a8ea96a079 Mon Sep 17 00:00:00 2001 From: "Zihan Chen (MSFT)" <53799235+ZihanChen-MSFT@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:06:07 -0800 Subject: [PATCH 3/6] Passed test case --- .../src/parsers/typescript/modules/index.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/index.js b/packages/react-native-codegen/src/parsers/typescript/modules/index.js index f3a182d71b8ea4..ba6c3568386c68 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/index.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/index.js @@ -22,6 +22,7 @@ import type { import type {Parser} from '../../parser'; import type {ParserErrorCapturer, TypeDeclarationMap} from '../../utils'; +const {flattenProperties} = require('../components/componentsUtils'); const {visit, isModuleRegistryCall, verifyPlatforms} = require('../../utils'); const {resolveTypeAnnotation, getTypes} = require('../utils'); @@ -182,6 +183,37 @@ function translateTypeAnnotation( } } } + case 'TSInterfaceDeclaration': { + const objectTypeAnnotation = { + type: 'ObjectTypeAnnotation', + properties: flattenProperties([typeAnnotation], types) + .map>>( + property => { + return tryParse(() => { + return parseObjectProperty( + property, + hasteModuleName, + types, + aliasMap, + tryParse, + cxxOnly, + nullable, + translateTypeAnnotation, + parser, + ); + }); + }, + ) + .filter(Boolean), + }; + + return typeAliasResolution( + typeAliasResolutionStatus, + objectTypeAnnotation, + aliasMap, + nullable, + ); + } case 'TSTypeLiteral': { // if there is TSIndexSignature, then it is a dictionary if (typeAnnotation.members) { From 773f5fc425e3ff877a100aa2cea0ed39d588a4c6 Mon Sep 17 00:00:00 2001 From: "Zihan Chen (MSFT)" <53799235+ZihanChen-MSFT@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:08:37 -0800 Subject: [PATCH 4/6] ... --- .../modules/__test_fixtures__/fixtures.js | 13 ++++++++++++- ...ypescript-module-parser-snapshot-test.js.snap | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js index 4cd9c780d1023a..56b22b61841504 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js @@ -213,9 +213,20 @@ interface Bar { z: number }; -interface Foo { +interface Base1 { bar1: Bar, +} + +interface Base2 { bar2: Bar, +} + +interface Base3 extends Base2 { + bar3: Bar, +} + +interface Foo extends Base1, Base3 { + bar4: Bar, }; export interface Spec extends TurboModule { diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index 4717a7f5c96f0f..d5ed3ec8c416a0 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -1539,6 +1539,22 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NE 'type': 'TypeAliasTypeAnnotation', 'name': 'Bar' } + }, + { + 'name': 'bar3', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Bar' + } + }, + { + 'name': 'bar4', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Bar' + } } ] } From fd08ffda6f64dfe1e01dec8bb95066f3bd27ff3a Mon Sep 17 00:00:00 2001 From: "Zihan Chen (MSFT)" <53799235+ZihanChen-MSFT@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:15:53 -0800 Subject: [PATCH 5/6] yarn prettier --- .../react-native-codegen/src/parsers/typescript/utils.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/react-native-codegen/src/parsers/typescript/utils.js b/packages/react-native-codegen/src/parsers/typescript/utils.js index c6f4869bac1516..725b74968ae6cc 100644 --- a/packages/react-native-codegen/src/parsers/typescript/utils.js +++ b/packages/react-native-codegen/src/parsers/typescript/utils.js @@ -90,8 +90,7 @@ function resolveTypeAnnotation( break; } - switch (resolvedTypeAnnotation.type) - { + switch (resolvedTypeAnnotation.type) { case 'TSTypeAliasDeclaration': node = resolvedTypeAnnotation.typeAnnotation; break; @@ -99,7 +98,9 @@ function resolveTypeAnnotation( node = resolvedTypeAnnotation; break; default: - throw new Error(`GenericTypeAnnotation '${node.typeName.name}' must resolve to a TSTypeAliasDeclaration or a TSInterfaceDeclaration. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`); + throw new Error( + `GenericTypeAnnotation '${node.typeName.name}' must resolve to a TSTypeAliasDeclaration or a TSInterfaceDeclaration. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`, + ); } } else { break; From 33dc4b77c502ab57457e7040eb8bd579f55bf82e Mon Sep 17 00:00:00 2001 From: "Zihan Chen (MSFT)" <53799235+ZihanChen-MSFT@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:24:28 -0800 Subject: [PATCH 6/6] yarn flow-check-ios --- .../src/parsers/typescript/modules/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/index.js b/packages/react-native-codegen/src/parsers/typescript/modules/index.js index ba6c3568386c68..b1df8711a58b92 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/index.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/index.js @@ -186,7 +186,11 @@ function translateTypeAnnotation( case 'TSInterfaceDeclaration': { const objectTypeAnnotation = { type: 'ObjectTypeAnnotation', - properties: flattenProperties([typeAnnotation], types) + // $FlowFixMe[missing-type-arg] + properties: (flattenProperties( + [typeAnnotation], + types, + ): $ReadOnlyArray<$FlowFixMe>) .map>>( property => { return tryParse(() => {