Skip to content

Commit

Permalink
Extract the function createParserErrorCapturer into a single function…
Browse files Browse the repository at this point in the history
… in the parsers/utils.js file (#34934)

Summary:
This PR aims to reduce code duplication by extracting `createParserErrorCapturer` function from the flow and typescript folders into a shared parsers/utils.js file. It is a task of #34872:
> Extract the function createParserErrorCapturer ([Flow](https://github.com/facebook/react-native/blob/main/packages/react-native-codegen/src/parsers/flow/utils.js#L122-L143) [TypeScript](https://github.com/facebook/react-native/blob/main/packages/react-native-codegen/src/parsers/typescript/utils.js#L114-L135)) into a single function in the parsers/utils.js file and replace its invocation with this new function.

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[Internal] [Changed] - Extract the function createParserErrorCapturer into a single function in the parsers/utils.js file

Pull Request resolved: #34934

Test Plan:
yarn flow:
<img width="628" alt="image" src="https://user-images.githubusercontent.com/40902940/194948886-d6763e39-ea07-4004-86cc-5287c4783012.png">

yarn lint:
<img width="509" alt="image" src="https://user-images.githubusercontent.com/40902940/194948916-3e54afa5-7e0b-4a61-ac18-8ec306d8c6d4.png">

yarn jest react-native-codegen:
<img width="386" alt="image" src="https://user-images.githubusercontent.com/40902940/194948966-d1e5b12e-02ab-4d53-a4bf-6abaf4d70fbe.png">

Reviewed By: cipolleschi

Differential Revision: D40256048

Pulled By: cipolleschi

fbshipit-source-id: 098519a17d6e3128d236c639b246a706f9dbf66d
  • Loading branch information
MaeIg authored and facebook-github-bot committed Oct 11, 2022
1 parent 966f3cd commit 38fcafe
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 68 deletions.
4 changes: 2 additions & 2 deletions packages/eslint-plugin-specs/react-native-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function requireModuleParser() {

withBabelRegister(config, () => {
RNModuleParser = require('react-native-codegen/src/parsers/flow/modules');
RNParserUtils = require('react-native-codegen/src/parsers/flow/utils');
RNParserUtils = require('react-native-codegen/src/parsers/utils');
});
} else {
const config = {
Expand All @@ -45,7 +45,7 @@ function requireModuleParser() {

withBabelRegister(config, () => {
RNModuleParser = require('react-native-codegen/lib/parsers/flow/modules');
RNParserUtils = require('react-native-codegen/lib/parsers/flow/utils');
RNParserUtils = require('react-native-codegen/lib/parsers/utils');
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/

'use strict';
const {extractNativeModuleName} = require('../utils.js');

const {
extractNativeModuleName,
createParserErrorCapturer,
} = require('../utils.js');
const {ParserError} = require('../errors');

describe('extractnativeModuleName', () => {
it('return filename when it ends with .js', () => {
Expand Down Expand Up @@ -63,3 +69,49 @@ describe('extractnativeModuleName', () => {
expect(nativeModuleName).toBe('NativeModule');
});
});

describe('createParserErrorCapturer', () => {
describe("when function doesn't throw", () => {
it("returns result and doesn't change errors array", () => {
const [errors, guard] = createParserErrorCapturer();
const fn = () => 'result';

const result = guard(fn);
expect(result).toBe('result');
expect(errors).toHaveLength(0);
});
});

describe('when function throws a ParserError', () => {
it('returns null and adds the error in errors array instead of throwing it', () => {
const [errors, guard] = createParserErrorCapturer();
const ErrorThrown = new ParserError(
'moduleName',
null,
'Something went wrong :(',
);
const fn = () => {
throw ErrorThrown;
};

const result = guard(fn);
expect(result).toBe(null);
expect(errors).toHaveLength(1);
expect(errors[0]).toEqual(ErrorThrown);
expect(() => guard(fn)).not.toThrow();
});
});

describe('when function throws another error', () => {
it("throws the error and doesn't change errors array", () => {
const [errors, guard] = createParserErrorCapturer();
const errorMessage = 'Something else went wrong :(';
const fn = () => {
throw new Error(errorMessage);
};

expect(() => guard(fn)).toThrow(errorMessage);
expect(errors).toHaveLength(0);
});
});
});
11 changes: 5 additions & 6 deletions packages/react-native-codegen/src/parsers/flow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ import type {SchemaType} from '../../CodegenSchema.js';
// $FlowFixMe[untyped-import] there's no flowtype flow-parser
const flowParser = require('flow-parser');
const fs = require('fs');
const {extractNativeModuleName} = require('../utils.js');
const {
extractNativeModuleName,
createParserErrorCapturer,
} = require('../utils.js');
const {buildComponentSchema} = require('./components');
const {wrapComponentSchema} = require('./components/schema');
const {buildModuleSchema} = require('./modules');
const {wrapModuleSchema} = require('../parsers-commons');
const {
createParserErrorCapturer,
visit,
isModuleRegistryCall,
} = require('./utils');
const {visit, isModuleRegistryCall} = require('./utils');
const invariant = require('invariant');

function getConfigType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
} from '../../../CodegenSchema.js';

import type {TypeDeclarationMap} from '../utils.js';
import type {ParserErrorCapturer} from '../utils';
import type {ParserErrorCapturer} from '../../utils';
import type {NativeModuleTypeAnnotation} from '../../../CodegenSchema.js';

const {
Expand Down
26 changes: 0 additions & 26 deletions packages/react-native-codegen/src/parsers/flow/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

import type {TypeAliasResolutionStatus} from '../utils';

const {ParserError} = require('../errors');

/**
* This FlowFixMe is supposed to refer to an InterfaceDeclaration or TypeAlias
* declaration type. Unfortunately, we don't have those types, because flow-parser
Expand Down Expand Up @@ -119,29 +117,6 @@ function getValueFromTypes(value: ASTNode, types: TypeDeclarationMap): ASTNode {
return value;
}

export type ParserErrorCapturer = <T>(fn: () => T) => ?T;

function createParserErrorCapturer(): [
Array<ParserError>,
ParserErrorCapturer,
] {
const errors = [];
function guard<T>(fn: () => T): ?T {
try {
return fn();
} catch (error) {
if (!(error instanceof ParserError)) {
throw error;
}
errors.push(error);

return null;
}
}

return [errors, guard];
}

// TODO(T71778680): Flow-type ASTNodes.
function visit(
astNode: $FlowFixMe,
Expand Down Expand Up @@ -213,7 +188,6 @@ function isModuleRegistryCall(node: $FlowFixMe): boolean {
module.exports = {
getValueFromTypes,
resolveTypeAnnotation,
createParserErrorCapturer,
getTypes,
visit,
isModuleRegistryCall,
Expand Down
11 changes: 5 additions & 6 deletions packages/react-native-codegen/src/parsers/typescript/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@
import type {SchemaType} from '../../CodegenSchema.js';
const babelParser = require('@babel/parser');
const fs = require('fs');
const {extractNativeModuleName} = require('../utils.js');
const {
extractNativeModuleName,
createParserErrorCapturer,
} = require('../utils.js');
const {buildComponentSchema} = require('./components');
const {wrapComponentSchema} = require('./components/schema');
const {buildModuleSchema} = require('./modules');
const {wrapModuleSchema} = require('../parsers-commons');

const {
createParserErrorCapturer,
visit,
isModuleRegistryCall,
} = require('./utils');
const {visit, isModuleRegistryCall} = require('./utils');
const invariant = require('invariant');

function getConfigType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
} from '../../../CodegenSchema.js';

import type {TypeDeclarationMap} from '../utils.js';
import type {ParserErrorCapturer} from '../utils';
import type {ParserErrorCapturer} from '../../utils';
import type {NativeModuleTypeAnnotation} from '../../../CodegenSchema.js';

const {
Expand Down
25 changes: 0 additions & 25 deletions packages/react-native-codegen/src/parsers/typescript/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import type {TypeAliasResolutionStatus} from '../utils';

const {ParserError} = require('../errors');
const {parseTopLevelType} = require('./parseTopLevelType');

/**
Expand Down Expand Up @@ -111,29 +110,6 @@ function resolveTypeAnnotation(
};
}

export type ParserErrorCapturer = <T>(fn: () => T) => ?T;

function createParserErrorCapturer(): [
Array<ParserError>,
ParserErrorCapturer,
] {
const errors = [];
function guard<T>(fn: () => T): ?T {
try {
return fn();
} catch (error) {
if (!(error instanceof ParserError)) {
throw error;
}
errors.push(error);

return null;
}
}

return [errors, guard];
}

// TODO(T108222691): Use flow-types for @babel/parser
function visit(
astNode: $FlowFixMe,
Expand Down Expand Up @@ -204,7 +180,6 @@ function isModuleRegistryCall(node: $FlowFixMe): boolean {

module.exports = {
resolveTypeAnnotation,
createParserErrorCapturer,
getTypes,
visit,
isModuleRegistryCall,
Expand Down
26 changes: 26 additions & 0 deletions packages/react-native-codegen/src/parsers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

'use strict';

const {ParserError} = require('./errors');

const path = require('path');

export type TypeAliasResolutionStatus =
Expand All @@ -27,6 +29,30 @@ function extractNativeModuleName(filename: string): string {
return path.basename(filename).split('.')[0];
}

export type ParserErrorCapturer = <T>(fn: () => T) => ?T;

function createParserErrorCapturer(): [
Array<ParserError>,
ParserErrorCapturer,
] {
const errors = [];
function guard<T>(fn: () => T): ?T {
try {
return fn();
} catch (error) {
if (!(error instanceof ParserError)) {
throw error;
}
errors.push(error);

return null;
}
}

return [errors, guard];
}

module.exports = {
extractNativeModuleName,
createParserErrorCapturer,
};

0 comments on commit 38fcafe

Please sign in to comment.