Revert D16200939: [codegen] Change module parser to consider extends instead of default exports

Differential Revision:
D16200939

Original commit changeset: a21cbfc46164

fbshipit-source-id: a551d5a9dbc7eef5c67b725e59d712fb323bd01e
This commit is contained in:
Ben Cheng
2019-07-11 10:05:16 -07:00
committed by Facebook Github Bot
parent cbd4ad43c0
commit f83f611f56
6 changed files with 91 additions and 120 deletions
+20 -55
View File
@@ -14,7 +14,6 @@ import type {SchemaType} from '../../CodegenSchema.js';
// $FlowFixMe there's no flowtype flow-parser
const flowParser = require('flow-parser');
const fs = require('fs');
const path = require('path');
const {buildModuleSchema} = require('./modules/schema');
const {buildComponentSchema} = require('./components/schema');
const {processComponent} = require('./components');
@@ -36,79 +35,46 @@ function getTypes(ast) {
}, {});
}
function getConfigType(ast, types): 'module' | 'component' {
function getConfigType(ast): 'module' | 'component' {
const defaultExports = ast.body.filter(
node => node.type === 'ExportDefaultDeclaration',
);
const isComponent =
defaultExports[0] &&
defaultExports[0].declaration &&
defaultExports[0].declaration.callee &&
defaultExports[0].declaration.callee.name === 'codegenNativeComponent';
const typesExtendingTurboModule = Object.keys(types)
.map(typeName => types[typeName])
.filter(
type =>
type.extends &&
type.extends[0] &&
type.extends[0].id.name === 'TurboModule',
);
if (typesExtendingTurboModule.length > 1) {
throw new Error(
'Found two types extending "TurboModule" is one file. Split them into separated files.',
);
if (defaultExports.length !== 1) {
throw new Error('File should contain only one default export.');
}
const isModule = typesExtendingTurboModule.length === 1;
if (isModule && isComponent) {
throw new Error(
'Found type extending "TurboModule" and exported "codegenNativeComponent" declaration in one file. Split them into separated files.',
);
}
if (isModule) {
return 'module';
} else if (isComponent) {
return 'component';
} else {
throw new Error(
`Default export for module specified incorrectly. It should containts
either type extending "TurboModule" or "codegenNativeComponent".`,
);
if (defaultExports[0].declaration && defaultExports[0].declaration.callee) {
const statement = defaultExports[0].declaration.callee;
if (statement.name === 'codegenNativeComponent') {
return 'component';
}
if (statement.object && statement.object.name === 'TurboModuleRegistry') {
return 'module';
}
}
throw new Error(
`Default export for module specified incorrectly. It should containts
either "TurboModuleRegistry.getEnforcing" or "codegenNativeComponent".`,
);
}
function buildSchema(contents: string, filename: ?string): ?SchemaType {
function buildSchema(contents: string): ?SchemaType {
const ast = flowParser.parse(contents);
const types = getTypes(ast);
const configType = getConfigType(ast);
const configType = getConfigType(ast, types);
const types = getTypes(ast);
if (configType === 'component') {
return buildComponentSchema(processComponent(ast, types));
} else {
if (filename === undefined || filename === null) {
throw new Error('Filepath expected while parasing a module');
}
const moduleName = path.basename(filename).slice(6, -3);
return buildModuleSchema(processModule(types), moduleName);
return buildModuleSchema(processModule(ast, types));
}
}
function parseFile(filename: string): ?SchemaType {
const contents = fs.readFileSync(filename, 'utf8');
return buildSchema(contents, filename);
}
function parseModuleFixture(filename: string): ?SchemaType {
const contents = fs.readFileSync(filename, 'utf8');
return buildSchema(contents, 'path/NativeSampleTurboModule.js');
return buildSchema(contents);
}
function parseString(contents: string): ?SchemaType {
@@ -117,6 +83,5 @@ function parseString(contents: string): ?SchemaType {
module.exports = {
parseFile,
parseModuleFixture,
parseString,
};
@@ -159,6 +159,30 @@ export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;
const INCORRECT_NATIVE_MODULES = `
/**
* 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';
export interface SpecWithoutTypo extends TurboModule {
// no methods
}
export default TurboModuleRegistry.getEnforcing<SpecWithTypo>('SampleTurboModule');
`;
const NATIVE_MODULE_NULLABLE_BOOLEAN = `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
@@ -227,33 +251,6 @@ import * as TurboModuleRegistry from '../TurboModuleRegistry';
export default TurboModuleRegistry.getEnforcing<Spec1>('SampleTurboModule1');
export default TurboModuleRegistry.getEnforcing<Spec2>('SampleTurboModule2');
`;
const TWO_NATIVE_EXTENDING_TURBO_MODULE = `
/**
* 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';
export interface Spec extends TurboModule {
+getSth(a : ?number) => void
}
export interface Spec2 extends TurboModule {
+getSth(a : ?number) => void
}
`;
module.exports = {
@@ -266,5 +263,5 @@ module.exports = {
NATIVE_MODULES_WITH_NOT_EXISTING_TYPE_AS_PARAM,
NATIVE_MODULES_WITH_NOT_EXISTING_TYPE_AS_RETURN,
NATIVE_MODULES_WITH_NOT_ONLY_METHODS,
TWO_NATIVE_EXTENDING_TURBO_MODULE,
INCORRECT_NATIVE_MODULES,
};
@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`RN Codegen Flow Parser Fails with error message INCORRECT_NATIVE_MODULES 1`] = `"Interface properties for \\"SpecWithTypo has been specified incorrectly.\\""`;
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\\"."`;
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\\"."`;
@@ -16,17 +18,12 @@ exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT
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"`;
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."`;
exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = `
"Default export for module specified incorrectly. It should containts
either type extending \\"TurboModule\\" or \\"codegenNativeComponent\\"."
`;
exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = `"File should contain only one default export."`;
exports[`RN Codegen Flow Parser can generate fixture EMPTY_NATIVE_MODULE 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [],
@@ -40,7 +37,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WITH_ALIAS 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -80,7 +77,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_ARRAY 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -120,7 +117,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_PARAM_TYPES 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -192,7 +189,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_CALLBACK 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -251,7 +248,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ARRAY 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -309,7 +306,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_OBJECTS 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -456,7 +453,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NULLABLE_PARAM 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -490,7 +487,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -533,7 +530,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_SIMPLE_OBJECT 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -567,7 +564,7 @@ Object {
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_WITH_ALIASES 1`] = `
Object {
"modules": Object {
"NativeSampleTurboModule": Object {
"SampleTurboModule": Object {
"nativeModules": Object {
"SampleTurboModule": Object {
"properties": Array [
@@ -23,7 +23,7 @@ describe('RN Codegen Flow Parser', () => {
.sort()
.forEach(fixtureName => {
it(`can generate fixture ${fixtureName}`, () => {
expect(FlowParser.parseModuleFixture(fixtureName)).toMatchSnapshot();
expect(FlowParser.parseFile(fixtureName)).toMatchSnapshot();
});
});
@@ -32,7 +32,7 @@ describe('RN Codegen Flow Parser', () => {
.forEach(fixtureName => {
it(`Fails with error message ${fixtureName}`, () => {
expect(() => {
FlowParser.parseModuleFixture(fixtureName);
FlowParser.parseFile(fixtureName);
}).toThrowErrorMatchingSnapshot();
});
});
@@ -18,28 +18,37 @@ function getModuleProperties(types, interfaceName) {
return types[interfaceName].body.properties;
}
throw new Error(
`Interface properties for "${interfaceName}" has been specified incorrectly.`,
`Interface properties for "${interfaceName} has been specified incorrectly."`,
);
}
function findInterfaceName(types) {
return Object.keys(types)
.map(typeName => types[typeName])
.filter(
type =>
type.extends &&
type.extends[0] &&
type.extends[0].id.name === 'TurboModule',
)[0].id.name;
function findModuleConfig(
ast,
): $ReadOnly<{|moduleName: string, interfaceName: string|}> {
const defaultExport = ast.body.filter(
node => node.type === 'ExportDefaultDeclaration',
)[0];
try {
const interfaceName =
defaultExport.declaration.typeArguments.params[0].id.name;
const moduleName = defaultExport.declaration.arguments[0].value;
return {interfaceName, moduleName};
} catch (e) {
throw new Error(
`Default export for module specified incorrectly. It should containts
either "TurboModuleRegistry.getEnforcing" or "codegenNativeComponent".`,
);
}
}
// $FlowFixMe there's no flowtype for AST
function processModule(types): NativeModuleSchemaBuilderConfig {
const interfaceName = findInterfaceName(types);
function processModule(ast, types): NativeModuleSchemaBuilderConfig {
const {interfaceName, moduleName} = findModuleConfig(ast);
const moduleProperties = getModuleProperties(types, interfaceName);
const properties = getMethods(moduleProperties, types);
return {properties};
return {properties, filename: moduleName, moduleName};
}
module.exports = {
@@ -13,16 +13,19 @@
import type {SchemaType, MethodTypeShape} from '../../../CodegenSchema.js';
export type NativeModuleSchemaBuilderConfig = $ReadOnly<{|
filename: string,
moduleName: string,
properties: $ReadOnlyArray<MethodTypeShape>,
|}>;
function buildModuleSchema(
{properties}: NativeModuleSchemaBuilderConfig,
moduleName: string,
): SchemaType {
function buildModuleSchema({
filename,
moduleName,
properties,
}: NativeModuleSchemaBuilderConfig): SchemaType {
return {
modules: {
[`Native${moduleName}`]: {
[filename]: {
nativeModules: {
[moduleName]: {
properties,