From 45bc6cf897b7897610c9e3a65a61f6dd5d58c27e Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski <janne@kuschku.de>
Date: Sat, 5 Mar 2022 17:40:43 +0100
Subject: [PATCH] fix: correct handling of nullable parameters

---
 .../libquassel/generator/Constants.kt         |  4 ++++
 .../generator/visitors/RpcModelProcessor.kt   | 20 ++++++++++++++++---
 .../kuschku/libquassel/protocol/QVariant.kt   |  2 +-
 .../libquassel/session/ProtocolHandler.kt     | 18 ++++++++++-------
 4 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt b/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt
index 9f2ccc91c..4752898f7 100644
--- a/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt
+++ b/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt
@@ -54,6 +54,10 @@ object Constants {
     "de.kuschku.libquassel.protocol",
     "valueOrThrow"
   )
+  val TYPENAME_QVARIANT_INTO = ClassName(
+    "de.kuschku.libquassel.protocol",
+    "value"
+  )
   val TYPENAME_GENERATED = ClassName(
     "de.justjanne.libquassel.annotations",
     "Generated"
diff --git a/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt b/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt
index 3564f6580..91ba64d81 100644
--- a/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt
+++ b/invokergenerator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt
@@ -22,6 +22,7 @@ import de.justjanne.libquassel.annotations.ProtocolSide
 import de.justjanne.libquassel.generator.Constants.TYPENAME_GENERATED
 import de.justjanne.libquassel.generator.Constants.TYPENAME_INVOKER
 import de.justjanne.libquassel.generator.Constants.TYPENAME_QVARIANTLIST
+import de.justjanne.libquassel.generator.Constants.TYPENAME_QVARIANT_INTO
 import de.justjanne.libquassel.generator.Constants.TYPENAME_QVARIANT_INTOORTHROW
 import de.justjanne.libquassel.generator.Constants.TYPENAME_SYNCABLESTUB
 import de.justjanne.libquassel.generator.Constants.TYPENAME_UNKNOWN_METHOD_EXCEPTION
@@ -47,6 +48,10 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> {
           TYPENAME_QVARIANT_INTOORTHROW.packageName,
           TYPENAME_QVARIANT_INTOORTHROW.simpleName
         )
+        .addImport(
+          TYPENAME_QVARIANT_INTO.packageName,
+          TYPENAME_QVARIANT_INTO.simpleName
+        )
         .addAnnotation(TYPENAME_GENERATED)
         .addType(
           TypeSpec.objectBuilder(name.simpleName)
@@ -93,7 +98,10 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> {
                         addCase(ArgString("%S", method.rpcName ?: method.name), block.data)
                       }
                       buildElse {
-                        addStatement("throw %T(className, method)", TYPENAME_UNKNOWN_METHOD_EXCEPTION)
+                        addStatement(
+                          "throw %T(className, method)",
+                          TYPENAME_UNKNOWN_METHOD_EXCEPTION
+                        )
                       }
                     }
                     nextControlFlow("else")
@@ -122,7 +130,10 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> {
             for ((i, parameter) in model.parameters.withIndex()) {
               val suffix = if (i != lastIndex) "," else ""
               addStatement(
-                "${parameter.name} = params[$i].valueOrThrow<%T>()$suffix",
+                if (parameter.type.isNullable)
+                  "${parameter.name} = params[$i].value<%T>()$suffix"
+                else
+                  "${parameter.name} = params[$i].valueOrThrow<%T>()$suffix",
                 parameter.type
               )
             }
@@ -132,5 +143,8 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> {
       }
     )
 
-  override fun visitParameterModel(model: RpcModel.ParameterModel, data: ProtocolSide): KotlinModel? = null
+  override fun visitParameterModel(
+    model: RpcModel.ParameterModel,
+    data: ProtocolSide
+  ): KotlinModel? = null
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt
index 0bbf59267..95343dde5 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt
@@ -95,7 +95,7 @@ inline fun <reified U> QVariant_?.value(defValue: U): U = this?.data as? U ?: de
 
 inline fun <reified U> QVariant_?.valueOr(f: () -> U): U = this?.data as? U ?: f()
 
-inline fun <reified U> QVariant_?.valueOrThrow(e: Throwable = NullPointerException()): U =
+inline fun <reified U> QVariant_?.valueOrThrow(e: Throwable = ClassCastException("Could not obtain a ${U::class.java.canonicalName} from $this")): U =
   this?.data as? U ?: throw e
 
 inline fun <reified U> QVariant_?.valueOrThrow(e: () -> Throwable): U =
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
index ad21ae593..dfb1d84a5 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
@@ -63,6 +63,7 @@ abstract class ProtocolHandler(
     } catch (e: ObjectNotFoundException) {
       log(DEBUG, "ProtocolHandler", "An error has occured while processing $f", e)
     } catch (e: Throwable) {
+      log(DEBUG, "ProtocolHandler", "An error has occured while processing $f", e)
       exceptionHandler?.invoke(MessageHandlingException.SignalProxy(f, e))
     }
     return true
@@ -130,13 +131,16 @@ abstract class ProtocolHandler(
 
       val invoker = Invokers.get(ProtocolSide.CLIENT, f.className)
         ?: throw IllegalArgumentException("Invalid classname: ${f.className}")
-      currentCallClass = f.className
-      currentCallInstance = f.objectName
-      currentCallSlot = f.slotName
-      invoker.invoke(it, f.slotName, f.params)
-      currentCallClass = ""
-      currentCallInstance = ""
-      currentCallSlot = ""
+      try {
+        currentCallClass = f.className
+        currentCallInstance = f.objectName
+        currentCallSlot = f.slotName
+        invoker.invoke(it, f.slotName, f.params)
+      } finally {
+        currentCallClass = ""
+        currentCallInstance = ""
+        currentCallSlot = ""
+      }
     }
     return true
   }
-- 
GitLab