From 4e054828627ff3d530072aa8ffdcaf30fccbc616 Mon Sep 17 00:00:00 2001 From: MaeIg Date: Wed, 25 Jan 2023 12:38:52 -0800 Subject: [PATCH] Extract parseString and parseModuleFixture functions in typescript and flow parsers (#35928) Summary: This PR aims to extract parseString and parseModuleFixture functions into the typescript and flow parsers. This task was proposed in https://github.com/facebook/react-native/issues/35158 and helps https://github.com/facebook/react-native/issues/34872. ## Changelog [Internal] [Changed] - Extract parseString and parseModuleFixture functions in typescript and flow parsers Pull Request resolved: https://github.com/facebook/react-native/pull/35928 Test Plan: yarn test: image yarn flow: image yarn lint: image Reviewed By: jacdebug Differential Revision: D42673866 Pulled By: cipolleschi fbshipit-source-id: f1b5f8a7b3944e7e8223b25c0fb9bf4e8b512aa7 --- packages/babel-plugin-codegen/index.js | 17 +++++-- .../src/parsers/flow/index.js | 47 ------------------- .../__tests__/module-parser-e2e-test.js | 9 ++-- .../__tests__/module-parser-snapshot-test.js | 8 ++-- .../src/parsers/flow/parser.js | 10 ++++ .../src/parsers/parser.js | 19 ++++++-- .../src/parsers/parserMock.js | 40 ++++++++++------ .../src/parsers/typescript/index.js | 47 ------------------- .../typescript-module-parser-e2e-test.js | 9 ++-- .../typescript-module-parser-snapshot-test.js | 9 ++-- .../src/parsers/typescript/parser.js | 10 ++++ 11 files changed, 96 insertions(+), 129 deletions(-) delete mode 100644 packages/react-native-codegen/src/parsers/flow/index.js delete mode 100644 packages/react-native-codegen/src/parsers/typescript/index.js diff --git a/packages/babel-plugin-codegen/index.js b/packages/babel-plugin-codegen/index.js index bb83feb4070e86..4314e6d50eb518 100644 --- a/packages/babel-plugin-codegen/index.js +++ b/packages/babel-plugin-codegen/index.js @@ -9,21 +9,28 @@ 'use strict'; -let flowParser, typeScriptParser, RNCodegen; +let FlowParser, TypeScriptParser, RNCodegen; const {basename} = require('path'); try { - flowParser = require('@react-native/codegen/src/parsers/flow'); - typeScriptParser = require('@react-native/codegen/src/parsers/typescript'); + FlowParser = + require('@react-native/codegen/src/parsers/flow/parser').FlowParser; + TypeScriptParser = + require('@react-native/codegen/src/parsers/typescript/parser').TypeScriptParser; RNCodegen = require('@react-native/codegen/src/generators/RNCodegen'); } catch (e) { // Fallback to lib when source doesn't exit (e.g. when installed as a dev dependency) - flowParser = require('@react-native/codegen/lib/parsers/flow'); - typeScriptParser = require('@react-native/codegen/lib/parsers/typescript'); + FlowParser = + require('@react-native/codegen/lib/parsers/flow/parser').FlowParser; + TypeScriptParser = + require('@react-native/codegen/lib/parsers/typescript/parser').TypeScriptParser; RNCodegen = require('@react-native/codegen/lib/generators/RNCodegen'); } +const flowParser = new FlowParser(); +const typeScriptParser = new TypeScriptParser(); + function parseFile(filename, code) { if (filename.endsWith('js')) { return flowParser.parseString(code); diff --git a/packages/react-native-codegen/src/parsers/flow/index.js b/packages/react-native-codegen/src/parsers/flow/index.js deleted file mode 100644 index e043b7967487dc..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/index.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 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. - * - * @flow strict - * @format - */ - -'use strict'; - -import type {SchemaType} from '../../CodegenSchema.js'; - -const fs = require('fs'); - -const {buildSchema} = require('../parsers-commons'); -const {Visitor} = require('./Visitor'); -const {FlowParser} = require('./parser'); -const {buildComponentSchema} = require('./components'); -const {wrapComponentSchema} = require('./components/schema'); -const {buildModuleSchema} = require('./modules'); - -const parser = new FlowParser(); - -function parseModuleFixture(filename: string): SchemaType { - const contents = fs.readFileSync(filename, 'utf8'); - - return parseString(contents, 'path/NativeSampleTurboModule.js'); -} - -function parseString(contents: string, filename: ?string): SchemaType { - return buildSchema( - contents, - filename, - wrapComponentSchema, - buildComponentSchema, - buildModuleSchema, - Visitor, - parser, - ); -} - -module.exports = { - parseModuleFixture, - parseString, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js index c1f959b7a884fc..07f1ad56afc73e 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js @@ -15,7 +15,8 @@ import type { NativeModuleParamTypeAnnotation, } from '../../../../CodegenSchema'; -const {parseString} = require('../../index.js'); +const invariant = require('invariant'); + const {unwrapNullable} = require('../../../parsers-commons'); const { UnsupportedGenericParserError, @@ -23,7 +24,9 @@ const { UnnamedFunctionParamParserError, MissingTypeParameterGenericParserError, } = require('../../../errors'); -const invariant = require('invariant'); +const {FlowParser} = require('../../parser'); + +const flowParser = new FlowParser(); type PrimitiveTypeAnnotationType = | 'StringTypeAnnotation' @@ -1229,7 +1232,7 @@ describe('Flow Module Parser', () => { }); function parseModule(source: string) { - const schema = parseString(source, `${MODULE_NAME}.js`); + const schema = flowParser.parseString(source, `${MODULE_NAME}.js`); const module = schema.modules.NativeFoo; invariant( module.type === 'NativeModule', diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js index f260240b7fdad6..ec20817c2bfba2 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js @@ -11,11 +11,13 @@ 'use strict'; -const FlowParser = require('../../index.js'); +const {FlowParser} = require('../../parser'); const fixtures = require('../__test_fixtures__/fixtures.js'); const failureFixtures = require('../__test_fixtures__/failures.js'); +const flowParser = new FlowParser(); + jest.mock('fs', () => ({ readFileSync: filename => { // Jest in the OSS does not allow to capture variables in closures. @@ -32,7 +34,7 @@ describe('RN Codegen Flow Parser', () => { .sort() .forEach(fixtureName => { it(`can generate fixture ${fixtureName}`, () => { - const schema = FlowParser.parseModuleFixture(fixtureName); + const schema = flowParser.parseModuleFixture(fixtureName); const serializedSchema = JSON.stringify(schema, null, 2).replace( /"/g, "'", @@ -47,7 +49,7 @@ describe('RN Codegen Flow Parser', () => { .forEach(fixtureName => { it(`Fails with error message ${fixtureName}`, () => { expect(() => { - FlowParser.parseModuleFixture(fixtureName); + flowParser.parseModuleFixture(fixtureName); }).toThrowErrorMatchingSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/parsers/flow/parser.js b/packages/react-native-codegen/src/parsers/flow/parser.js index 59b2a6f9433fac..561ae77a3f19fd 100644 --- a/packages/react-native-codegen/src/parsers/flow/parser.js +++ b/packages/react-native-codegen/src/parsers/flow/parser.js @@ -96,6 +96,10 @@ class FlowParser implements Parser { parseFile(filename: string): SchemaType { const contents = fs.readFileSync(filename, 'utf8'); + return this.parseString(contents, filename); + } + + parseString(contents: string, filename: ?string): SchemaType { return buildSchema( contents, filename, @@ -107,6 +111,12 @@ class FlowParser implements Parser { ); } + parseModuleFixture(filename: string): SchemaType { + const contents = fs.readFileSync(filename, 'utf8'); + + return this.parseString(contents, 'path/NativeSampleTurboModule.js'); + } + getAst(contents: string): $FlowFixMe { return flowParser.parse(contents, { enums: true, diff --git a/packages/react-native-codegen/src/parsers/parser.js b/packages/react-native-codegen/src/parsers/parser.js index 0ccaaf7522015e..9f73635e6eae65 100644 --- a/packages/react-native-codegen/src/parsers/parser.js +++ b/packages/react-native-codegen/src/parsers/parser.js @@ -78,11 +78,24 @@ export interface Parser { types: $FlowFixMe, ): UnionTypeAnnotationMemberType[]; /** - * Given the content of a file and options, it returns an AST. - * @parameter contents: the content of the file. - * @returns: the AST of the file (given in program property for typescript). + * Given the name of a file, it returns a Schema. + * @parameter filename: the name of the file. + * @returns: the Schema of the file. */ parseFile(filename: string): SchemaType; + /** + * Given the content of a file, it returns a Schema. + * @parameter contents: the content of the file. + * @parameter filename: the name of the file. + * @returns: the Schema of the file. + */ + parseString(contents: string, filename: ?string): SchemaType; + /** + * Given the name of a file, it returns a Schema. + * @parameter filename: the name of the file. + * @returns: the Schema of the file. + */ + parseModuleFixture(filename: string): SchemaType; /** * Given the content of a file, it returns an AST. diff --git a/packages/react-native-codegen/src/parsers/parserMock.js b/packages/react-native-codegen/src/parsers/parserMock.js index f0846f17cb07c0..c3caff7aaacd79 100644 --- a/packages/react-native-codegen/src/parsers/parserMock.js +++ b/packages/react-native-codegen/src/parsers/parserMock.js @@ -26,6 +26,22 @@ const { UnsupportedObjectPropertyTypeAnnotationParserError, } = require('./errors'); +const schemaMock = { + modules: { + StringPropNativeComponentView: { + type: 'Component', + components: { + StringPropNativeComponentView: { + extendsProps: [], + events: [], + props: [], + commands: [], + }, + }, + }, + }, +}; + export class MockedParser implements Parser { typeParameterInstantiation: string = 'TypeParameterInstantiation'; @@ -74,21 +90,15 @@ export class MockedParser implements Parser { } parseFile(filename: string): SchemaType { - return { - modules: { - StringPropNativeComponentView: { - type: 'Component', - components: { - StringPropNativeComponentView: { - extendsProps: [], - events: [], - props: [], - commands: [], - }, - }, - }, - }, - }; + return schemaMock; + } + + parseString(contents: string, filename: ?string): SchemaType { + return schemaMock; + } + + parseModuleFixture(filename: string): SchemaType { + return schemaMock; } getAst(contents: string): $FlowFixMe { diff --git a/packages/react-native-codegen/src/parsers/typescript/index.js b/packages/react-native-codegen/src/parsers/typescript/index.js deleted file mode 100644 index ceeb305c6b08da..00000000000000 --- a/packages/react-native-codegen/src/parsers/typescript/index.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 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. - * - * @flow strict - * @format - */ - -'use strict'; - -import type {SchemaType} from '../../CodegenSchema.js'; - -const fs = require('fs'); - -const {buildSchema} = require('../parsers-commons'); -const {Visitor} = require('./Visitor'); -const {TypeScriptParser} = require('./parser'); -const {buildComponentSchema} = require('./components'); -const {wrapComponentSchema} = require('./components/schema'); -const {buildModuleSchema} = require('./modules'); - -const parser = new TypeScriptParser(); - -function parseModuleFixture(filename: string): SchemaType { - const contents = fs.readFileSync(filename, 'utf8'); - - return parseString(contents, 'path/NativeSampleTurboModule.ts'); -} - -function parseString(contents: string, filename: ?string): SchemaType { - return buildSchema( - contents, - filename, - wrapComponentSchema, - buildComponentSchema, - buildModuleSchema, - Visitor, - parser, - ); -} - -module.exports = { - parseModuleFixture, - parseString, -}; diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-e2e-test.js b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-e2e-test.js index 92858546206bed..507895ba589433 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-e2e-test.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-e2e-test.js @@ -15,7 +15,8 @@ import type { NativeModuleParamTypeAnnotation, } from '../../../../CodegenSchema'; -const {parseString} = require('../../index.js'); +const invariant = require('invariant'); + const {unwrapNullable} = require('../../../parsers-commons'); const { UnsupportedGenericParserError, @@ -23,7 +24,9 @@ const { UnnamedFunctionParamParserError, MissingTypeParameterGenericParserError, } = require('../../../errors'); -const invariant = require('invariant'); +const {TypeScriptParser} = require('../../parser'); + +const typescriptParser = new TypeScriptParser(); type PrimitiveTypeAnnotationType = | 'StringTypeAnnotation' @@ -1228,7 +1231,7 @@ describe('TypeScript Module Parser', () => { }); function parseModule(source: string) { - const schema = parseString(source, `${MODULE_NAME}.ts`); + const schema = typescriptParser.parseString(source, `${MODULE_NAME}.ts`); const module = schema.modules.NativeFoo; invariant( module.type === 'NativeModule', diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-snapshot-test.js b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-snapshot-test.js index b831c0710631c0..68b1e694dbf28b 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-snapshot-test.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/typescript-module-parser-snapshot-test.js @@ -11,10 +11,13 @@ 'use strict'; -const TypeScriptParser = require('../../index.js'); +const {TypeScriptParser} = require('../../parser'); + const fixtures = require('../__test_fixtures__/fixtures.js'); const failureFixtures = require('../__test_fixtures__/failures.js'); +const typeScriptParser = new TypeScriptParser(); + jest.mock('fs', () => ({ readFileSync: filename => { // Jest in the OSS does not allow to capture variables in closures. @@ -31,7 +34,7 @@ describe('RN Codegen TypeScript Parser', () => { .sort() .forEach(fixtureName => { it(`can generate fixture ${fixtureName}`, () => { - const schema = TypeScriptParser.parseModuleFixture(fixtureName); + const schema = typeScriptParser.parseModuleFixture(fixtureName); const serializedSchema = JSON.stringify(schema, null, 2).replace( /"/g, "'", @@ -46,7 +49,7 @@ describe('RN Codegen TypeScript Parser', () => { .forEach(fixtureName => { it(`Fails with error message ${fixtureName}`, () => { expect(() => { - TypeScriptParser.parseModuleFixture(fixtureName); + typeScriptParser.parseModuleFixture(fixtureName); }).toThrowErrorMatchingSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/parsers/typescript/parser.js b/packages/react-native-codegen/src/parsers/typescript/parser.js index b95249fbe4be85..40b4af14d8ed95 100644 --- a/packages/react-native-codegen/src/parsers/typescript/parser.js +++ b/packages/react-native-codegen/src/parsers/typescript/parser.js @@ -102,6 +102,10 @@ class TypeScriptParser implements Parser { parseFile(filename: string): SchemaType { const contents = fs.readFileSync(filename, 'utf8'); + return this.parseString(contents, filename); + } + + parseString(contents: string, filename: ?string): SchemaType { return buildSchema( contents, filename, @@ -113,6 +117,12 @@ class TypeScriptParser implements Parser { ); } + parseModuleFixture(filename: string): SchemaType { + const contents = fs.readFileSync(filename, 'utf8'); + + return this.parseString(contents, 'path/NativeSampleTurboModule.ts'); + } + getAst(contents: string): $FlowFixMe { return babelParser.parse(contents, { sourceType: 'module',