Skip to content
This repository has been archived by the owner on Jan 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #14 from k163377/update_kotlin
Browse files Browse the repository at this point in the history
Update Kotlin and Improvement of initialization process.
  • Loading branch information
k163377 authored Dec 20, 2020
2 parents cefe218 + 5465444 commit 12e6e29
Show file tree
Hide file tree
Showing 11 changed files with 644 additions and 147 deletions.
2 changes: 1 addition & 1 deletion .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

206 changes: 103 additions & 103 deletions benchmark-results.csv

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id("maven")
kotlin("jvm") version "1.4.20"
kotlin("jvm") version "1.4.21"
// プロダクションコード以外
id("org.jlleitschuh.gradle.ktlint") version "9.4.1"
id("jacoco")
Expand All @@ -22,6 +22,7 @@ dependencies {
testImplementation(group = "org.junit.jupiter", name = "junit-jupiter", version = "5.7.0") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
}
testImplementation("io.mockk:mockk:1.10.3-jdk8")

implementation(group = "org.openjdk.jmh", name = "jmh-core", version = "1.26")
}
Expand Down
49 changes: 29 additions & 20 deletions src/main/kotlin/com/mapk/fastkfunction/FastKFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.mapk.fastkfunction.argumentbucket.BucketGenerator
import com.mapk.fastkfunction.spreadwrapper.ForConstructor
import com.mapk.fastkfunction.spreadwrapper.ForKFunction
import com.mapk.fastkfunction.spreadwrapper.ForMethod
import org.jetbrains.annotations.TestOnly
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import kotlin.reflect.KFunction
Expand Down Expand Up @@ -129,47 +130,49 @@ sealed class FastKFunction<T> {
}

companion object {
private fun List<KParameter>.checkParameters() = also {
val requireInstanceParameter = this[0].kind != KParameter.Kind.VALUE

if (isEmpty() || (requireInstanceParameter && size == 1))
@TestOnly
internal fun List<KParameter>.checkParameters() = also {
if (isEmpty() || (this[0].kind != KParameter.Kind.VALUE && size == 1))
throw IllegalArgumentException("This function is not require arguments.")

if (3 <= size && requireInstanceParameter && get(1).kind != KParameter.Kind.VALUE)
if (2 <= size && this[1].kind != KParameter.Kind.VALUE)
throw IllegalArgumentException("This function is require multiple instances.")
}

private fun <T> topLevelFunctionOf(
@TestOnly
internal fun <T> topLevelFunctionOf(
function: KFunction<T>,
instance: Any?,
parameters: List<KParameter>,
method: Method
): FastKFunction<T> = when {
// KParameter.Kind.EXTENSION_RECEIVERの要求が有れば確定で拡張関数
parameters[0].kind == KParameter.Kind.EXTENSION_RECEIVER -> {
parameters[0].kind == KParameter.Kind.EXTENSION_RECEIVER ->
// 対象が拡張関数ならinstanceはreceiver、指定が無ければエラー
instance ?: throw IllegalArgumentException(
"Function requires EXTENSION_RECEIVER instance, but is not present."
)
instance.instanceOrThrow(KParameter.Kind.EXTENSION_RECEIVER).let {
checkInstanceClass(parameters[0].clazz, it::class)

val generator = BucketGenerator(parameters, instance)
val valueParameters = parameters.subList(1, parameters.size)
val generator = BucketGenerator(parameters, it)
val valueParameters = parameters.subList(1, parameters.size)

TopLevelExtensionFunction(function, method, instance, generator, valueParameters)
}
TopLevelExtensionFunction(function, method, it, generator, valueParameters)
}
// javaMethodのパラメータサイズとKFunctionのパラメータサイズが違う場合も拡張関数
// インスタンスが設定されていれば高速呼び出し、そうじゃなければ通常の関数呼び出し
method.parameters.size != parameters.size ->
instance
?.let {
checkInstanceClass(method.parameters[0].type.kotlin, it::class)

// KFunctionとしては値パラメータを求めていないため、バケツにはインスタンスを設定しない
TopLevelExtensionFunction(function, method, it, BucketGenerator(parameters, null), parameters)
} ?: Function(function, parameters)
// トップレベル関数
else -> TopLevelFunction(function, method, parameters)
}

private fun <T> instanceFunctionOf(
@TestOnly
internal fun <T> instanceFunctionOf(
function: KFunction<T>,
inputtedInstance: Any?,
parameters: List<KParameter>,
Expand All @@ -178,15 +181,21 @@ sealed class FastKFunction<T> {
val instance = inputtedInstance ?: method.declaringObject

return if (parameters[0].kind == KParameter.Kind.INSTANCE) {
instance ?: throw IllegalArgumentException("Function requires INSTANCE parameter, but is not present.")
instance.instanceOrThrow(KParameter.Kind.INSTANCE).let { nonNullInstance ->
checkInstanceClass(parameters[0].clazz, nonNullInstance::class)

val generator = BucketGenerator(parameters, instance)
val valueParameters = parameters.subList(1, parameters.size)
val generator = BucketGenerator(parameters, instance)
val valueParameters = parameters.subList(1, parameters.size)

InstanceFunction(function, method, instance, generator, valueParameters)
InstanceFunction(function, method, nonNullInstance, generator, valueParameters)
}
} else {
instance
?.let { InstanceFunction(function, method, it, BucketGenerator(parameters, null), parameters) }
?.let {
checkInstanceClass(method.declaringClass.kotlin, it::class)

InstanceFunction(function, method, it, BucketGenerator(parameters, null), parameters)
}
?: Function(function, parameters)
}
}
Expand Down
36 changes: 36 additions & 0 deletions src/main/kotlin/com/mapk/fastkfunction/InternalFunctions.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.mapk.fastkfunction

import java.lang.reflect.Method
import kotlin.reflect.KClass
import kotlin.reflect.KParameter
import kotlin.reflect.full.isSuperclassOf

/**
* Get object instance if receiver declared in object.
Expand All @@ -10,3 +13,36 @@ import java.lang.reflect.Method
* @throws UnsupportedOperationException Method declared on top level.
*/
internal val Method.declaringObject: Any? get() = declaringClass.kotlin.objectInstance

/**
* Get KParameters KClass.
*
* @receiver KParameter.
* @returns KClass.
*/
internal val KParameter.clazz: KClass<*> get() = this.type.classifier as KClass<*>

/**
* Check instance class is valid.
*
* @param expected Required clazz.
* @param actual Actual clazz.
* @throws IllegalArgumentException If actual is not required class.
*/
internal fun checkInstanceClass(expected: KClass<*>, actual: KClass<*>) {
if (!expected.isSuperclassOf(actual))
throw IllegalArgumentException(
"INSTANCE parameter required ${expected.simpleName}, but ${actual.simpleName} is present."
)
}

/**
* Throw IllegalArgumentException if instance is null.
*
* @receiver Instance parameter.
* @param kind Instance Kind.
* @return instance.
* @throws IllegalArgumentException Instance is null.
*/
internal fun <T : Any> T?.instanceOrThrow(kind: KParameter.Kind): T =
this ?: throw IllegalArgumentException("Function requires ${kind.name} parameter, but is not present.")
46 changes: 31 additions & 15 deletions src/main/kotlin/com/mapk/fastkfunction/SingleArgFastKFunction.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mapk.fastkfunction

import org.jetbrains.annotations.TestOnly
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import kotlin.reflect.KFunction
Expand Down Expand Up @@ -54,42 +55,51 @@ sealed class SingleArgFastKFunction<T> {
}

companion object {
private fun List<KParameter>.checkParameters() = also {
val requireInstanceParameter = this[0].kind != KParameter.Kind.VALUE
@TestOnly
internal fun List<KParameter>.checkParameters() = also {
val requireInstanceParameter = !isEmpty() && this[0].kind != KParameter.Kind.VALUE

if (isEmpty() || (requireInstanceParameter && size == 1))
throw IllegalArgumentException("This function is not require arguments.")

if (!(this.size == 1 || (this.size == 2 && requireInstanceParameter)))
throw IllegalArgumentException("This function is require multiple arguments.")

if (this.size == 2 && this[1].kind != KParameter.Kind.VALUE)
throw IllegalArgumentException("This function is require multiple instances.")
}

private fun <T> topLevelFunctionOf(
@TestOnly
internal fun <T> topLevelFunctionOf(
function: KFunction<T>,
instance: Any?,
parameters: List<KParameter>,
method: Method
): SingleArgFastKFunction<T> = when {
// KParameter.Kind.EXTENSION_RECEIVERの要求が有れば確定で拡張関数
parameters[0].kind == KParameter.Kind.EXTENSION_RECEIVER -> {
parameters[0].kind == KParameter.Kind.EXTENSION_RECEIVER ->
// 対象が拡張関数ならinstanceはreceiver、指定が無ければエラー
instance ?: throw IllegalArgumentException(
"Function requires EXTENSION_RECEIVER instance, but is not present."
)
instance.instanceOrThrow(KParameter.Kind.EXTENSION_RECEIVER).let {
checkInstanceClass(parameters[0].clazz, it::class)

TopLevelExtensionFunction(parameters[1], method, instance)
}
TopLevelExtensionFunction(parameters[1], method, it)
}
// javaMethodのパラメータサイズとKFunctionのパラメータサイズが違う場合も拡張関数
// インスタンスが設定されていれば高速呼び出し、そうじゃなければ通常の関数呼び出し
method.parameters.size != parameters.size ->
instance
?.let { TopLevelExtensionFunction(parameters[0], method, instance) }
?.let {
checkInstanceClass(method.parameters[0].type.kotlin, it::class)

TopLevelExtensionFunction(parameters[0], method, instance)
}
?: Function(parameters[0], function)
// トップレベル関数
else -> TopLevelFunction(parameters[0], method)
}

private fun <T> instanceFunctionOf(
@TestOnly
internal fun <T> instanceFunctionOf(
function: KFunction<T>,
inputtedInstance: Any?,
parameters: List<KParameter>,
Expand All @@ -99,10 +109,16 @@ sealed class SingleArgFastKFunction<T> {

return when {
parameters[0].kind == KParameter.Kind.INSTANCE ->
instance
?.let { InstanceFunction(parameters[1], method, it) }
?: throw IllegalArgumentException("Function requires INSTANCE parameter, but is not present.")
instance != null -> InstanceFunction(parameters[0], method, instance)
instance.instanceOrThrow(KParameter.Kind.INSTANCE).let {
checkInstanceClass(method.declaringClass.kotlin, it::class)

InstanceFunction(parameters[1], method, it)
}
instance != null -> {
checkInstanceClass(method.declaringClass.kotlin, instance::class)

InstanceFunction(parameters[0], method, instance)
}
else -> Function(parameters[0], function)
}
}
Expand Down
Loading

0 comments on commit 12e6e29

Please sign in to comment.