Skip to content

Commit

Permalink
feat: codegen handle negative values in enums
Browse files Browse the repository at this point in the history
  • Loading branch information
okwasniewski committed Nov 6, 2024
1 parent fddf7aa commit 12b7143
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,52 @@ describe('TypeScript Module Parser', () => {
expect(parser).toThrow(UnnamedFunctionParamParserError);
});

it('should properly parse negative enums', () => {
const parser = () =>
parseModule(`
import type {TurboModule} from 'RCTExport';
import * as TurboModuleRegistry from 'TurboModuleRegistry';
enum MyEnum {
ZERO = 0,
POSITIVE = 1,
NEGATIVE = -1,
}
export interface Spec extends TurboModule {
useArg(arg: MyEnum): void;
}
export default TurboModuleRegistry.get<Spec>('Foo');
`);

expect(parser).not.toThrow();
expect(parser().enumMap.MyEnum.members).toEqual([
{name: 'ZERO', value: 0},
{name: 'POSITIVE', value: 1},
{name: 'NEGATIVE', value: -1},
]);
});

it('should properly parse enums', () => {
const parser = () =>
parseModule(`
import type {TurboModule} from 'RCTExport';
import * as TurboModuleRegistry from 'TurboModuleRegistry';
enum MyEnum {
ZERO = 0,
POSITIVE = 1,
}
export interface Spec extends TurboModule {
useArg(arg: MyEnum): void;
}
export default TurboModuleRegistry.get<Spec>('Foo');
`);

expect(parser).not.toThrow();
expect(parser().enumMap.MyEnum.members).toEqual([
{name: 'ZERO', value: 0},
{name: 'POSITIVE', value: 1},
]);
});

[
{nullable: false, optional: false},
{nullable: false, optional: true},
Expand Down
56 changes: 43 additions & 13 deletions packages/react-native-codegen/src/parsers/typescript/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,27 @@ class TypeScriptParser implements Parser {

parseEnumMembersType(typeAnnotation: $FlowFixMe): NativeModuleEnumMemberType {
const enumInitializer = typeAnnotation.members[0]?.initializer;
const enumMembersType: ?NativeModuleEnumMemberType =
!enumInitializer || enumInitializer.type === 'StringLiteral'
? 'StringTypeAnnotation'
: enumInitializer.type === 'NumericLiteral'
? 'NumberTypeAnnotation'
: null;
const enumInitializerType = enumInitializer?.type;

let enumMembersType: ?NativeModuleEnumMemberType = null;

switch (enumInitializerType) {
case undefined:
case 'StringLiteral':
enumMembersType = 'StringTypeAnnotation';
break;
case 'NumericLiteral':
enumMembersType = 'NumberTypeAnnotation';
break;
case 'UnaryExpression':
if (enumInitializer.operator === '-') {
enumMembersType = 'NumberTypeAnnotation';
}
break;
default:
enumMembersType = null;
}

if (!enumMembersType) {
throw new Error(
'Enum values must be either blank, number, or string values.',
Expand All @@ -213,9 +228,14 @@ class TypeScriptParser implements Parser {
: null;

typeAnnotation.members.forEach(member => {
if (
(member.initializer?.type ?? 'StringLiteral') !== enumInitializerType
) {
const isNegative =
member.initializer?.type === 'UnaryExpression' &&
member.initializer?.operator === '-';
const initializerType = isNegative
? member.initializer?.argument?.type
: member.initializer?.type;

if ((initializerType ?? 'StringLiteral') !== enumInitializerType) {
throw new Error(
'Enum values can not be mixed. They all must be either blank, number, or string values.',
);
Expand All @@ -226,10 +246,20 @@ class TypeScriptParser implements Parser {
parseEnumMembers(
typeAnnotation: $FlowFixMe,
): $ReadOnlyArray<NativeModuleEnumMember> {
return typeAnnotation.members.map(member => ({
name: member.id.name,
value: member.initializer?.value ?? member.id.name,
}));
return typeAnnotation.members.map(member => {
// Handle negative values
if (member.initializer?.operator === '-') {
return {
name: member.id.name,
value: -member.initializer?.argument?.value ?? member.id.name,
};
}

return {
name: member.id.name,
value: member.initializer?.value ?? member.id.name,
};
});
}

isModuleInterface(node: $FlowFixMe): boolean {
Expand Down

0 comments on commit 12b7143

Please sign in to comment.