Skip to content

Commit 05454fa

Browse files
Pranav-yadavfacebook-github-bot
authored andcommitted
Merge Parse-Module-Name anon fn of Flow & TS parsers' (#36297)
Summary: Part of Umbrella #34872 > [**Codegen 84** - assigned to Pranav-yadav] It depends on [Codegen 83] export the parseModuleName anonymous function (Flow, TypeScript) in a common parseModuleName function in the parsers-commons.js file. - merged Parse Module-Name _**anon**_ fn of `Flow` & `TS` parsers; into a common `parseModuleName` fn in the `parsers-commons.js` - added **tests** for `parseModuleName` fn from `parsers-commons.js` - added `callExpressionTypeParameters` method to **_parsers_** - added **tests** for `callExpressionTypeParameters` method of _parsers_ - used `parser.callExpressionTypeParameters` method in `parseModuleName` fn PS: fixed merge conflicts several times :( Overall :) ## Changelog [INTERNAL] [CHANGED] - Merge Parse-Module-Name anon fn of `Flow` & `TS` and add `callExpressionTypeParameters` method to **_parsers_** Pull Request resolved: #36297 Test Plan: - `yarn lint && yarn run flow && yarn test react-native-codegen` ==> ✅ Reviewed By: rshest Differential Revision: D43694563 Pulled By: cipolleschi fbshipit-source-id: 99cf40ada0a567cd9ff91078f66fd4ac3684f7cc
1 parent b0863e1 commit 05454fa

File tree

9 files changed

+379
-133
lines changed

9 files changed

+379
-133
lines changed

packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
unwrapNullable,
2020
buildSchemaFromConfigType,
2121
buildSchema,
22+
parseModuleName,
2223
} from '../parsers-commons';
2324
import type {ParserType} from '../errors';
2425

@@ -30,6 +31,11 @@ const {isModuleRegistryCall} = require('../utils.js');
3031
const {
3132
ParserError,
3233
UnsupportedObjectPropertyTypeAnnotationParserError,
34+
UnusedModuleInterfaceParserError,
35+
MoreThanOneModuleRegistryCallsParserError,
36+
IncorrectModuleRegistryCallArityParserError,
37+
IncorrectModuleRegistryCallArgumentTypeParserError,
38+
UntypedModuleRegistryCallParserError,
3339
} = require('../errors');
3440

3541
import {MockedParser} from '../parserMock';
@@ -783,3 +789,221 @@ describe('buildSchema', () => {
783789
});
784790
});
785791
});
792+
793+
describe('parseModuleName', () => {
794+
const hasteModuleName = 'testModuleName';
795+
const emptyFlowAst = parser.getAst('');
796+
const moduleSpecs = [{name: 'Spec'}];
797+
const flowAstWithOneCallExpression = parser.getAst(
798+
"export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');",
799+
);
800+
801+
describe('throwIfUnusedModuleInterfaceParserError', () => {
802+
it("throws an 'UnusedModuleInterfaceParserError' error if 'callExpressions' array is 'empty'", () => {
803+
const expected = new UnusedModuleInterfaceParserError(
804+
hasteModuleName,
805+
moduleSpecs[0],
806+
);
807+
808+
expect(() =>
809+
parseModuleName(hasteModuleName, moduleSpecs[0], emptyFlowAst, parser),
810+
).toThrow(expected);
811+
});
812+
813+
it("doesn't throw an 'UnusedModuleInterfaceParserError' error if 'callExpressions' array is 'NOT empty'", () => {
814+
expect(() =>
815+
parseModuleName(
816+
hasteModuleName,
817+
moduleSpecs[0],
818+
flowAstWithOneCallExpression,
819+
parser,
820+
),
821+
).not.toThrow(UnusedModuleInterfaceParserError);
822+
});
823+
});
824+
825+
describe('throwIfMoreThanOneModuleRegistryCalls', () => {
826+
it("throws an 'MoreThanOneModuleRegistryCallsParserError' error if 'callExpressions' array contains more than one 'callExpression'", () => {
827+
const flowAstWithTwoCallExpressions = parser.getAst(
828+
"export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule'); TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');",
829+
);
830+
831+
const callExpressions: Array<$FlowFixMe> =
832+
flowAstWithTwoCallExpressions.body;
833+
834+
const expected = new MoreThanOneModuleRegistryCallsParserError(
835+
hasteModuleName,
836+
callExpressions,
837+
callExpressions.length,
838+
);
839+
840+
expect(() =>
841+
parseModuleName(
842+
hasteModuleName,
843+
moduleSpecs[0],
844+
flowAstWithTwoCallExpressions,
845+
parser,
846+
),
847+
).toThrow(expected);
848+
});
849+
850+
it("doesn't throw an 'MoreThanOneModuleRegistryCallsParserError' error if 'callExpressions' array contains extactly one 'callExpression'", () => {
851+
expect(() =>
852+
parseModuleName(
853+
hasteModuleName,
854+
moduleSpecs[0],
855+
flowAstWithOneCallExpression,
856+
parser,
857+
),
858+
).not.toThrow(MoreThanOneModuleRegistryCallsParserError);
859+
});
860+
});
861+
862+
describe('throwIfWrongNumberOfCallExpressionArgs', () => {
863+
it("throws an 'IncorrectModuleRegistryCallArityParserError' error if wrong number of call expression args is used", () => {
864+
const flowAstWithZeroCallExpressionArgs = parser.getAst(
865+
'export default TurboModuleRegistry.getEnforcing();',
866+
);
867+
const flowCallExpressionWithoutArgs =
868+
flowAstWithZeroCallExpressionArgs.body[0].declaration;
869+
const numberOfCallExpressionArgs =
870+
flowCallExpressionWithoutArgs.arguments.length;
871+
const flowCallExpressionWithoutArgsCallee =
872+
flowCallExpressionWithoutArgs.callee.property.name;
873+
874+
const expected = new IncorrectModuleRegistryCallArityParserError(
875+
hasteModuleName,
876+
flowCallExpressionWithoutArgs,
877+
flowCallExpressionWithoutArgsCallee,
878+
numberOfCallExpressionArgs,
879+
);
880+
881+
expect(() =>
882+
parseModuleName(
883+
hasteModuleName,
884+
moduleSpecs[0],
885+
flowAstWithZeroCallExpressionArgs,
886+
parser,
887+
),
888+
).toThrow(expected);
889+
});
890+
891+
it("doesn't throw an 'IncorrectModuleRegistryCallArityParserError' error if correct number of call expression args is used", () => {
892+
expect(() =>
893+
parseModuleName(
894+
hasteModuleName,
895+
moduleSpecs[0],
896+
flowAstWithOneCallExpression,
897+
parser,
898+
),
899+
).not.toThrow(IncorrectModuleRegistryCallArityParserError);
900+
});
901+
});
902+
903+
describe('throwIfIncorrectModuleRegistryCallArgument', () => {
904+
it("throws an 'IncorrectModuleRegistryCallArgumentTypeParserError' error if call expression arg is NOT a string literal", () => {
905+
const flowAstWithNonStringLiteralCallExpressionArg = parser.getAst(
906+
'export default TurboModuleRegistry.getEnforcing(Spec);',
907+
);
908+
const flowCallExpression =
909+
flowAstWithNonStringLiteralCallExpressionArg.body[0].declaration;
910+
const flowCallExpressionCalllee = flowCallExpression.callee.property.name;
911+
const flowCallExpressionArg = flowCallExpression.arguments[0];
912+
913+
const expected = new IncorrectModuleRegistryCallArgumentTypeParserError(
914+
hasteModuleName,
915+
flowCallExpressionArg,
916+
flowCallExpressionCalllee,
917+
flowCallExpressionArg.type,
918+
);
919+
920+
expect(() =>
921+
parseModuleName(
922+
hasteModuleName,
923+
moduleSpecs[0],
924+
flowAstWithNonStringLiteralCallExpressionArg,
925+
parser,
926+
),
927+
).toThrow(expected);
928+
});
929+
930+
it("doesn't throw an 'IncorrectModuleRegistryCallArgumentTypeParserError' error if call expression arg is a string literal", () => {
931+
expect(() =>
932+
parseModuleName(
933+
hasteModuleName,
934+
moduleSpecs[0],
935+
flowAstWithOneCallExpression,
936+
parser,
937+
),
938+
).not.toThrow(IncorrectModuleRegistryCallArgumentTypeParserError);
939+
});
940+
});
941+
942+
describe('throwIfUntypedModule', () => {
943+
it("throws an 'UntypedModuleRegistryCallParserError' error if call expression is untyped", () => {
944+
const flowAstWithUntypedCallExpression = parser.getAst(
945+
"export default TurboModuleRegistry.getEnforcing('SampleTurboModule');",
946+
);
947+
const flowCallExpression =
948+
flowAstWithUntypedCallExpression.body[0].declaration;
949+
const flowCallExpressionCallee = flowCallExpression.callee.property.name;
950+
const moduleName = flowCallExpression.arguments[0].value;
951+
const expected = new UntypedModuleRegistryCallParserError(
952+
hasteModuleName,
953+
flowCallExpression,
954+
flowCallExpressionCallee,
955+
moduleName,
956+
);
957+
958+
expect(() =>
959+
parseModuleName(
960+
hasteModuleName,
961+
moduleSpecs[0],
962+
flowAstWithUntypedCallExpression,
963+
parser,
964+
),
965+
).toThrow(expected);
966+
});
967+
968+
it("doesn't throw an 'UntypedModuleRegistryCallParserError' error if call expression is typed", () => {
969+
expect(() =>
970+
parseModuleName(
971+
hasteModuleName,
972+
moduleSpecs[0],
973+
flowAstWithOneCallExpression,
974+
parser,
975+
),
976+
).not.toThrow(UntypedModuleRegistryCallParserError);
977+
});
978+
});
979+
980+
describe('when flow ast with valid module is passed', () => {
981+
it("returns the correct ModuleName and doesn't throw any error", () => {
982+
const moduleType = 'Spec';
983+
const moduleName = 'SampleTurboModule';
984+
const flowAstWithValidModule = parser.getAst(
985+
`export default TurboModuleRegistry.getEnforcing<${moduleType}>('${moduleName}');`,
986+
);
987+
988+
const expected = moduleName;
989+
990+
expect(
991+
parseModuleName(
992+
hasteModuleName,
993+
moduleSpecs[0],
994+
flowAstWithValidModule,
995+
parser,
996+
),
997+
).toEqual(expected);
998+
999+
expect(() =>
1000+
parseModuleName(
1001+
hasteModuleName,
1002+
moduleSpecs[0],
1003+
flowAstWithValidModule,
1004+
parser,
1005+
),
1006+
).not.toThrow();
1007+
});
1008+
});
1009+
});

packages/react-native-codegen/src/parsers/__tests__/parsers-test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,27 @@ describe('FlowParser', () => {
8989
expect(parser.isModuleInterface(node)).toBe(false);
9090
});
9191
});
92+
93+
describe('callExpressionTypeParameters', () => {
94+
it('returns type arguments if it is a valid node', () => {
95+
const node = {
96+
type: 'CallExpression',
97+
typeArguments: {
98+
type: 'TypeParameterInstantiation',
99+
params: [],
100+
},
101+
};
102+
expect(parser.callExpressionTypeParameters(node)).toEqual({
103+
type: 'TypeParameterInstantiation',
104+
params: [],
105+
});
106+
});
107+
108+
it('returns null if it is a invalid node', () => {
109+
const node = {};
110+
expect(parser.callExpressionTypeParameters(node)).toBe(null);
111+
});
112+
});
92113
});
93114

94115
describe('TypeScriptParser', () => {
@@ -160,4 +181,25 @@ describe('TypeScriptParser', () => {
160181
expect(parser.isModuleInterface(node)).toBe(false);
161182
});
162183
});
184+
185+
describe('callExpressionTypeParameters', () => {
186+
it('returns type parameters if it is a valid node', () => {
187+
const node = {
188+
type: 'CallExpression',
189+
typeParameters: {
190+
type: 'TypeParameterInstantiation',
191+
params: [],
192+
},
193+
};
194+
expect(parser.callExpressionTypeParameters(node)).toEqual({
195+
type: 'TypeParameterInstantiation',
196+
params: [],
197+
});
198+
});
199+
200+
it('returns null if it is a invalid node', () => {
201+
const node = {};
202+
expect(parser.callExpressionTypeParameters(node)).toBe(null);
203+
});
204+
});
163205
});

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

Lines changed: 10 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@ import type {
2424
import type {Parser} from '../../parser';
2525
import type {ParserErrorCapturer, TypeDeclarationMap} from '../../utils';
2626

27-
const {visit, isModuleRegistryCall, verifyPlatforms} = require('../../utils');
27+
const {verifyPlatforms} = require('../../utils');
2828
const {resolveTypeAnnotation} = require('../utils');
2929
const {
3030
unwrapNullable,
3131
wrapNullable,
3232
assertGenericTypeAnnotationHasExactlyOneTypeParameter,
3333
parseObjectProperty,
3434
buildPropertySchema,
35+
parseModuleName,
3536
} = require('../../parsers-commons');
3637
const {
3738
emitArrayType,
@@ -62,12 +63,6 @@ const {
6263
const {
6364
throwIfModuleInterfaceNotFound,
6465
throwIfModuleInterfaceIsMisnamed,
65-
throwIfUnusedModuleInterfaceParserError,
66-
throwIfWrongNumberOfCallExpressionArgs,
67-
throwIfMoreThanOneModuleRegistryCalls,
68-
throwIfIncorrectModuleRegistryCallTypeParameterParserError,
69-
throwIfIncorrectModuleRegistryCallArgument,
70-
throwIfUntypedModule,
7166
throwIfMoreThanOneModuleInterfaceParserError,
7267
throwIfPartialNotAnnotatingTypeParameter,
7368
throwIfPartialWithMoreParameter,
@@ -362,65 +357,14 @@ function buildModuleSchema(
362357
throwIfModuleInterfaceIsMisnamed(hasteModuleName, moduleSpec.id, language);
363358

364359
// Parse Module Name
365-
const moduleName = ((): string => {
366-
const callExpressions = [];
367-
visit(ast, {
368-
CallExpression(node) {
369-
if (isModuleRegistryCall(node)) {
370-
callExpressions.push(node);
371-
}
372-
},
373-
});
374-
375-
throwIfUnusedModuleInterfaceParserError(
376-
hasteModuleName,
377-
moduleSpec,
378-
callExpressions,
379-
);
380-
381-
throwIfMoreThanOneModuleRegistryCalls(
382-
hasteModuleName,
383-
callExpressions,
384-
callExpressions.length,
385-
);
386-
387-
const [callExpression] = callExpressions;
388-
const {typeArguments} = callExpression;
389-
const methodName = callExpression.callee.property.name;
390-
391-
throwIfWrongNumberOfCallExpressionArgs(
392-
hasteModuleName,
393-
callExpression,
394-
methodName,
395-
callExpression.arguments.length,
396-
);
397-
398-
throwIfIncorrectModuleRegistryCallArgument(
399-
hasteModuleName,
400-
callExpression.arguments[0],
401-
methodName,
402-
);
403-
404-
const $moduleName = callExpression.arguments[0].value;
405-
406-
throwIfUntypedModule(
407-
typeArguments,
408-
hasteModuleName,
409-
callExpression,
410-
methodName,
411-
$moduleName,
412-
);
413-
414-
throwIfIncorrectModuleRegistryCallTypeParameterParserError(
415-
hasteModuleName,
416-
typeArguments,
417-
methodName,
418-
$moduleName,
419-
parser,
420-
);
421-
422-
return $moduleName;
423-
})();
360+
// Also checks and throws error if:
361+
// - Module Interface is Unused
362+
// - More than 1 Module Registry Calls
363+
// - Wrong number of Call Expression Args
364+
// - Module Registry Call Args are Incorrect
365+
// - Module is Untyped
366+
// - Module Registry Call Type Parameter is Icorrect
367+
const moduleName = parseModuleName(hasteModuleName, moduleSpec, ast, parser);
424368

425369
// Some module names use platform suffix to indicate platform-exclusive modules.
426370
// Eventually this should be made explicit in the Flow type itself.

0 commit comments

Comments
 (0)