Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c523a01
Kotlinのアップデート
k163377 Dec 12, 2020
e75b44a
1.4.21へのアップデートに伴うベンチマーク更新
k163377 Dec 20, 2020
6a71d53
テスト内容に合わせて修正
k163377 Dec 20, 2020
9a46f01
呼び出し系テストをパッケージ移動
k163377 Dec 20, 2020
90516fc
mockk追加
k163377 Dec 20, 2020
c4710e8
テストのためinternal化
k163377 Dec 20, 2020
17f71fe
依存のバージョン修正
k163377 Dec 20, 2020
6fd8b03
パラメータが空リストだった時に落ちる問題を修正
k163377 Dec 20, 2020
e4725f2
Value以外のパラメータが2つ以上要求される場合のチェックを修正
k163377 Dec 20, 2020
8c3f8a7
簡略化
k163377 Dec 20, 2020
84bf6af
CheckParametersのテストまで追加
k163377 Dec 20, 2020
35662ac
パラメータの移植 + レシーバーパラメータのmockを追加
k163377 Dec 20, 2020
99b2f69
テストのためinternal化
k163377 Dec 20, 2020
5aacd45
topLevelFunctionOfのテスト追加
k163377 Dec 20, 2020
d5ebaf7
テストのためinternal化
k163377 Dec 20, 2020
e6171e7
instanceのクラスがパラメータにできないものであればその場で落とすように修正
k163377 Dec 20, 2020
49951b4
instanceのクラスがパラメータにできないものであればその場で落とすように修正
k163377 Dec 20, 2020
22deffe
instanceFunctionOfのテストを追加
k163377 Dec 20, 2020
f42062b
スコープに合わせて修正
k163377 Dec 20, 2020
1a04899
*でまとめないよう修正
k163377 Dec 20, 2020
4450eba
フォーマッティング
k163377 Dec 20, 2020
f696b6f
テストのためinternal化
k163377 Dec 20, 2020
72c8a6a
パラメータが空だった場合に落ちる問題の修正
k163377 Dec 20, 2020
f618c1b
Valueパラメータ以外が2つで渡された場合に落ちるようにバリデーションを修正
k163377 Dec 20, 2020
5ed297f
checkParametersのテストを追加
k163377 Dec 20, 2020
f62d258
テストのためinternal化
k163377 Dec 20, 2020
59e5366
フォーマット修正
k163377 Dec 20, 2020
b9403a9
topLevelFunctionOfのテストを追加
k163377 Dec 20, 2020
6e81a1f
テストのためinternal化
k163377 Dec 20, 2020
3521398
インスタンスの型バリデーションを追加
k163377 Dec 20, 2020
d9e46eb
instanceFunctionOfのテスト追加
k163377 Dec 20, 2020
8d4eeef
エラーメッセージの間違いを修正
k163377 Dec 20, 2020
f129f62
instanceパラメータバリデーション時の「Nullならthrow」の共通化用関数を定義
k163377 Dec 20, 2020
90519b2
instanceOrThrowで共通化
k163377 Dec 20, 2020
6fe1779
KParameterからKClassを取り出す共通関数を追加
k163377 Dec 20, 2020
cf7f5bb
インスタンスパラメータのバリデーション用共通関数を追加
k163377 Dec 20, 2020
87aa5a4
共通化
k163377 Dec 20, 2020
3378ae6
フォーマッティング
k163377 Dec 20, 2020
1701959
receiverの型チェックを追加
k163377 Dec 20, 2020
f6da2e7
無駄なネストを修正
k163377 Dec 20, 2020
2c597f0
変なreceiverを渡した時のテストを追加
k163377 Dec 20, 2020
7980f05
receiverの型チェックを追加
k163377 Dec 20, 2020
5465444
変なreceiverを渡した時のテストを追加
k163377 Dec 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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