Skip to content

Commit 8ffaede

Browse files
tarunrajputfacebook-github-bot
authored andcommitted
add handleGenericTypeAnnotation in parser-commons (#37525)
Summary: Part of #34872 Move the switch construct from [parsers/typescript/utils.js](https://github.com/facebook/react-native/blob/e133100721939108b0f28dfa9f60ac627c804018/packages/react-native-codegen/src/parsers/typescript/utils.js#L59-L93) and [parsers/flow/utils.js](https://github.com/facebook/react-native/blob/e133100721939108b0f28dfa9f60ac627c804018/packages/react-native-codegen/src/parsers/flow/utils.js#L56-L81) to the parsers-commons.js file, in a handleGenericTypeAnnotation function. Use that function in place of the switch. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [Internal][Added]: Added handleGenericTypeAnnotation in parsers-commons Pull Request resolved: #37525 Test Plan: `yarn test` Reviewed By: cortinico Differential Revision: D46264650 Pulled By: cipolleschi fbshipit-source-id: a315ee8cad24d91c9e98e5533d4cdc8b43ebc9a0
1 parent 0af806e commit 8ffaede

File tree

6 files changed

+263
-65
lines changed

6 files changed

+263
-65
lines changed

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

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
getCommandOptions,
2626
getOptions,
2727
getCommandTypeNameAndOptionsExpression,
28+
getTypeResolutionStatus,
29+
handleGenericTypeAnnotation,
2830
} from '../parsers-commons';
2931
import type {ParserType} from '../errors';
3032

@@ -1544,3 +1546,120 @@ describe('getCommandTypeNameAndOptionsExpression', () => {
15441546
});
15451547
});
15461548
});
1549+
1550+
describe('getTypeResolutionStatus', () => {
1551+
it('returns type resolution status for a type declaration', () => {
1552+
const typeAnnotation = {
1553+
id: {
1554+
name: 'TypeAnnotationName',
1555+
},
1556+
};
1557+
expect(
1558+
getTypeResolutionStatus('alias', typeAnnotation, flowParser),
1559+
).toEqual({
1560+
successful: true,
1561+
type: 'alias',
1562+
name: 'TypeAnnotationName',
1563+
});
1564+
});
1565+
1566+
it('returns type resolution status for an enum declaration', () => {
1567+
const typeAnnotation = {
1568+
id: {
1569+
name: 'TypeAnnotationName',
1570+
},
1571+
};
1572+
expect(getTypeResolutionStatus('enum', typeAnnotation, flowParser)).toEqual(
1573+
{
1574+
successful: true,
1575+
type: 'enum',
1576+
name: 'TypeAnnotationName',
1577+
},
1578+
);
1579+
});
1580+
});
1581+
1582+
describe('handleGenericTypeAnnotation', () => {
1583+
it('returns when TypeAnnotation is a type declaration', () => {
1584+
const typeAnnotation = {
1585+
id: {
1586+
name: 'TypeAnnotationName',
1587+
},
1588+
};
1589+
const resolvedTypeAnnotation = {
1590+
type: 'TypeAlias',
1591+
right: {
1592+
type: 'TypeAnnotation',
1593+
},
1594+
};
1595+
expect(
1596+
handleGenericTypeAnnotation(
1597+
typeAnnotation,
1598+
resolvedTypeAnnotation,
1599+
flowParser,
1600+
),
1601+
).toEqual({
1602+
typeAnnotation: {
1603+
type: 'TypeAnnotation',
1604+
},
1605+
typeResolutionStatus: {
1606+
successful: true,
1607+
type: 'alias',
1608+
name: 'TypeAnnotationName',
1609+
},
1610+
});
1611+
});
1612+
1613+
it('returns when TypeAnnotation is an enum declaration', () => {
1614+
const typeAnnotation = {
1615+
id: {
1616+
name: 'TypeAnnotationName',
1617+
},
1618+
};
1619+
const resolvedTypeAnnotation = {
1620+
type: 'EnumDeclaration',
1621+
body: {
1622+
type: 'TypeAnnotation',
1623+
},
1624+
};
1625+
expect(
1626+
handleGenericTypeAnnotation(
1627+
typeAnnotation,
1628+
resolvedTypeAnnotation,
1629+
flowParser,
1630+
),
1631+
).toEqual({
1632+
typeAnnotation: {
1633+
type: 'TypeAnnotation',
1634+
},
1635+
typeResolutionStatus: {
1636+
successful: true,
1637+
type: 'enum',
1638+
name: 'TypeAnnotationName',
1639+
},
1640+
});
1641+
});
1642+
1643+
it('throws when the non GenericTypeAnnotation is unsupported', () => {
1644+
const typeAnnotation = {
1645+
type: 'UnsupportedTypeAnnotation',
1646+
id: {
1647+
name: 'UnsupportedType',
1648+
},
1649+
};
1650+
const resolvedTypeAnnotation = {
1651+
type: 'UnsupportedTypeAnnotation',
1652+
};
1653+
expect(() =>
1654+
handleGenericTypeAnnotation(
1655+
typeAnnotation,
1656+
resolvedTypeAnnotation,
1657+
flowParser,
1658+
),
1659+
).toThrow(
1660+
new Error(
1661+
parser.genericTypeAnnotationErrorMessage(resolvedTypeAnnotation),
1662+
),
1663+
);
1664+
});
1665+
});

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

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,15 @@ const {flowTranslateTypeAnnotation} = require('./modules');
5555
// $FlowFixMe[untyped-import] there's no flowtype flow-parser
5656
const flowParser = require('flow-parser');
5757

58-
const {buildSchema, buildPropSchema} = require('../parsers-commons');
58+
const {
59+
buildSchema,
60+
buildPropSchema,
61+
buildModuleSchema,
62+
handleGenericTypeAnnotation,
63+
} = require('../parsers-commons');
5964
const {Visitor} = require('../parsers-primitives');
6065
const {buildComponentSchema} = require('./components');
6166
const {wrapComponentSchema} = require('../schema.js');
62-
const {buildModuleSchema} = require('../parsers-commons.js');
6367

6468
const fs = require('fs');
6569

@@ -411,36 +415,16 @@ class FlowParser implements Parser {
411415
break;
412416
}
413417

414-
const resolvedTypeAnnotation = types[node.id.name];
418+
const typeAnnotationName = this.nameForGenericTypeAnnotation(node);
419+
const resolvedTypeAnnotation = types[typeAnnotationName];
415420
if (resolvedTypeAnnotation == null) {
416421
break;
417422
}
418423

419-
switch (resolvedTypeAnnotation.type) {
420-
case parser.typeAlias: {
421-
typeResolutionStatus = {
422-
successful: true,
423-
type: 'alias',
424-
name: node.id.name,
425-
};
426-
node = resolvedTypeAnnotation.right;
427-
break;
428-
}
429-
case parser.enumDeclaration: {
430-
typeResolutionStatus = {
431-
successful: true,
432-
type: 'enum',
433-
name: node.id.name,
434-
};
435-
node = resolvedTypeAnnotation.body;
436-
break;
437-
}
438-
default: {
439-
throw new TypeError(
440-
`A non GenericTypeAnnotation must be a type declaration ('${parser.typeAlias}') or enum ('${parser.enumDeclaration}'). Instead, got the unsupported ${resolvedTypeAnnotation.type}.`,
441-
);
442-
}
443-
}
424+
const {typeAnnotation: typeAnnotationNode, typeResolutionStatus: status} =
425+
handleGenericTypeAnnotation(node, resolvedTypeAnnotation, this);
426+
typeResolutionStatus = status;
427+
node = typeAnnotationNode;
444428
}
445429

446430
return {
@@ -531,6 +515,18 @@ class FlowParser implements Parser {
531515
);
532516
}
533517
}
518+
519+
nextNodeForTypeAlias(typeAnnotation: $FlowFixMe): $FlowFixMe {
520+
return typeAnnotation.right;
521+
}
522+
523+
nextNodeForEnum(typeAnnotation: $FlowFixMe): $FlowFixMe {
524+
return typeAnnotation.body;
525+
}
526+
527+
genericTypeAnnotationErrorMessage(typeAnnotation: $FlowFixMe): string {
528+
return `A non GenericTypeAnnotation must be a type declaration ('${this.typeAlias}') or enum ('${this.enumDeclaration}'). Instead, got the unsupported ${typeAnnotation.type}.`;
529+
}
534530
}
535531

536532
module.exports = {

packages/react-native-codegen/src/parsers/parser.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,4 +378,19 @@ export interface Parser {
378378
};
379379

380380
getProperties(typeName: string, types: TypeDeclarationMap): $FlowFixMe;
381+
382+
/**
383+
* Given a typeAlias, it returns the next node.
384+
*/
385+
nextNodeForTypeAlias(typeAnnotation: $FlowFixMe): $FlowFixMe;
386+
387+
/**
388+
* Given an enum Declaration, it returns the next node.
389+
*/
390+
nextNodeForEnum(typeAnnotation: $FlowFixMe): $FlowFixMe;
391+
392+
/**
393+
* Given a unsupported typeAnnotation, returns an error message.
394+
*/
395+
genericTypeAnnotationErrorMessage(typeAnnotation: $FlowFixMe): string;
381396
}

packages/react-native-codegen/src/parsers/parserMock.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,4 +456,16 @@ export class MockedParser implements Parser {
456456
);
457457
}
458458
}
459+
460+
nextNodeForTypeAlias(typeAnnotation: $FlowFixMe): $FlowFixMe {
461+
return typeAnnotation.right;
462+
}
463+
464+
nextNodeForEnum(typeAnnotation: $FlowFixMe): $FlowFixMe {
465+
return typeAnnotation.body;
466+
}
467+
468+
genericTypeAnnotationErrorMessage(typeAnnotation: $FlowFixMe): string {
469+
return `A non GenericTypeAnnotation must be a type declaration ('${this.typeAlias}') or enum ('${this.enumDeclaration}'). Instead, got the unsupported ${typeAnnotation.type}.`;
470+
}
459471
}

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

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ import type {
3030

3131
import type {Parser} from './parser';
3232
import type {ParserType} from './errors';
33-
import type {ParserErrorCapturer, TypeDeclarationMap, PropAST} from './utils';
33+
import type {
34+
ParserErrorCapturer,
35+
TypeDeclarationMap,
36+
PropAST,
37+
TypeResolutionStatus,
38+
} from './utils';
3439
import type {ComponentSchemaBuilderConfig} from './schema.js';
3540

3641
const {
@@ -983,6 +988,71 @@ function getCommandProperties(ast: $FlowFixMe, parser: Parser) {
983988
return properties;
984989
}
985990

991+
function getTypeResolutionStatus(
992+
type: 'alias' | 'enum',
993+
typeAnnotation: $FlowFixMe,
994+
parser: Parser,
995+
): TypeResolutionStatus {
996+
return {
997+
successful: true,
998+
type,
999+
name: parser.nameForGenericTypeAnnotation(typeAnnotation),
1000+
};
1001+
}
1002+
1003+
function handleGenericTypeAnnotation(
1004+
typeAnnotation: $FlowFixMe,
1005+
resolvedTypeAnnotation: TypeDeclarationMap,
1006+
parser: Parser,
1007+
): {
1008+
typeAnnotation: $FlowFixMe,
1009+
typeResolutionStatus: TypeResolutionStatus,
1010+
} {
1011+
let typeResolutionStatus;
1012+
let node;
1013+
1014+
switch (resolvedTypeAnnotation.type) {
1015+
case parser.typeAlias: {
1016+
typeResolutionStatus = getTypeResolutionStatus(
1017+
'alias',
1018+
typeAnnotation,
1019+
parser,
1020+
);
1021+
node = parser.nextNodeForTypeAlias(resolvedTypeAnnotation);
1022+
break;
1023+
}
1024+
case parser.enumDeclaration: {
1025+
typeResolutionStatus = getTypeResolutionStatus(
1026+
'enum',
1027+
typeAnnotation,
1028+
parser,
1029+
);
1030+
node = parser.nextNodeForEnum(resolvedTypeAnnotation);
1031+
break;
1032+
}
1033+
// parser.interfaceDeclaration is not used here because for flow it should fall through to default case and throw an error
1034+
case 'TSInterfaceDeclaration': {
1035+
typeResolutionStatus = getTypeResolutionStatus(
1036+
'alias',
1037+
typeAnnotation,
1038+
parser,
1039+
);
1040+
node = resolvedTypeAnnotation;
1041+
break;
1042+
}
1043+
default: {
1044+
throw new TypeError(
1045+
parser.genericTypeAnnotationErrorMessage(resolvedTypeAnnotation),
1046+
);
1047+
}
1048+
}
1049+
1050+
return {
1051+
typeAnnotation: node,
1052+
typeResolutionStatus,
1053+
};
1054+
}
1055+
9861056
module.exports = {
9871057
wrapModuleSchema,
9881058
unwrapNullable,
@@ -1007,4 +1077,6 @@ module.exports = {
10071077
getEventArgument,
10081078
findComponentConfig,
10091079
getCommandProperties,
1080+
handleGenericTypeAnnotation,
1081+
getTypeResolutionStatus,
10101082
};

0 commit comments

Comments
 (0)