Lucky Ozzy
Lucky Ozzy

Reputation: 23

Kotlin KCallable illegalArgumentException

I have the following Kotlin function:

fun invokeSync(typedArguments : List<Any?>): Any?{
    var returnedValue : Any?    
    try {
        returnedValue = callable.call(this, typedArguments);
    } catch (e:Exception) {
        logInvocationError(e, typedArguments);
        throw IllegalArgumentException(e);
    }
}

It doesn't matter how much arguments are in this list, I will always get an IllegalArgumentException saying "Callable expects 3 arguments, but 1 were provided".

The function is a simple isGreater-function with 2 arguments of type Int. I have checked the list of arguments and there are 2 arguments of type Int in there.

Here the function in context:

open class TypedJavaScriptFunction(name: String) : SelfRegisteringJavascriptFunction(MessageFormat.format(JS_NAME_CONVENTION, name)) {

    val callable = getCallable(this::class)

    override fun function(arguments: Array<Any?>): Any? {
        try {
            val typedArguments = getTypedArguments(arguments)
            val annotations = callable.annotations

            for (a in annotations) {
                if (a is BrowserFunction) {
                    if (a.value == Policy.ASYNC) {
                        invokeAsync(typedArguments);
                        return null
                    } else {
                        return invokeSync(typedArguments)
                    }
                }
            }
        } catch (e: IllegalArgumentException) {
            // this Exception is only for signaling the error; it has already
            // been logged before
            JavaScriptAPI.showError(browser, "Internal Error (" + callable.name + ")");
        }
        return null
    }

    fun getTypedArguments(arguments: Array<Any?>): List<Any?> {
        var typedArguments = mutableListOf<Any?>()
        val argTypes = callable.valueParameters
        if (arguments.size != argTypes.size) {
            LOG.error(getName()
                    + ": given arguments don't match signature. Given: "
                    + arguments.size + ", expected: " + argTypes.size);
            throw IllegalArgumentException()
        }

        for (i in 0 until arguments.size) {
            typedArguments.add(TypeRefinery.refine(arguments[i], argTypes[i].type.classifier as KClass<Any>))
        }

        return typedArguments
    }

    // ...

    fun invokeSync(typedArguments: List<Any?>): Any? {
        var returnedValue: Any?
        try {
            returnedValue = callable.call(this, typedArguments);
        } catch (e: Exception) {
            logInvocationError(e, typedArguments);
            throw IllegalArgumentException(e);
        }

        // ...
    }
}

Did anyone can help me and tell me whats wrong or can give me a hint?

Upvotes: 0

Views: 724

Answers (1)

Willi Mentzel
Willi Mentzel

Reputation: 29844

Since call takes a vararg you need to use the spread operator * and toTypedArray() to pass in the List like that:

returnedValue = callable.call(this, *typedArguments.toTypedArray());

The first argument is the instance you are calling the function on and the other two parameters come from the spreaded List, under the condition that List has exactly two elements.

Upvotes: 3

Related Questions