@@ -98,7 +98,8 @@ class SignalGenerationService : ISignalGenerationService {
9898
9999 signalFileSpec.addFunction(generateFakeSignalConstructor(argCount, genericClassNameInfo))
100100 signalFileSpec.addFunction(generateSignalDelegate(argCount, genericClassNameInfo))
101- signalFileSpec.addFunction(generateSignalExtension(genericClassNameInfo))
101+ signalFileSpec.addFunction(generateSignalExtension(genericClassNameInfo, false ))
102+ signalFileSpec.addFunction(generateSignalExtension(genericClassNameInfo, true ))
102103 }
103104
104105 return signalFileSpec
@@ -179,6 +180,19 @@ class SignalGenerationService : ISignalGenerationService {
179180 .addCode(generateConnectionCodeBlock())
180181 .build(),
181182
183+ FunSpec .builder(CONNECT_THREAD_SAFE_METHOD_NAME )
184+ .addTypeVariable(godotObjectBoundTypeVariable)
185+ .addParameters(
186+ listOf (
187+ ParameterSpec .builder(TARGET_PARAMETER_NAME , godotObjectBoundTypeVariable).build(),
188+ ParameterSpec .builder(METHOD_PARAMETER_NAME , lambdaTypeName).build(),
189+ flagsParameter
190+ )
191+ )
192+ .returns(ANY .copy(nullable = true ))
193+ .addCode(generateConnectionCodeBlock(false , true ))
194+ .build(),
195+
182196 FunSpec .builder(DISCONNECT_METHOD_NAME )
183197 .addTypeVariable(godotObjectBoundTypeVariable)
184198 .addParameters(
@@ -196,8 +210,16 @@ class SignalGenerationService : ISignalGenerationService {
196210 .build()
197211 }
198212
199- private fun generateConnectionCodeBlock (isDisconnect : Boolean = false): CodeBlock {
200- val methodName = if (isDisconnect) DISCONNECT_METHOD_NAME else CONNECT_METHOD_NAME
213+ private fun generateConnectionCodeBlock (isDisconnect : Boolean = false, isThreadSafe : Boolean = false): CodeBlock {
214+ val methodName = if (isDisconnect) {
215+ DISCONNECT_METHOD_NAME
216+ } else {
217+ if (isThreadSafe) {
218+ CONNECT_THREAD_SAFE_METHOD_NAME
219+ } else {
220+ CONNECT_METHOD_NAME
221+ }
222+ }
201223 val flagsParameters = if (isDisconnect) " " else " ,·$FLAGS_PARAMETER_NAME "
202224
203225 return CodeBlock .of(
@@ -301,37 +323,37 @@ class SignalGenerationService : ISignalGenerationService {
301323 val genericReadOnlyPropertyClassName = readOnlyPropertyClassName.parameterizedBy(GODOT_OBJECT , genericClassNameInfo.genericClassName)
302324
303325 return genericClassNameInfo
304- .toFunSpecBuilder(SIGNAL_METHOD_NAME + argCount)
305- .addModifiers(KModifier .INLINE )
306- .receiver(GODOT_OBJECT )
307- .addParameters(
308- (0 .. < argCount)
309- .map {
310- ParameterSpec .builder(" p$it " , STRING ).build()
311- }
312- )
313- .addCode(
314- if (argCount == 0 ) {
315- CodeBlock .of(" return·%T.$DELEGATE_PROPERTY_NAME " , genericClassNameInfo.className)
316- } else {
317- CodeBlock .of(" return·%T.$DELEGATE_PROPERTY_NAME ·as·%T" , genericClassNameInfo.className, genericReadOnlyPropertyClassName)
318- }
319- )
320- .apply {
321- if (argCount != 0 ) {
322- addAnnotation(
323- AnnotationSpec
324- .builder(Suppress ::class )
325- .addMember(" \" UNCHECKED_CAST\" " )
326- .build()
327- )
326+ .toFunSpecBuilder(SIGNAL_METHOD_NAME + argCount)
327+ .addModifiers(KModifier .INLINE )
328+ .receiver(GODOT_OBJECT )
329+ .addParameters(
330+ (0 .. < argCount)
331+ .map {
332+ ParameterSpec .builder(" p$it " , STRING ).build()
328333 }
334+ )
335+ .addCode(
336+ if (argCount == 0 ) {
337+ CodeBlock .of(" return·%T.$DELEGATE_PROPERTY_NAME " , genericClassNameInfo.className)
338+ } else {
339+ CodeBlock .of(" return·%T.$DELEGATE_PROPERTY_NAME ·as·%T" , genericClassNameInfo.className, genericReadOnlyPropertyClassName)
340+ }
341+ )
342+ .apply {
343+ if (argCount != 0 ) {
344+ addAnnotation(
345+ AnnotationSpec
346+ .builder(Suppress ::class )
347+ .addMember(" \" UNCHECKED_CAST\" " )
348+ .build()
349+ )
329350 }
330- .build()
351+ }
352+ .build()
331353 }
332354
333355
334- private fun generateSignalExtension (genericClassNameInfo : GenericClassNameInfo ): FunSpec {
356+ private fun generateSignalExtension (genericClassNameInfo : GenericClassNameInfo , isThreadSafe : Boolean ): FunSpec {
335357 val flagsParameter = ParameterSpec .builder(FLAGS_PARAMETER_NAME , INT )
336358 .defaultValue(" 0" )
337359 .build()
@@ -346,23 +368,34 @@ class SignalGenerationService : ISignalGenerationService {
346368 .addModifiers(KModifier .NOINLINE )
347369 .build()
348370
371+ val methodName = if (isThreadSafe) {
372+ CONNECT_THREAD_SAFE_METHOD_NAME
373+ } else {
374+ CONNECT_METHOD_NAME
375+ }
376+
349377 return genericClassNameInfo
350- .toReifiedExtensionFunSpecBuilder(CONNECT_METHOD_NAME )
378+ .toReifiedExtensionFunSpecBuilder(methodName )
351379 .addParameters(
352380 listOf (
353381 flagsParameter,
354382 signalConnectExtensionGenericParameters
355383 )
356384 )
357385 .addCode(
358- " return·$CONNECT_METHOD_NAME ($METHOD_PARAMETER_NAME .%M(),·$FLAGS_PARAMETER_NAME )" ,
386+ " return·$methodName ($METHOD_PARAMETER_NAME .%M(),·$FLAGS_PARAMETER_NAME )" ,
359387 AS_CALLABLE_UTIL_FUNCTION
360388 )
361- .returns(GODOT_ERROR )
389+ .returns(
390+ if (isThreadSafe) {
391+ ANY .copy(nullable = true )
392+ } else {
393+ GODOT_ERROR
394+ }
395+ )
362396 .build()
363397 }
364398
365-
366399 companion object {
367400 private const val SIGNAL_CLASS_NAME = " Signal"
368401 private const val INSTANCE_PARAMETER = " instance"
@@ -375,6 +408,7 @@ class SignalGenerationService : ISignalGenerationService {
375408
376409 private const val EMIT_METHOD_NAME = " emit"
377410 private const val CONNECT_METHOD_NAME = " connect"
411+ private const val CONNECT_THREAD_SAFE_METHOD_NAME = " connectThreadSafe"
378412 private const val DISCONNECT_METHOD_NAME = " disconnect"
379413 private const val SIGNAL_METHOD_NAME = " signal"
380414 private const val JAVA_CREATE_METHOD_NAME = " javaCreate"
0 commit comments