Skip to content

Commit

Permalink
Faster API Generation (#721)
Browse files Browse the repository at this point in the history
* Cache classes and singletons
* Unify search for methods in ancestor for properties.
  • Loading branch information
CedNaru authored Oct 12, 2024
1 parent f252330 commit 6a19acb
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ val jvmReservedMethods = listOf(
arguments = null,
description = null,
briefDescription = null
),
""
)
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,12 @@ fun File.generateApiFrom(jsonSource: File) {

//We first generate singletons so that their index in engine types and engine singleton lists are same.
for (singleton in classService.getSingletons()) {
for (property in singleton.properties) {
classService.updatePropertyIfShouldUseSuper(singleton.name, property.name)
}

generationService.generateSingleton(singleton).writeTo(this)
generationService.generateEngineIndexesForClass(engineIndexFile, singleton)
generationService.generateEngineTypesRegistrationForSingleton(registrationFileSpec, singleton)
}

for (enrichedClass in classService.getClasses()) {
for (property in enrichedClass.properties) {
classService.updatePropertyIfShouldUseSuper(enrichedClass.name, property.name)
}

generationService.generateClass(enrichedClass).writeTo(this)
generationService.generateEngineIndexesForClass(engineIndexFile, enrichedClass)
generationService.generateEngineTypesRegistrationForClass(registrationFileSpec, enrichedClass)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class EnrichedClass(val internal: Class) : TypedTrait, IDocumented {
val inherits = internal.inherits?.escapeUnderscore()
val engineClassDBIndexName = "ENGINECLASS_${internal.name.uppercase(Locale.US)}"
val properties= internal.properties?.toEnriched() ?: listOf()
val methods = internal.methods?.toEnriched(engineClassDBIndexName) ?: listOf()
val methods = internal.methods?.toEnriched() ?: listOf()
val apiType = ApiType.from(internal.apiType)
override val description = internal.description

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import godot.tools.common.constants.Constraints
import godot.tools.common.constants.GodotTypes
import godot.tools.common.extensions.convertToCamelCase

class EnrichedMethod(val internal: Method, engineClassIndexName: String) : CallableTrait, IDocumented {
class EnrichedMethod(val internal: Method) : CallableTrait, IDocumented {
override val arguments = internal.arguments?.toEnriched() ?: listOf()
override val isVararg = internal.isVararg
val name: String
Expand All @@ -36,7 +36,7 @@ class EnrichedMethod(val internal: Method, engineClassIndexName: String) : Calla
override val description = internal.description
}

fun List<Method>.toEnriched(engineClassIndexName: String) = map { EnrichedMethod(it, engineClassIndexName) }
fun List<Method>.toEnriched() = map { EnrichedMethod(it) }

fun EnrichedMethod.isSameSignature(other: EnrichedMethod): Boolean {
val otherInternal = other.internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ import godot.codegen.models.enriched.EnrichedClass
interface IClassService {
fun getSingletons(): List<EnrichedClass>
fun getClasses(): List<EnrichedClass>
fun updatePropertyIfShouldUseSuper(className: String, propertyName: String)
fun findGetSetMethodsAndUpdateProperties()
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import godot.codegen.models.ApiType
import godot.codegen.models.Argument
import godot.codegen.models.Method
import godot.codegen.models.ReturnValue
import godot.codegen.models.enriched.EnrichedClass
import godot.codegen.models.enriched.EnrichedMethod
import godot.codegen.models.enriched.EnrichedProperty
import godot.codegen.repositories.ClassRepository
import godot.codegen.repositories.SingletonRepository
import godot.codegen.services.IClassGraphService
Expand All @@ -19,15 +21,15 @@ class ClassService(
private val classRepository: ClassRepository,
private val singletonRepository: SingletonRepository,
private val classGraphService: IClassGraphService
) : IClassService{
override fun getSingletons() = singletonRepository
) : IClassService {
private val singletons = singletonRepository
.list()
.map {
classRepository.findByClassName(it.type)?.copy(it.name) ?: throw NoMatchingClassFoundException(it.type)
}
.filter { it.apiType == ApiType.CORE }

override fun getClasses() = classRepository
private val classes = classRepository
.list()
.filter {
for (singleton in singletonRepository.list()) {
Expand All @@ -36,60 +38,59 @@ class ClassService(
it.apiType == ApiType.CORE
}

override fun updatePropertyIfShouldUseSuper(className: String, propertyName: String) {
fun inner(className: String, propertyName: String, isSetter: Boolean) {
val clazz = classRepository.findByClassName(className) ?: throw NoMatchingClassFoundException(className)
val property = clazz.properties.first { it.name == propertyName }

val setter = property.internal.setter

if (isSetter && setter == null) return

val methodName = if (isSetter) setter!! else property.internal.getter
val returnType = if (isSetter) "" else property.type
val arguments = if (isSetter) {
listOf(Argument(property.name, property.type, null, null))
} else {
listOf()
}
override fun getSingletons() = singletons

override fun getClasses() = classes

private fun findGetterSetterInAncestor(clazz: EnrichedClass, property: EnrichedProperty, isSetter: Boolean) {
val methodName: String
val returnType: String
val arguments: List<Argument>

if (isSetter) {
if(property.setterMethod != null) return
methodName = property.internal.setter ?: return // Early return if the property doesn't have a setter.
returnType = ""
arguments = listOf(Argument(property.name, property.type, null, null))
} else {
if(property.getterMethod != null) return
methodName = property.internal.getter // No need to check, a property always has at least a getter.
returnType = property.type
arguments = listOf()
}

val method = EnrichedMethod(
Method(
name = methodName,
isConst = false,
isVararg = false,
isVirtual = false,
isStatic = false,
hash = 0,
hashCompatibility = listOf(),
returnValue = ReturnValue(returnType, null),
returnType = null,
arguments = arguments,
description = null,
briefDescription = null
),
clazz.engineClassDBIndexName
val method = EnrichedMethod(
Method(
name = methodName,
isConst = false,
isVararg = false,
isVirtual = false,
isStatic = false,
hash = 0,
hashCompatibility = listOf(),
returnValue = ReturnValue(returnType, null),
returnType = null,
arguments = arguments,
description = null,
briefDescription = null
)
)

val parentClassAndMethod = classGraphService.getMethodFromAncestor(clazz, method)
val hasValidAccessor = if (isSetter) property.hasValidSetterInClass else property.hasValidGetterInClass
if (parentClassAndMethod != null && !hasValidAccessor) {
if (isSetter) {
property.setterMethod = parentClassAndMethod.second
} else {
property.getterMethod = parentClassAndMethod.second
}
val parentClassAndMethod = classGraphService.getMethodFromAncestor(clazz, method)
val hasValidAccessor = if (isSetter) property.hasValidSetterInClass else property.hasValidGetterInClass
if (parentClassAndMethod != null && !hasValidAccessor) {
if (isSetter) {
property.setterMethod = parentClassAndMethod.second
} else {
property.getterMethod = parentClassAndMethod.second
}
}

inner(className, propertyName, true)
inner(className, propertyName, false)
}

override fun findGetSetMethodsAndUpdateProperties() {
for (enrichedClass in classRepository.list()) {
for (property in enrichedClass.properties) {
for (method in enrichedClass.methods) {
for (clazz in classRepository.list()) {
for (property in clazz.properties) {
for (method in clazz.methods) {
if (property.name == "") continue

when (method.name) {
Expand All @@ -102,6 +103,7 @@ class ClassService(

property.getterMethod = method
}

property.setter -> {
if (method.getTypeClassName().className != UNIT || method.arguments.size > 2 || method.internal.isVirtual) continue

Expand All @@ -113,6 +115,8 @@ class ClassService(
}
}
}
findGetterSetterInAncestor(clazz, property, false)
findGetterSetterInAncestor(clazz, property, true)
}
}
}
Expand Down

0 comments on commit 6a19acb

Please sign in to comment.