Add EventEmitter Code-gen support for Java and ObjC Turbo Modules (#45119)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45119

## Changelog:

[iOS][Added] - Add EventEmitter Code-gen support for Java and ObjC Turbo Modules

Reviewed By: RSNara

Differential Revision: D58929417

fbshipit-source-id: 5208ba5ecb5882d47c3827c2aa8e3a54a3d7f2b6
This commit is contained in:
Christoph Purrer
2024-07-01 14:42:46 -07:00
committed by Facebook GitHub Bot
parent 9d3052378a
commit ad3df84668
14 changed files with 1305 additions and 47 deletions
@@ -12,6 +12,7 @@
import type {
NamedShape,
NativeModuleEventEmitterShape,
NativeModuleFunctionTypeAnnotation,
NativeModuleParamTypeAnnotation,
NativeModulePropertyShape,
@@ -23,6 +24,7 @@ import type {AliasResolver} from './Utils';
const {unwrapNullable} = require('../../parsers/parsers-commons');
const {wrapOptional} = require('../TypeUtils/Java');
const {toPascalCase} = require('../Utils');
const {createAliasResolver, getModules} = require('./Utils');
type FilesOutput = Map<string, string>;
@@ -32,11 +34,13 @@ function FileTemplate(
packageName: string,
className: string,
jsName: string,
eventEmitters: string,
methods: string,
imports: string,
}>,
): string {
const {packageName, className, jsName, methods, imports} = config;
const {packageName, className, jsName, eventEmitters, methods, imports} =
config;
return `
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
@@ -65,11 +69,28 @@ public abstract class ${className} extends ReactContextBaseJavaModule implements
return NAME;
}
${methods}
${eventEmitters}${eventEmitters.length > 0 ? '\n\n' : ''}${methods}
}
`;
}
function EventEmitterTemplate(
eventEmitter: NativeModuleEventEmitterShape,
imports: Set<string>,
): string {
return ` protected final void emit${toPascalCase(eventEmitter.name)}(${
eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation'
? `${translateEventEmitterTypeToJavaType(eventEmitter, imports)} value`
: ''
}) {
mEventEmitterCallback.invoke("${eventEmitter.name}"${
eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation'
? ', value'
: ''
});
}`;
}
function MethodTemplate(
config: $ReadOnly<{
abstract: boolean,
@@ -102,6 +123,34 @@ function MethodTemplate(
type Param = NamedShape<Nullable<NativeModuleParamTypeAnnotation>>;
function translateEventEmitterTypeToJavaType(
eventEmitter: NativeModuleEventEmitterShape,
imports: Set<string>,
): string {
switch (eventEmitter.typeAnnotation.typeAnnotation.type) {
case 'StringTypeAnnotation':
return 'String';
case 'NumberTypeAnnotation':
case 'FloatTypeAnnotation':
case 'DoubleTypeAnnotation':
case 'Int32TypeAnnotation':
return 'double';
case 'BooleanTypeAnnotation':
return 'boolean';
case 'ObjectTypeAnnotation':
case 'TypeAliasTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
return 'ReadableMap';
case 'ArrayTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableArray');
return 'ReadableArray';
default:
throw new Error(
`Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`,
);
}
}
function translateFunctionParamToJavaType(
param: Param,
createErrorMessage: (typeName: string) => string,
@@ -533,6 +582,9 @@ module.exports = {
packageName: normalizedPackageName,
className,
jsName: moduleName,
eventEmitters: spec.eventEmitters
.map(eventEmitter => EventEmitterTemplate(eventEmitter, imports))
.join('\n\n'),
methods: methods.filter(Boolean).join('\n\n'),
imports: Array.from(imports)
.sort()