Skip to content

Commit 4ebf9c7

Browse files
authored
Fix callable call issues (#926)
* Fix lambda callable warnings * Fix class name export for function arguments * Warm API classes
1 parent 5d9a95f commit 4ebf9c7

13 files changed

Lines changed: 1332 additions & 211 deletions

File tree

kt/api-generator/src/main/kotlin/godot/codegen/generation/rule/RegistrationRule.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ class RegistrationRule : GodotApiRule<ApiTask>() {
8282
}
8383

8484
private fun RegistrationTask.addMethodBindings(clazz: EnrichedClass) {
85+
engineMethods.addStatement(
86+
"%T.forName(%T::class.java.name,·true,·%T::class.java.classLoader)",
87+
Class::class,
88+
clazz.className,
89+
clazz.className
90+
)
8591
engineMethods.addStatement(
8692
"%T",
8793
clazz.className.nestedClass(API.methodBindingsInnerClassName)

kt/api-generator/src/main/kotlin/godot/codegen/generation/task/RegistrationTask.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class RegistrationTask(
1010
val builder = FileSpec.builder(godotPackage, "RegisterEngineTypes")
1111

1212
val variantMapper = FunSpec.builder("registerVariantMapping")
13-
val engineMethods = FunSpec.builder("registerEngineTypeMethods")
13+
val engineMethods = FunSpec.builder("warmEngineTypes")
1414
val engineTypes = FunSpec.builder("registerEngineTypes")
1515

1616
override fun executeSingle(): FileSpec {

kt/api-generator/src/main/kotlin/godot/codegen/services/impl/CallableGenerationService.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -442,15 +442,24 @@ object CallableGenerationService : ICallableGenerationService {
442442
)
443443
.returns(returnTypeParameter)
444444
.addCode(
445-
CodeBlock.of(
446-
buildString {
447-
append("return·(${Generator.functionParameterName}·as?·%T)?.invoke(")
448-
append(containerInfo.toArgumentsString("args[INDEX]", "INDEX"))
449-
append(")?:·throw·%T()")
450-
},
451-
containerInfo.toErasedLambdaTypeName(returnType = returnTypeParameter),
452-
Core.invalidJvmLambdaException
453-
)
445+
CodeBlock
446+
.builder()
447+
.addStatement(
448+
"val function = %N as? %T ?: throw %T()",
449+
Generator.functionParameterName,
450+
containerInfo.toErasedLambdaTypeName(returnType = returnTypeParameter),
451+
Core.invalidJvmLambdaException
452+
)
453+
.add(
454+
CodeBlock.of(
455+
buildString {
456+
append("return function.invoke(")
457+
append(containerInfo.toArgumentsString("args[INDEX]", "INDEX"))
458+
append(")")
459+
}
460+
)
461+
)
462+
.build()
454463
)
455464
.build()
456465

@@ -718,4 +727,3 @@ object CallableGenerationService : ICallableGenerationService {
718727
}
719728

720729

721-

kt/entry-generation/godot-entry-generator/src/main/kotlin/godot/entrygenerator/ext/TypeExtensions.kt

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,47 @@ import godot.core.Vector4
4747
import godot.core.Vector4i
4848
import godot.entrygenerator.model.Type
4949
import godot.entrygenerator.model.TypeKind
50+
import godot.entrygenerator.model.RegisteredClass
51+
import godot.entrygenerator.settings.Settings
52+
import godot.tools.common.constants.GODOT_AABB
53+
import godot.tools.common.constants.GODOT_ARRAY
54+
import godot.tools.common.constants.GODOT_BOOL
55+
import godot.tools.common.constants.GODOT_CALLABLE
56+
import godot.tools.common.constants.GODOT_COLOR
57+
import godot.tools.common.constants.GODOT_DICTIONARY
58+
import godot.tools.common.constants.GODOT_FLOAT
59+
import godot.tools.common.constants.GODOT_INT
60+
import godot.tools.common.constants.GODOT_NIL
61+
import godot.tools.common.constants.GODOT_NODE_PATH
62+
import godot.tools.common.constants.GODOT_OBJECT
63+
import godot.tools.common.constants.GODOT_PLANE
64+
import godot.tools.common.constants.GODOT_PACKED_BYTE_ARRAY
65+
import godot.tools.common.constants.GODOT_PACKED_COLOR_ARRAY
66+
import godot.tools.common.constants.GODOT_PACKED_FLOAT32_ARRAY
67+
import godot.tools.common.constants.GODOT_PACKED_FLOAT64_ARRAY
68+
import godot.tools.common.constants.GODOT_PACKED_INT32_ARRAY
69+
import godot.tools.common.constants.GODOT_PACKED_INT64_ARRAY
70+
import godot.tools.common.constants.GODOT_PACKED_STRING_ARRAY
71+
import godot.tools.common.constants.GODOT_PACKED_VECTOR2_ARRAY
72+
import godot.tools.common.constants.GODOT_PACKED_VECTOR3_ARRAY
73+
import godot.tools.common.constants.GODOT_PACKED_VECTOR4_ARRAY
74+
import godot.tools.common.constants.GODOT_PROJECTION
75+
import godot.tools.common.constants.GODOT_QUATERNION
76+
import godot.tools.common.constants.GODOT_RECT2
77+
import godot.tools.common.constants.GODOT_RECT2I
78+
import godot.tools.common.constants.GODOT_RID
79+
import godot.tools.common.constants.GODOT_SIGNAL
80+
import godot.tools.common.constants.GODOT_STRING
81+
import godot.tools.common.constants.GODOT_STRING_NAME
82+
import godot.tools.common.constants.GODOT_TRANSFORM2D
83+
import godot.tools.common.constants.GODOT_TRANSFORM3D
84+
import godot.tools.common.constants.GODOT_BASIS
85+
import godot.tools.common.constants.GODOT_VECTOR2
86+
import godot.tools.common.constants.GODOT_VECTOR2I
87+
import godot.tools.common.constants.GODOT_VECTOR3
88+
import godot.tools.common.constants.GODOT_VECTOR3I
89+
import godot.tools.common.constants.GODOT_VECTOR4
90+
import godot.tools.common.constants.GODOT_VECTOR4I
5091
import godot.tools.common.constants.godotApiPackage
5192
import godot.tools.common.constants.godotCorePackage
5293
import godot.tools.common.constants.isCollectionsType
@@ -152,6 +193,60 @@ fun Type.baseGodotType(): Type? {
152193
}
153194
}
154195

196+
fun Type?.toGodotClassName(
197+
settings: Settings,
198+
registeredClassesByFqName: Map<String, RegisteredClass>,
199+
): String = when {
200+
this == null || fqName == Unit::class.qualifiedName || fqName == Any::class.qualifiedName -> ""
201+
kind == TypeKind.ENUM_CLASS -> fqName.substringAfterLast(".")
202+
fqName == Boolean::class.qualifiedName -> GODOT_BOOL
203+
fqName == Byte::class.qualifiedName ||
204+
fqName == Short::class.qualifiedName ||
205+
fqName == Int::class.qualifiedName ||
206+
fqName == NaturalT::class.qualifiedName ||
207+
fqName == Long::class.qualifiedName -> GODOT_INT
208+
fqName == Float::class.qualifiedName ||
209+
fqName == RealT::class.qualifiedName ||
210+
fqName == Double::class.qualifiedName -> GODOT_FLOAT
211+
fqName == String::class.qualifiedName -> GODOT_STRING
212+
fqName == Vector2::class.qualifiedName -> GODOT_VECTOR2
213+
fqName == Vector2i::class.qualifiedName -> GODOT_VECTOR2I
214+
fqName == Rect2::class.qualifiedName -> GODOT_RECT2
215+
fqName == Rect2i::class.qualifiedName -> GODOT_RECT2I
216+
fqName == Vector3::class.qualifiedName -> GODOT_VECTOR3
217+
fqName == Vector3i::class.qualifiedName -> GODOT_VECTOR3I
218+
fqName == Vector4::class.qualifiedName -> GODOT_VECTOR4
219+
fqName == Vector4i::class.qualifiedName -> GODOT_VECTOR4I
220+
fqName == Plane::class.qualifiedName -> GODOT_PLANE
221+
fqName == Quaternion::class.qualifiedName -> GODOT_QUATERNION
222+
fqName == AABB::class.qualifiedName -> GODOT_AABB
223+
fqName == Basis::class.qualifiedName -> GODOT_BASIS
224+
fqName == Color::class.qualifiedName -> GODOT_COLOR
225+
fqName == Transform2D::class.qualifiedName -> GODOT_TRANSFORM2D
226+
fqName == Transform3D::class.qualifiedName -> GODOT_TRANSFORM3D
227+
fqName == Projection::class.qualifiedName -> GODOT_PROJECTION
228+
fqName == StringName::class.qualifiedName -> GODOT_STRING_NAME
229+
fqName == NodePath::class.qualifiedName -> GODOT_NODE_PATH
230+
fqName == RID::class.qualifiedName -> GODOT_RID
231+
fqName == Callable::class.qualifiedName || fqName.startsWith(LambdaCallable::class.qualifiedName!!) -> GODOT_CALLABLE
232+
fqName == Signal::class.qualifiedName -> GODOT_SIGNAL
233+
fqName == Dictionary::class.qualifiedName -> GODOT_DICTIONARY
234+
fqName == VariantArray::class.qualifiedName -> GODOT_ARRAY
235+
fqName == PackedByteArray::class.qualifiedName -> GODOT_PACKED_BYTE_ARRAY
236+
fqName == PackedInt32Array::class.qualifiedName -> GODOT_PACKED_INT32_ARRAY
237+
fqName == PackedInt64Array::class.qualifiedName -> GODOT_PACKED_INT64_ARRAY
238+
fqName == PackedFloat32Array::class.qualifiedName -> GODOT_PACKED_FLOAT32_ARRAY
239+
fqName == PackedFloat64Array::class.qualifiedName -> GODOT_PACKED_FLOAT64_ARRAY
240+
fqName == PackedStringArray::class.qualifiedName -> GODOT_PACKED_STRING_ARRAY
241+
fqName == PackedVector2Array::class.qualifiedName -> GODOT_PACKED_VECTOR2_ARRAY
242+
fqName == PackedVector3Array::class.qualifiedName -> GODOT_PACKED_VECTOR3_ARRAY
243+
fqName == PackedVector4Array::class.qualifiedName -> GODOT_PACKED_VECTOR4_ARRAY
244+
fqName == PackedColorArray::class.qualifiedName -> GODOT_PACKED_COLOR_ARRAY
245+
baseGodotType() != null -> registeredClassesByFqName[fqName]?.getRegisteredName(settings)
246+
?: baseGodotType()!!.fqName.substringAfterLast(".")
247+
else -> fqName.substringAfterLast(".").ifEmpty { GODOT_NIL }.let { if (it == "Object") GODOT_OBJECT else it }
248+
}
249+
155250
fun Type.toTypeName(): TypeName = ClassName(
156251
fqName.substringBeforeLast("."),
157252
fqName.substringAfterLast(".")

kt/entry-generation/godot-entry-generator/src/main/kotlin/godot/entrygenerator/filebuilder/ClassRegistrarFileBuilder.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class ClassRegistrarFileBuilder(
7171

7272
if (!registeredClass.isAbstract) {
7373
ConstructorRegistrationGenerator.generate(className, registerClassControlFlow)
74-
FunctionRegistrationGenerator.generate(registeredClass, className, registerClassControlFlow)
75-
SignalRegistrationGenerator.generate(registeredClass, className, registerClassControlFlow)
74+
FunctionRegistrationGenerator.generate(registeredClass, settings, className, registerClassControlFlow, registeredClassesByFqName)
75+
SignalRegistrationGenerator.generate(registeredClass, settings, className, registerClassControlFlow, registeredClassesByFqName)
7676
PropertyRegistrationGenerator.generate(registeredClass, settings, className, registerClassControlFlow, registeredClassesByFqName)
7777
}
7878

@@ -104,4 +104,3 @@ class ClassRegistrarFileBuilder(
104104
)
105105
}
106106
}
107-

kt/entry-generation/godot-entry-generator/src/main/kotlin/godot/entrygenerator/generator/FunctionRegistrationGenerator.kt

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,27 @@ import godot.core.KtRpcConfig
1313
import godot.entrygenerator.ext.VariantConverterNames
1414
import godot.entrygenerator.ext.getAnnotation
1515
import godot.entrygenerator.ext.isEnum
16+
import godot.entrygenerator.ext.toGodotClassName
1617
import godot.entrygenerator.ext.toKtVariantMemberName
1718
import godot.entrygenerator.model.RegisteredClass
1819
import godot.entrygenerator.model.RegisteredFunction
1920
import godot.entrygenerator.model.RpcAnnotation
2021
import godot.entrygenerator.model.TypeKind
22+
import godot.entrygenerator.settings.Settings
2123
import godot.entrygenerator.utils.asEnumName
2224
import godot.registration.KtFunctionArgument
2325
import godot.tools.common.constants.godotCorePackage
2426
import godot.tools.common.constants.kotlinCollectionsPackage
2527
import godot.tools.common.constants.notificationFunction
2628

2729
object FunctionRegistrationGenerator {
28-
fun generate(registeredClass: RegisteredClass, className: ClassName, registerClassControlFlow: FunSpec.Builder) {
30+
fun generate(
31+
registeredClass: RegisteredClass,
32+
settings: Settings,
33+
className: ClassName,
34+
registerClassControlFlow: FunSpec.Builder,
35+
registeredClassesByFqName: Map<String, RegisteredClass>,
36+
) {
2937
val notificationFunctions = mapOf(
3038
*registeredClass.functions.filter { registeredFunction ->
3139
registeredFunction.isNotificationFunction() && registeredFunction.isDeclaredInThisClass
@@ -74,7 +82,7 @@ object FunctionRegistrationGenerator {
7482
registerClassControlFlow
7583
.addStatement(
7684
getFunctionTemplateString(registeredFunction),
77-
*getTemplateArgs(registeredFunction, className).toTypedArray()
85+
*getTemplateArgs(registeredFunction, settings, className, registeredClassesByFqName).toTypedArray()
7886
)
7987
}
8088
}
@@ -105,14 +113,15 @@ object FunctionRegistrationGenerator {
105113
append(",·%T($variantType,·%S),·%T(%M.ordinal,·%L,·%M.ordinal,·%L))")
106114
}
107115

108-
private fun getTemplateArgs(registeredFunction: RegisteredFunction, className: ClassName): List<Any> {
116+
private fun getTemplateArgs(
117+
registeredFunction: RegisteredFunction,
118+
settings: Settings,
119+
className: ClassName,
120+
registeredClassesByFqName: Map<String, RegisteredClass>,
121+
): List<Any> {
109122
val ktFunctionArgumentClassName = KtFunctionArgument::class.asClassName()
110123

111-
val returnType = if (registeredFunction.returnType?.kind == TypeKind.ENUM_CLASS) {
112-
"Int"
113-
} else {
114-
registeredFunction.returnType?.fqName ?: requireNotNull(Unit::class.qualifiedName)
115-
}
124+
val returnType = registeredFunction.returnType.toGodotClassName(settings, registeredClassesByFqName)
116125

117126
val typeClassName = registeredFunction.returnType?.let { returnTypeInfo ->
118127
ClassName(
@@ -138,7 +147,7 @@ object FunctionRegistrationGenerator {
138147
registeredFunction.parameters.forEach { valueParameter ->
139148
add(ktFunctionArgumentClassName)
140149
add(valueParameter.type.toKtVariantMemberName())
141-
add(valueParameter.type.fqName)
150+
add(valueParameter.type.toGodotClassName(settings, registeredClassesByFqName))
142151
add(valueParameter.name)
143152
}
144153
}

kt/entry-generation/godot-entry-generator/src/main/kotlin/godot/entrygenerator/generator/PropertyRegistrationGenerator.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import godot.core.PropertyUsageFlags
1212
import godot.entrygenerator.ext.hasAnnotation
1313
import godot.entrygenerator.ext.isEnum
1414
import godot.entrygenerator.ext.isJavaCollection
15+
import godot.entrygenerator.ext.toGodotClassName
1516
import godot.entrygenerator.ext.toGodotVariantMemberName
1617
import godot.entrygenerator.ext.toKtVariantMemberName
1718
import godot.entrygenerator.ext.toTypeName
@@ -66,8 +67,11 @@ object PropertyRegistrationGenerator {
6667
className: ClassName,
6768
registeredClassesByFqName: Map<String, RegisteredClass>
6869
) {
69-
val typeFqName = if (registeredProperty.type.isEnum()) "Int" else registeredProperty.type.fqName
70-
val typeFqNameWithNullability = if (registeredProperty.type.isNullable) "$typeFqName?" else typeFqName
70+
val typeGodotName = if (registeredProperty.type.isEnum()) {
71+
"int"
72+
} else {
73+
registeredProperty.type.toGodotClassName(settings, registeredClassesByFqName)
74+
}
7175

7276
val variantType = if (registeredProperty.type.isEnum()) {
7377
"%M(%T.entries.toTypedArray())"
@@ -106,7 +110,7 @@ object PropertyRegistrationGenerator {
106110
typeClassName,
107111
registeredProperty.type.toGodotVariantMemberName(),
108112
typeClassName,
109-
typeFqNameWithNullability,
113+
typeGodotName,
110114
PropertyTypeHintProvider.provide(registeredProperty),
111115
PropertyHintStringGeneratorProvider
112116
.provide(registeredProperty, settings, registeredClassesByFqName)
@@ -122,7 +126,7 @@ object PropertyRegistrationGenerator {
122126
getSetterReference(registeredProperty, className),
123127
registeredProperty.type.toKtVariantMemberName(),
124128
registeredProperty.type.toGodotVariantMemberName(),
125-
typeFqNameWithNullability,
129+
typeGodotName,
126130
PropertyTypeHintProvider.provide(registeredProperty),
127131
PropertyHintStringGeneratorProvider
128132
.provide(registeredProperty, settings, registeredClassesByFqName)
@@ -138,7 +142,7 @@ object PropertyRegistrationGenerator {
138142
"property(%L,·$variantType$variantType,·%S,·%M,·%S,·%L.flag)",
139143
getPropertyReference(registeredProperty, className),
140144
*variantTypeArguments.toTypedArray(),
141-
typeFqNameWithNullability,
145+
typeGodotName,
142146
PropertyTypeHintProvider.provide(registeredProperty),
143147
PropertyHintStringGeneratorProvider
144148
.provide(registeredProperty, settings, registeredClassesByFqName)

kt/entry-generation/godot-entry-generator/src/main/kotlin/godot/entrygenerator/generator/SignalRegistrationGenerator.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,28 @@ import com.squareup.kotlinpoet.CodeBlock
55
import com.squareup.kotlinpoet.FunSpec
66
import com.squareup.kotlinpoet.MemberName.Companion.member
77
import godot.core.VariantCaster
8-
import godot.entrygenerator.EntryGenerator
8+
import godot.entrygenerator.ext.toGodotClassName
99
import godot.entrygenerator.ext.toKtVariantMemberName
10-
import godot.entrygenerator.model.JvmType
1110
import godot.entrygenerator.model.RegisteredClass
1211
import godot.entrygenerator.model.RegisteredSignal
12+
import godot.entrygenerator.settings.Settings
1313
import godot.registration.KtFunctionArgument
1414

1515
object SignalRegistrationGenerator {
16-
fun generate(registeredClass: RegisteredClass, className: ClassName, registerClassControlFlow: FunSpec.Builder) {
16+
fun generate(
17+
registeredClass: RegisteredClass,
18+
settings: Settings,
19+
className: ClassName,
20+
registerClassControlFlow: FunSpec.Builder,
21+
registeredClassesByFqName: Map<String, RegisteredClass>,
22+
) {
1723
registeredClass
1824
.signals
1925
.forEach { registeredSignal ->
2026
registerClassControlFlow
2127
.addStatement(
2228
getStringTemplate(registeredSignal),
23-
*getTemplateArguments(registeredSignal, className)
29+
*getTemplateArguments(registeredSignal, settings, className, registeredClassesByFqName)
2430
)
2531
}
2632
}
@@ -35,7 +41,9 @@ object SignalRegistrationGenerator {
3541

3642
private fun getTemplateArguments(
3743
registeredSignal: RegisteredSignal,
38-
className: ClassName
44+
settings: Settings,
45+
className: ClassName,
46+
registeredClassesByFqName: Map<String, RegisteredClass>,
3947
) = buildList {
4048
add(getPropertyReference(registeredSignal, className))
4149

@@ -44,15 +52,16 @@ object SignalRegistrationGenerator {
4452
val argumentName = registeredSignal.parameterNames.getOrNull(index) ?: "p$index"
4553
add(KtFunctionArgument::class)
4654
add(argumentType.toKtVariantMemberName())
47-
add(argumentType.fqName)
55+
add(argumentType.toGodotClassName(settings, registeredClassesByFqName))
4856
add(argumentName)
4957
}
5058
} else {
5159
registeredSignal.parameterNames.forEachIndexed { index, argumentName ->
5260
val argumentTypeVariantType = registeredSignal.parameterTypes.getOrNull(index)?.toKtVariantMemberName()
5361
?: VariantCaster.ANY
54-
val argumentTypeFqName = registeredSignal.parameterTypes.getOrNull(index)?.fqName
55-
?: EntryGenerator.jvmTypeFqNamesProvider(JvmType.ANY).first()
62+
val argumentTypeFqName = registeredSignal.parameterTypes.getOrNull(index)
63+
?.toGodotClassName(settings, registeredClassesByFqName)
64+
?: ""
5665

5766
add(KtFunctionArgument::class)
5867
add(argumentTypeVariantType)

0 commit comments

Comments
 (0)