Skip to content

Commit

Permalink
fix: fail to parse function with vararg
Browse files Browse the repository at this point in the history
  • Loading branch information
asforest committed Mar 8, 2022
1 parent 91f549e commit 3d96357
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 23 deletions.
10 changes: 6 additions & 4 deletions src/main/kotlin/command/resolver/ArgumentedFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ data class ArgumentedFunction(
) {
private val isExtensionFunction: Boolean = signature.extensionReceiverParameter != null

private fun buildArgs(extensionReceiver: Any?): kotlin.Array<Any?>
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
private inline fun buildArgs(extensionReceiver: Any?): Array<Any?>
{
return (if(extensionReceiver != null && isExtensionFunction)
listOf(extensionReceiver, *arguments.toTypedArray())
return if(extensionReceiver != null && isExtensionFunction)
arrayOf(extensionReceiver, *arguments.toTypedArray())
else
listOf(*arguments.toTypedArray())).toTypedArray()
arguments.toTypedArray()
}

@JvmOverloads
suspend fun callSuspend(extensionReceiver: Any? = null)
{
val args = buildArgs(extensionReceiver)
// println("call: ${args.map { it.toString() }} | value args: $arguments")
signature.callable.callSuspend(thisRef, *args)
}

Expand Down
37 changes: 20 additions & 17 deletions src/main/kotlin/command/resolver/CommandCallResolver.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.github.asforest.mshell.command.resolver

import com.github.asforest.mshell.exception.system.NoApplicableParserException
import java.lang.reflect.Array
import kotlin.reflect.full.callSuspend
import kotlin.reflect.jvm.jvmErasure

object CommandCallResolver
Expand Down Expand Up @@ -38,36 +38,36 @@ object CommandCallResolver
return ResolveResult.TooManyArguments(signature)
}

// println("common args: ${zipped.size}, varargs: ${remainingParameters.size}")

var argIndex = 0

// 解析普通参数
for ((parameter, argument) in zipped)
{
// println(">> ${parameter.name} => $parameter ${parameter.isOptional} ${parameter.isVararg}")
// println(">> ${parameter.name} => $parameter ${parameter.isOptional} ${parameter.isVararg}, arg: $argument")

if (parameter.isVararg)
{
val parser = BuiltinArgumentParsers.parsers[parameter.genaricType]
if (parser != null)
{
if (parameter.isPrimitiveArrayType)
{
val varargs = argument.split(" ").map { parser.parse(it, argIndex, signature) }
val array = Array.newInstance(parameter.type.jvmErasure.java.componentType, varargs.size)

for (i in varargs.indices)
Array.set(array, i, varargs[i])

argumentsToCall.add(array)
} else {
for (el in argument.split(" "))
argumentsToCall += parser.parse(el, argIndex, signature)
}
val varargs = argument.split(" ").map { parser.parse(it, argIndex, signature) }
val array = Array.newInstance(parameter.type.jvmErasure.java.componentType, varargs.size)

for (i in varargs.indices)
Array.set(array, i, varargs[i])

argumentsToCall.add(array)
} else {
throw NoApplicableParserException(signature, argIndex, parameter)
}
} else {
val parser = BuiltinArgumentParsers.parsers[parameter.type.jvmErasure]
if (parser != null)
argumentsToCall += parser.parse(argument, argIndex, signature)
else
throw NoApplicableParserException(signature, argIndex, parameter)
}

argIndex += 1
Expand All @@ -81,13 +81,16 @@ object CommandCallResolver
argumentsToCall += Array.newInstance(remainingParameter.type.jvmErasure.java.componentType, 0)

// 使用null
if (remainingParameter.isOptional)
else if (remainingParameter.isOptional)
argumentsToCall += null

// 不会再有第三种情况出现
else
throw RuntimeException("unknown error")

}

// println(argumentsToCall.toString2())
// println("arg built: "+argumentsToCall.toString2())

return ResolveResult.ResolveCorrect(ArgumentedFunction(signature, argumentsToCall, thisRef))
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/command/resolver/CommandSignature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ data class CommandSignature(
}

val genaricType: KClass<*> by lazy {
check(isVararg) { "can not access 'varargGenaricType' because paramter '$name' is not a Vararg" }
check(isVararg) { "can not access 'genaricType' because paramter '$name' is not a Vararg" }

if (isPrimitiveArrayType)
type.jvmErasure.java.componentType.kotlin
else
type.arguments.first()::class
type.arguments.first().type!!.classifier as KClass<*>
}

// val actualGenaricType = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<*>
Expand Down
14 changes: 14 additions & 0 deletions src/main/kotlin/exception/system/NoApplicableParserException.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.asforest.mshell.exception.system

import com.github.asforest.mshell.command.resolver.CommandSignature
import com.github.asforest.mshell.exception.AbstractSystemException

class NoApplicableParserException(function: CommandSignature, index: Int, parameter: CommandSignature.Parameter)
: AbstractSystemException(
"No applicable parser for " +
"function '${function.name}'(${function.description}), " +
"paramter index: $index, " +
"paramter type: ${parameter.type}, " +
"genaric type(if has): ${if (parameter.isVararg) parameter.genaricType.toString() else "not a Vararg"}, " +
"is paramter primitiveArrayType: ${parameter.isPrimitiveArrayType}"
)

0 comments on commit 3d96357

Please sign in to comment.