Skip to content

Commit c20eaa5

Browse files
osdnkfacebook-github-bot
authored andcommitted
Change module parser to consider extends instead of default exports
Summary: Following out internal communication we decided to change logic of current parser to consider types which extend 'TurboModule' instead of looking at default exports. It also cassed for minor changes in testing logic and updating snapshots. Reviewed By: rickhanlonii Differential Revision: D16205707 fbshipit-source-id: c75cd4febf773ba5101e6b60ed1a921773246009
1 parent 9374b23 commit c20eaa5

File tree

6 files changed

+111
-82
lines changed

6 files changed

+111
-82
lines changed

packages/react-native-codegen/src/parsers/flow/index.js

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {SchemaType} from '../../CodegenSchema.js';
1414
// $FlowFixMe there's no flowtype flow-parser
1515
const flowParser = require('flow-parser');
1616
const fs = require('fs');
17+
const path = require('path');
1718
const {buildModuleSchema} = require('./modules/schema');
1819
const {buildComponentSchema} = require('./components/schema');
1920
const {processComponent} = require('./components');
@@ -35,46 +36,79 @@ function getTypes(ast) {
3536
}, {});
3637
}
3738

38-
function getConfigType(ast): 'module' | 'component' {
39+
function getConfigType(ast, types): 'module' | 'component' {
3940
const defaultExports = ast.body.filter(
4041
node => node.type === 'ExportDefaultDeclaration',
4142
);
42-
if (defaultExports.length !== 1) {
43-
throw new Error('File should contain only one default export.');
43+
const isComponent =
44+
defaultExports[0] &&
45+
defaultExports[0].declaration &&
46+
defaultExports[0].declaration.callee &&
47+
defaultExports[0].declaration.callee.name === 'codegenNativeComponent';
48+
49+
const typesExtendingTurboModule = Object.keys(types)
50+
.map(typeName => types[typeName])
51+
.filter(
52+
type =>
53+
type.extends &&
54+
type.extends[0] &&
55+
type.extends[0].id.name === 'TurboModule',
56+
);
57+
58+
if (typesExtendingTurboModule.length > 1) {
59+
throw new Error(
60+
'Found two types extending "TurboModule" is one file. Split them into separated files.',
61+
);
4462
}
45-
if (defaultExports[0].declaration && defaultExports[0].declaration.callee) {
46-
const statement = defaultExports[0].declaration.callee;
47-
if (statement.name === 'codegenNativeComponent') {
48-
return 'component';
49-
}
50-
if (statement.object && statement.object.name === 'TurboModuleRegistry') {
51-
return 'module';
52-
}
63+
64+
const isModule = typesExtendingTurboModule.length === 1;
65+
66+
if (isModule && isComponent) {
67+
throw new Error(
68+
'Found type extending "TurboModule" and exported "codegenNativeComponent" declaration in one file. Split them into separated files.',
69+
);
70+
}
71+
72+
if (isModule) {
73+
return 'module';
74+
} else if (isComponent) {
75+
return 'component';
76+
} else {
77+
throw new Error(
78+
`Default export for module specified incorrectly. It should containts
79+
either type extending "TurboModule" or "codegenNativeComponent".`,
80+
);
5381
}
54-
throw new Error(
55-
`Default export for module specified incorrectly. It should containts
56-
either "TurboModuleRegistry.getEnforcing" or "codegenNativeComponent".`,
57-
);
5882
}
5983

60-
function buildSchema(contents: string): ?SchemaType {
84+
function buildSchema(contents: string, filename: ?string): ?SchemaType {
6185
const ast = flowParser.parse(contents);
6286

63-
const configType = getConfigType(ast);
64-
6587
const types = getTypes(ast);
6688

89+
const configType = getConfigType(ast, types);
90+
6791
if (configType === 'component') {
6892
return buildComponentSchema(processComponent(ast, types));
6993
} else {
70-
return buildModuleSchema(processModule(ast, types));
94+
if (filename === undefined || filename === null) {
95+
throw new Error('Filepath expected while parasing a module');
96+
}
97+
const moduleName = path.basename(filename).slice(6, -3);
98+
return buildModuleSchema(processModule(types), moduleName);
7199
}
72100
}
73101

74102
function parseFile(filename: string): ?SchemaType {
75103
const contents = fs.readFileSync(filename, 'utf8');
76104

77-
return buildSchema(contents);
105+
return buildSchema(contents, filename);
106+
}
107+
108+
function parseModuleFixture(filename: string): ?SchemaType {
109+
const contents = fs.readFileSync(filename, 'utf8');
110+
111+
return buildSchema(contents, 'path/NativeSampleTurboModule.js');
78112
}
79113

80114
function parseString(contents: string): ?SchemaType {
@@ -83,5 +117,6 @@ function parseString(contents: string): ?SchemaType {
83117

84118
module.exports = {
85119
parseFile,
120+
parseModuleFixture,
86121
parseString,
87122
};

packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/failures.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
159159
160160
`;
161161

162-
const INCORRECT_NATIVE_MODULES = `
162+
const NATIVE_MODULE_NULLABLE_BOOLEAN = `
163163
/**
164164
* Copyright (c) Facebook, Inc. and its affiliates.
165165
*
@@ -175,15 +175,15 @@ const INCORRECT_NATIVE_MODULES = `
175175
import type {TurboModule} from '../RCTExport';
176176
import * as TurboModuleRegistry from '../TurboModuleRegistry';
177177
178-
export interface SpecWithoutTypo extends TurboModule {
179-
// no methods
178+
export interface Spec extends TurboModule {
179+
+getSth(a : ?boolean) => void
180180
}
181181
182-
export default TurboModuleRegistry.getEnforcing<SpecWithTypo>('SampleTurboModule');
182+
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
183183
184184
`;
185185

186-
const NATIVE_MODULE_NULLABLE_BOOLEAN = `
186+
const NATIVE_MODULE_NULLABLE_NUMBER = `
187187
/**
188188
* Copyright (c) Facebook, Inc. and its affiliates.
189189
*
@@ -200,14 +200,14 @@ import type {TurboModule} from '../RCTExport';
200200
import * as TurboModuleRegistry from '../TurboModuleRegistry';
201201
202202
export interface Spec extends TurboModule {
203-
+getSth(a : ?boolean) => void
203+
+getSth(a : ?number) => void
204204
}
205205
206206
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
207207
208208
`;
209209

210-
const NATIVE_MODULE_NULLABLE_NUMBER = `
210+
const TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT = `
211211
/**
212212
* Copyright (c) Facebook, Inc. and its affiliates.
213213
*
@@ -223,15 +223,13 @@ const NATIVE_MODULE_NULLABLE_NUMBER = `
223223
import type {TurboModule} from '../RCTExport';
224224
import * as TurboModuleRegistry from '../TurboModuleRegistry';
225225
226-
export interface Spec extends TurboModule {
227-
+getSth(a : ?number) => void
228-
}
229226
230-
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
227+
export default TurboModuleRegistry.getEnforcing<Spec1>('SampleTurboModule1');
228+
export default TurboModuleRegistry.getEnforcing<Spec2>('SampleTurboModule2');
231229
232230
`;
233231

234-
const TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT = `
232+
const TWO_NATIVE_EXTENDING_TURBO_MODULE = `
235233
/**
236234
* Copyright (c) Facebook, Inc. and its affiliates.
237235
*
@@ -247,9 +245,14 @@ const TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT = `
247245
import type {TurboModule} from '../RCTExport';
248246
import * as TurboModuleRegistry from '../TurboModuleRegistry';
249247
248+
export interface Spec extends TurboModule {
249+
+getSth(a : ?number) => void
250+
}
251+
252+
export interface Spec2 extends TurboModule {
253+
+getSth(a : ?number) => void
254+
}
250255
251-
export default TurboModuleRegistry.getEnforcing<Spec1>('SampleTurboModule1');
252-
export default TurboModuleRegistry.getEnforcing<Spec2>('SampleTurboModule2');
253256
254257
`;
255258

@@ -263,5 +266,5 @@ module.exports = {
263266
NATIVE_MODULES_WITH_NOT_EXISTING_TYPE_AS_PARAM,
264267
NATIVE_MODULES_WITH_NOT_EXISTING_TYPE_AS_RETURN,
265268
NATIVE_MODULES_WITH_NOT_ONLY_METHODS,
266-
INCORRECT_NATIVE_MODULES,
269+
TWO_NATIVE_EXTENDING_TURBO_MODULE,
267270
};

packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`RN Codegen Flow Parser Fails with error message INCORRECT_NATIVE_MODULES 1`] = `"Interface properties for \\"SpecWithTypo has been specified incorrectly.\\""`;
4-
53
exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULE_NULLABLE_BOOLEAN 1`] = `"Booleans and numbers cannot be nullable for param \\"a in method \\"getSth\\"."`;
64

75
exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULE_NULLABLE_NUMBER 1`] = `"Booleans and numbers cannot be nullable for param \\"a in method \\"getSth\\"."`;
@@ -18,12 +16,17 @@ exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT
1816

1917
exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Unsupported return promise type for getBool: expected to find annotation for type of promise content"`;
2018

21-
exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = `"File should contain only one default export."`;
19+
exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_EXTENDING_TURBO_MODULE 1`] = `"Found two types extending \\"TurboModule\\" is one file. Split them into separated files."`;
20+
21+
exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = `
22+
"Default export for module specified incorrectly. It should containts
23+
either type extending \\"TurboModule\\" or \\"codegenNativeComponent\\"."
24+
`;
2225

2326
exports[`RN Codegen Flow Parser can generate fixture EMPTY_NATIVE_MODULE 1`] = `
2427
Object {
2528
"modules": Object {
26-
"SampleTurboModule": Object {
29+
"NativeSampleTurboModule": Object {
2730
"nativeModules": Object {
2831
"SampleTurboModule": Object {
2932
"properties": Array [],
@@ -37,7 +40,7 @@ Object {
3740
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WITH_ALIAS 1`] = `
3841
Object {
3942
"modules": Object {
40-
"SampleTurboModule": Object {
43+
"NativeSampleTurboModule": Object {
4144
"nativeModules": Object {
4245
"SampleTurboModule": Object {
4346
"properties": Array [
@@ -77,7 +80,7 @@ Object {
7780
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_ARRAY 1`] = `
7881
Object {
7982
"modules": Object {
80-
"SampleTurboModule": Object {
83+
"NativeSampleTurboModule": Object {
8184
"nativeModules": Object {
8285
"SampleTurboModule": Object {
8386
"properties": Array [
@@ -117,7 +120,7 @@ Object {
117120
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_PARAM_TYPES 1`] = `
118121
Object {
119122
"modules": Object {
120-
"SampleTurboModule": Object {
123+
"NativeSampleTurboModule": Object {
121124
"nativeModules": Object {
122125
"SampleTurboModule": Object {
123126
"properties": Array [
@@ -189,7 +192,7 @@ Object {
189192
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_CALLBACK 1`] = `
190193
Object {
191194
"modules": Object {
192-
"SampleTurboModule": Object {
195+
"NativeSampleTurboModule": Object {
193196
"nativeModules": Object {
194197
"SampleTurboModule": Object {
195198
"properties": Array [
@@ -248,7 +251,7 @@ Object {
248251
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ARRAY 1`] = `
249252
Object {
250253
"modules": Object {
251-
"SampleTurboModule": Object {
254+
"NativeSampleTurboModule": Object {
252255
"nativeModules": Object {
253256
"SampleTurboModule": Object {
254257
"properties": Array [
@@ -306,7 +309,7 @@ Object {
306309
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_OBJECTS 1`] = `
307310
Object {
308311
"modules": Object {
309-
"SampleTurboModule": Object {
312+
"NativeSampleTurboModule": Object {
310313
"nativeModules": Object {
311314
"SampleTurboModule": Object {
312315
"properties": Array [
@@ -453,7 +456,7 @@ Object {
453456
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NULLABLE_PARAM 1`] = `
454457
Object {
455458
"modules": Object {
456-
"SampleTurboModule": Object {
459+
"NativeSampleTurboModule": Object {
457460
"nativeModules": Object {
458461
"SampleTurboModule": Object {
459462
"properties": Array [
@@ -487,7 +490,7 @@ Object {
487490
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE 1`] = `
488491
Object {
489492
"modules": Object {
490-
"SampleTurboModule": Object {
493+
"NativeSampleTurboModule": Object {
491494
"nativeModules": Object {
492495
"SampleTurboModule": Object {
493496
"properties": Array [
@@ -530,7 +533,7 @@ Object {
530533
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_SIMPLE_OBJECT 1`] = `
531534
Object {
532535
"modules": Object {
533-
"SampleTurboModule": Object {
536+
"NativeSampleTurboModule": Object {
534537
"nativeModules": Object {
535538
"SampleTurboModule": Object {
536539
"properties": Array [
@@ -564,7 +567,7 @@ Object {
564567
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_WITH_ALIASES 1`] = `
565568
Object {
566569
"modules": Object {
567-
"SampleTurboModule": Object {
570+
"NativeSampleTurboModule": Object {
568571
"nativeModules": Object {
569572
"SampleTurboModule": Object {
570573
"properties": Array [
@@ -639,7 +642,7 @@ Object {
639642
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_WITH_FLOAT_AND_INT32 1`] = `
640643
Object {
641644
"modules": Object {
642-
"SampleTurboModule": Object {
645+
"NativeSampleTurboModule": Object {
643646
"nativeModules": Object {
644647
"SampleTurboModule": Object {
645648
"properties": Array [

packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('RN Codegen Flow Parser', () => {
2323
.sort()
2424
.forEach(fixtureName => {
2525
it(`can generate fixture ${fixtureName}`, () => {
26-
expect(FlowParser.parseFile(fixtureName)).toMatchSnapshot();
26+
expect(FlowParser.parseModuleFixture(fixtureName)).toMatchSnapshot();
2727
});
2828
});
2929

@@ -32,7 +32,7 @@ describe('RN Codegen Flow Parser', () => {
3232
.forEach(fixtureName => {
3333
it(`Fails with error message ${fixtureName}`, () => {
3434
expect(() => {
35-
FlowParser.parseFile(fixtureName);
35+
FlowParser.parseModuleFixture(fixtureName);
3636
}).toThrowErrorMatchingSnapshot();
3737
});
3838
});

packages/react-native-codegen/src/parsers/flow/modules/index.js

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,28 @@ function getModuleProperties(types, interfaceName) {
1818
return types[interfaceName].body.properties;
1919
}
2020
throw new Error(
21-
`Interface properties for "${interfaceName} has been specified incorrectly."`,
21+
`Interface properties for "${interfaceName}" has been specified incorrectly.`,
2222
);
2323
}
2424

25-
function findModuleConfig(
26-
ast,
27-
): $ReadOnly<{|moduleName: string, interfaceName: string|}> {
28-
const defaultExport = ast.body.filter(
29-
node => node.type === 'ExportDefaultDeclaration',
30-
)[0];
31-
try {
32-
const interfaceName =
33-
defaultExport.declaration.typeArguments.params[0].id.name;
34-
35-
const moduleName = defaultExport.declaration.arguments[0].value;
36-
return {interfaceName, moduleName};
37-
} catch (e) {
38-
throw new Error(
39-
`Default export for module specified incorrectly. It should containts
40-
either "TurboModuleRegistry.getEnforcing" or "codegenNativeComponent".`,
41-
);
42-
}
25+
function findInterfaceName(types) {
26+
return Object.keys(types)
27+
.map(typeName => types[typeName])
28+
.filter(
29+
type =>
30+
type.extends &&
31+
type.extends[0] &&
32+
type.extends[0].id.name === 'TurboModule',
33+
)[0].id.name;
4334
}
4435

4536
// $FlowFixMe there's no flowtype for AST
46-
function processModule(ast, types): NativeModuleSchemaBuilderConfig {
47-
const {interfaceName, moduleName} = findModuleConfig(ast);
37+
function processModule(types): NativeModuleSchemaBuilderConfig {
38+
const interfaceName = findInterfaceName(types);
4839

4940
const moduleProperties = getModuleProperties(types, interfaceName);
5041
const properties = getMethods(moduleProperties, types);
51-
return {properties, filename: moduleName, moduleName};
42+
return {properties};
5243
}
5344

5445
module.exports = {

0 commit comments

Comments
 (0)