Skip to content

Commit

Permalink
Remove explicit dependency of JniGenerator on JavaGenerator (#1636)
Browse files Browse the repository at this point in the history
------ Motivation ------
Types defined in `generator/jni` were tightly coupled with types from
`generator/java`.

There are more languages than Java, that could use JNI in the future.
Therefore, removing the explicit dependencies could be beneficial
by avoiding changes in JNI code and making this layer future-proof.

------ Solution ------
Removed the explicit dependencies on types and functions related to
`generator/java` from `generator/jni` by injecting them via constructors.

Signed-off-by: Patryk Wrobel <183546751+pwrobeldev@users.noreply.github.com>
  • Loading branch information
pwrobeldev authored Jan 14, 2025
1 parent eff29f1 commit b453f88
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,16 @@ internal class JavaGenerator : Generator {
val descendantInterfaces = LimeTypeHelper.collectDescendantInterfaces(jniFilteredModel.topElements)
val jniTemplates =
JniTemplates(
generatorName = GENERATOR_NAME,
platformAttribute = JAVA,
limeReferenceMap = jniFilteredModel.referenceMap,
javaNameRules = javaNameRules,
nameRules = javaNameRules,
externalNameRules =
mapOf(
"getPackageFromImportString" to JavaNameRules.Companion::getPackageFromImportString,
"getClassNamesFromImportString" to JavaNameRules.Companion::getClassNamesFromImportString,
),
signatureResolver = signatureResolver,
basePackages = basePackages,
internalPackages = internalPackage,
internalNamespace = internalNamespace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,30 @@

package com.here.gluecodium.generator.jni

import com.here.gluecodium.generator.java.JavaNameRules
import com.here.gluecodium.model.lime.LimeAttributeType
import com.here.gluecodium.model.lime.LimeExternalDescriptor.Companion.NAME_NAME
import com.here.gluecodium.model.lime.LimeInterface
import com.here.gluecodium.model.lime.LimeLambda
import com.here.gluecodium.model.lime.LimeNamedElement
import java.io.File

internal class JniFileNameRules(generatorName: String, private val nameResolver: JniNameResolver) {
internal class JniFileNameRules(
generatorName: String,
private val platformAttribute: LimeAttributeType,
private val nameResolver: JniNameResolver,
) {
private val jniPathPrefix = generatorName + File.separator + "jni" + File.separator

fun getHeaderFilePath(fileName: String) = "$jniPathPrefix$fileName.h"

fun getImplementationFilePath(fileName: String) = "$jniPathPrefix$fileName.cpp"

fun getConversionFileName(limeElement: LimeNamedElement): String {
val externalName = limeElement.external?.java?.get(NAME_NAME)
val externalName = limeElement.external?.getFor(platformAttribute)?.get(NAME_NAME)
return when {
externalName != null -> {
val packageNames = JavaNameRules.getPackageFromImportString(externalName)
val classNames = JavaNameRules.getClassNamesFromImportString(externalName)
val packageNames = nameResolver.getPackageFromImportString(externalName)
val classNames = nameResolver.getClassNamesFromImportString(externalName)
(packageNames + classNames).joinToString("_")
}
else -> getElementFileNamePrefix(limeElement)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ package com.here.gluecodium.generator.jni

import com.here.gluecodium.common.LimeModelSkipPredicates
import com.here.gluecodium.generator.common.CommonGeneratorPredicates
import com.here.gluecodium.generator.common.PlatformSignatureResolver
import com.here.gluecodium.generator.cpp.CppNameResolver
import com.here.gluecodium.generator.cpp.CppNameRules
import com.here.gluecodium.generator.cpp.CppSignatureResolver
import com.here.gluecodium.generator.java.JavaNameRules
import com.here.gluecodium.generator.java.JavaSignatureResolver
import com.here.gluecodium.model.lime.LimeAttributeType
import com.here.gluecodium.model.lime.LimeAttributeType.JAVA
import com.here.gluecodium.model.lime.LimeBasicType
import com.here.gluecodium.model.lime.LimeBasicType.TypeId.BOOLEAN
import com.here.gluecodium.model.lime.LimeBasicType.TypeId.VOID
Expand All @@ -51,12 +49,12 @@ import com.here.gluecodium.model.lime.LimeTypeRef
*/
internal class JniGeneratorPredicates(
private val limeReferenceMap: Map<String, LimeElement>,
javaNameRules: JavaNameRules,
private val platformSignatureResolver: PlatformSignatureResolver,
private val platformAttribute: LimeAttributeType,
cppNameRules: CppNameRules,
cppNameResolver: CppNameResolver,
private val activeTags: Set<String>,
) {
private val javaSignatureResolver = JavaSignatureResolver(limeReferenceMap, javaNameRules, activeTags)
private val cppSignatureResolver = CppSignatureResolver(limeReferenceMap, cppNameRules)
private val overloadedLambdas = collectOverloadedLambdas()

Expand Down Expand Up @@ -93,13 +91,13 @@ internal class JniGeneratorPredicates(
return typeId.isNumericType || typeId == VOID || typeId == BOOLEAN
},
"isOverloaded" to { limeFunction: Any ->
limeFunction is LimeFunction && javaSignatureResolver.isOverloadedInBindings(limeFunction)
limeFunction is LimeFunction && platformSignatureResolver.isOverloadedInBindings(limeFunction)
},
"needsOrdinalConversion" to

fun(limeEnumeration: Any): Boolean {
if (limeEnumeration !is LimeEnumeration) return false
val descriptor = limeEnumeration.external?.java ?: return false
val descriptor = limeEnumeration.external?.getFor(platformAttribute) ?: return false
return !descriptor.containsKey(CONVERTER_NAME)
},
"needsRefSuffix" to { limeTypeRef: Any ->
Expand All @@ -115,7 +113,7 @@ internal class JniGeneratorPredicates(
)

fun shouldRetain(limeElement: LimeNamedElement) =
LimeModelSkipPredicates.shouldRetainCheckParent(limeElement, activeTags, JAVA, limeReferenceMap)
LimeModelSkipPredicates.shouldRetainCheckParent(limeElement, activeTags, platformAttribute, limeReferenceMap)

private fun collectOverloadedLambdas(): Set<String> {
val lambdas = limeReferenceMap.values.filterIsInstance<LimeLambda>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ package com.here.gluecodium.generator.jni

import com.here.gluecodium.cli.GluecodiumExecutionException
import com.here.gluecodium.generator.common.NameResolver
import com.here.gluecodium.generator.common.NameRules
import com.here.gluecodium.generator.common.ReferenceMapBasedResolver
import com.here.gluecodium.generator.java.JavaNameRules
import com.here.gluecodium.model.lime.LimeAttributeType
import com.here.gluecodium.model.lime.LimeAttributeType.CACHED
import com.here.gluecodium.model.lime.LimeAttributeType.JAVA
import com.here.gluecodium.model.lime.LimeAttributeType.OPTIMIZED
import com.here.gluecodium.model.lime.LimeAttributeValueType.FUNCTION_NAME
import com.here.gluecodium.model.lime.LimeBasicType
Expand All @@ -45,18 +45,23 @@ import com.here.gluecodium.model.lime.LimeTypeRef
import com.here.gluecodium.model.lime.LimeTypedElement

internal class JniNameResolver(
private val platformAttribute: LimeAttributeType,
limeReferenceMap: Map<String, LimeElement>,
private val basePackages: List<String>,
private val javaNameRules: JavaNameRules,
private val nameRules: NameRules,
externalNameRules: Map<String, (String) -> List<String>>,
) : ReferenceMapBasedResolver(limeReferenceMap), NameResolver {
val getPackageFromImportString = externalNameRules["getPackageFromImportString"]!!
val getClassNamesFromImportString = externalNameRules["getClassNamesFromImportString"]!!

override fun resolveName(element: Any): String =
when (element) {
is String -> createJavaTypePath(element)
is LimeType -> resolveTypeName(element)
is LimeTypeRef -> resolveTypeRef(element)
is LimeReturnType -> resolveTypeRef(element.typeRef)
is LimeFunction -> resolveFunctionName(element)
is LimeNamedElement -> javaNameRules.getName(element)
is LimeNamedElement -> nameRules.getName(element)
else ->
throw GluecodiumExecutionException("Unsupported element type ${element.javaClass.name}")
}
Expand All @@ -71,19 +76,19 @@ internal class JniNameResolver(
override fun resolveReferenceName(element: Any) =
when {
element is LimeTypeRef && element.attributes.have(OPTIMIZED) ->
javaNameRules.getName((element.type.actualType as LimeList).elementType.type.actualType) + "LazyNativeList"
nameRules.getName((element.type.actualType as LimeList).elementType.type.actualType) + "LazyNativeList"
element !is LimeType ->
throw GluecodiumExecutionException("Unsupported element type ${element.javaClass.name}")
element.external?.java?.get(CONVERTER_NAME) == null -> resolveTypeName(element)
element.external?.getFor(platformAttribute)?.get(CONVERTER_NAME) == null -> resolveTypeName(element)
else -> createJavaTypePath(basePackages + element.path.head, resolveNestedNames(element))
}

private fun resolveAccessorName(
element: Any,
rule: JavaNameRules.(LimeTypedElement) -> String,
rule: NameRules.(LimeTypedElement) -> String,
): String? {
val limeTypedElement = element as? LimeTypedElement ?: return null
return javaNameRules.rule(limeTypedElement) +
return nameRules.rule(limeTypedElement) +
if (limeTypedElement.attributes.have(CACHED)) "_private" else ""
}

Expand All @@ -103,15 +108,12 @@ internal class JniNameResolver(
is LimeSet -> "java/util/Set"
is LimeMap -> "java/util/Map"
else ->
limeType.external?.java?.get(LimeExternalDescriptor.NAME_NAME)?.let { createJavaTypePath(it) }
limeType.external?.getFor(platformAttribute)?.get(LimeExternalDescriptor.NAME_NAME)?.let { createJavaTypePath(it) }
?: createJavaTypePath(basePackages + actualType.path.head, resolveNestedNames(actualType))
}

private fun createJavaTypePath(importString: String) =
createJavaTypePath(
JavaNameRules.getPackageFromImportString(importString),
JavaNameRules.getClassNamesFromImportString(importString),
)
createJavaTypePath(getPackageFromImportString(importString), getClassNamesFromImportString(importString))

private fun createJavaTypePath(
packageNames: List<String>,
Expand All @@ -122,12 +124,12 @@ internal class JniNameResolver(
}

private fun resolveFunctionName(limeFunction: LimeFunction): String {
val parentLambda = getParentElement(limeFunction) as? LimeLambda ?: return javaNameRules.getName(limeFunction)
return parentLambda.attributes.get(JAVA, FUNCTION_NAME) ?: "apply"
val parentLambda = getParentElement(limeFunction) as? LimeLambda ?: return nameRules.getName(limeFunction)
return parentLambda.attributes.get(platformAttribute, FUNCTION_NAME) ?: "apply"
}

private fun resolveNestedNames(limeElement: LimeNamedElement): List<String> {
val elementName = javaNameRules.getName(limeElement)
val elementName = nameRules.getName(limeElement)
val parentElement = if (limeElement.path.hasParent) getParentElement(limeElement) else null
return when (parentElement) {
null -> listOf(elementName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ package com.here.gluecodium.generator.jni
import com.here.gluecodium.generator.common.CommonGeneratorPredicates
import com.here.gluecodium.generator.common.GeneratedFile
import com.here.gluecodium.generator.common.Include
import com.here.gluecodium.generator.common.NameRules
import com.here.gluecodium.generator.common.OptimizedListsCollector
import com.here.gluecodium.generator.common.PlatformSignatureResolver
import com.here.gluecodium.generator.common.templates.TemplateEngine
import com.here.gluecodium.generator.cpp.CppFullNameResolver
import com.here.gluecodium.generator.cpp.CppIncludeResolver
import com.here.gluecodium.generator.cpp.CppNameCache
import com.here.gluecodium.generator.cpp.CppNameResolver
import com.here.gluecodium.generator.cpp.CppNameRules
import com.here.gluecodium.generator.java.JavaGenerator
import com.here.gluecodium.generator.java.JavaNameRules
import com.here.gluecodium.generator.jni.JniGeneratorPredicates.Companion.hasThrowingFunctions
import com.here.gluecodium.model.lime.LimeAttributeType
import com.here.gluecodium.model.lime.LimeAttributes
Expand All @@ -47,8 +47,12 @@ import com.here.gluecodium.model.lime.LimeStruct
import com.here.gluecodium.model.lime.LimeType

internal class JniTemplates(
generatorName: String,
private val platformAttribute: LimeAttributeType,
private val limeReferenceMap: Map<String, LimeElement>,
javaNameRules: JavaNameRules,
nameRules: NameRules,
externalNameRules: Map<String, (String) -> List<String>>,
signatureResolver: PlatformSignatureResolver,
private val basePackages: List<String>,
internalPackages: List<String>,
private val internalNamespace: List<String>,
Expand All @@ -57,9 +61,9 @@ internal class JniTemplates(
activeTags: Set<String>,
private val descendantInterfaces: Map<String, List<LimeInterface>>,
) {
private val jniNameResolver = JniNameResolver(limeReferenceMap, basePackages, javaNameRules)
private val jniNameResolver = JniNameResolver(platformAttribute, limeReferenceMap, basePackages, nameRules, externalNameRules)
private val cppNameResolver = CppNameResolver(limeReferenceMap, internalNamespace, nameCache)
private val fileNameRules = JniFileNameRules(JavaGenerator.GENERATOR_NAME, jniNameResolver)
private val fileNameRules = JniFileNameRules(generatorName, platformAttribute, jniNameResolver)
private val fullInternalPackages = basePackages + internalPackages
private val nameResolvers =
mapOf(
Expand All @@ -69,8 +73,16 @@ internal class JniTemplates(
"C++" to cppNameResolver,
"C++ FQN" to CppFullNameResolver(nameCache),
)

private val generatorPredicates =
JniGeneratorPredicates(limeReferenceMap, javaNameRules, nameCache.nameRules, cppNameResolver, activeTags)
JniGeneratorPredicates(
limeReferenceMap = limeReferenceMap,
platformSignatureResolver = signatureResolver,
platformAttribute = platformAttribute,
cppNameRules = nameCache.nameRules,
cppNameResolver = cppNameResolver,
activeTags = activeTags,
)

private val cppIncludeResolver = CppIncludeResolver(limeReferenceMap, cppNameRules, internalNamespace)
private val jniIncludeResolver = JniIncludeResolver(fileNameRules, descendantInterfaces)
Expand Down Expand Up @@ -234,7 +246,7 @@ internal class JniTemplates(

mustacheData["includes"] = listOf(selfInclude) +
limeStruct.fields.filter {
CommonGeneratorPredicates.needsImportsForSkippedField(it, LimeAttributeType.JAVA, limeReferenceMap)
CommonGeneratorPredicates.needsImportsForSkippedField(it, platformAttribute, limeReferenceMap)
}.flatMap { cppIncludeResolver.resolveElementImports(it.typeRef) }
val implFile =
GeneratedFile(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ class LimeExternalDescriptor private constructor(
val dart
get() = descriptors[DART_TAG]

fun getFor(target: LimeAttributeType) =
when (target) {
LimeAttributeType.CPP -> cpp
LimeAttributeType.JAVA -> java
LimeAttributeType.SWIFT -> swift
LimeAttributeType.DART -> dart
else -> throw IllegalArgumentException("LimeExternalDescriptor.getFor(): Unknown target language: $target")
}

operator fun plus(other: LimeExternalDescriptor) = LimeExternalDescriptor(descriptors + other.descriptors)

override fun toString() =
Expand Down

0 comments on commit b453f88

Please sign in to comment.