UNPKG

nitro-codegen

Version:

The code-generator for react-native-nitro-modules.

118 lines (104 loc) 3.65 kB
import { NitroConfig } from '../../config/NitroConfig.js'; import { capitalizeName, indent } from '../../utils.js'; import { createFileMetadataString } from '../helpers.js'; import { EnumType } from '../types/EnumType.js'; export function createKotlinEnum(enumType) { const members = enumType.enumMembers.map((m) => m.name.toUpperCase()); const packageName = NitroConfig.getAndroidPackage('java/kotlin'); const code = ` ${createFileMetadataString(`${enumType.enumName}.kt`)} package ${packageName} import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "${enumType.enumName}". */ @DoNotStrip @Keep enum class ${enumType.enumName} { ${indent(members.join(',\n'), ' ')}; @DoNotStrip @Keep private val _ordinal = ordinal } `.trim(); const cxxNamespace = NitroConfig.getCxxNamespace('c++'); const jniClassDescriptor = NitroConfig.getAndroidPackage('c++/jni', enumType.enumName); const cppToJniConverterCode = getCppToJniConverterCode('value', enumType); const fbjniCode = ` ${createFileMetadataString(`J${enumType.enumName}.hpp`)} #pragma once #include <fbjni/fbjni.h> #include "${enumType.declarationFile.name}" namespace ${cxxNamespace} { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "${enumType.enumName}" and the the Kotlin enum "${enumType.enumName}". */ struct J${enumType.enumName} final: public jni::JavaClass<J${enumType.enumName}> { public: static auto constexpr kJavaDescriptor = "L${jniClassDescriptor};"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum ${enumType.enumName}. */ [[maybe_unused]] [[nodiscard]] ${enumType.enumName} toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldOrdinal = clazz->getField<int>("_ordinal"); int ordinal = this->getFieldValue(fieldOrdinal); return static_cast<${enumType.enumName}>(ordinal); } public: /** * Create a Java/Kotlin-based enum with the given C++ enum's value. */ [[maybe_unused]] static jni::alias_ref<J${enumType.enumName}> fromCpp(${enumType.enumName} value) { ${indent(cppToJniConverterCode, ' ')} } }; } // namespace ${cxxNamespace} `.trim(); const files = []; files.push({ content: code, language: 'kotlin', name: `${enumType.enumName}.kt`, subdirectory: NitroConfig.getAndroidPackageDirectory(), platform: 'android', }); files.push({ content: fbjniCode, language: 'c++', name: `J${enumType.enumName}.hpp`, subdirectory: [], platform: 'android', }); return files; } function getCppToJniConverterCode(cppValueName, enumType) { const jniEnumName = `J${enumType.enumName}`; const fields = enumType.enumMembers.map((m) => { const fieldName = `field${capitalizeName(m.name)}`; return `static const auto ${fieldName} = clazz->getStaticField<${jniEnumName}>("${m.name}");`; }); const cases = enumType.enumMembers.map((m) => { const fieldName = `field${capitalizeName(m.name)}`; return ` case ${enumType.enumName}::${m.name}: return clazz->getStaticFieldValue(${fieldName}); `.trim(); }); return ` static const auto clazz = javaClassStatic(); ${fields.join('\n')} switch (${cppValueName}) { ${indent(cases.join('\n'), ' ')} default: std::string stringValue = std::to_string(static_cast<int>(${cppValueName})); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } `.trim(); }