fix NPE of ktorm

This commit is contained in:
tursom 2023-10-27 19:13:44 +08:00
parent 1613393381
commit fc31966b5c
15 changed files with 90 additions and 72 deletions

View File

@ -7,7 +7,7 @@ plugins {
id("ts-gradle-env") apply false
id("ts-gradle-install") apply false
id("ts-gradle-no-test") apply false
id("ts-gradle-test") apply false
id("ts-gradle-publish") apply false
id("ts-gradle-repos") apply false
}
@ -17,7 +17,7 @@ allprojects {
apply(plugin = "maven-publish")
apply(plugin = "ts-gradle-env")
apply(plugin = "ts-gradle-install")
apply(plugin = "ts-gradle-no-test")
apply(plugin = "ts-gradle-test")
apply(plugin = "ts-gradle-publish")
apply(plugin = "ts-gradle-repos")

View File

@ -20,3 +20,7 @@ artifacts {
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
}
tasks.withType<Test>() {
jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED")
}

View File

@ -37,22 +37,27 @@ object Proxy {
inline operator fun <T : Any> get(
clazz: Class<T>,
container: MutableProxyContainer = defaultContainer(),
useDirectAccessor: Boolean = false,
builder: (Class<T>) -> T,
): Pair<T, MutableProxyContainer> {
val target = getCachedTarget(clazz)
val directAccessor = builder(target)
val obj = builder(target)
val directAccessor = if (useDirectAccessor) builder(target) else obj
container.target = obj
container.ctx[directAccessorKey] = directAccessor
if (useDirectAccessor) container.ctx[directAccessorKey] = directAccessor
injectCallback(obj as Factory, container, directAccessor as Factory)
return obj to container
}
inline fun <reified T : Any> get() = get(T::class.java)
inline fun <reified T : Any> get(
container: MutableProxyContainer = defaultContainer(),
useDirectAccessor: Boolean = false,
) = get(T::class.java, container, useDirectAccessor)
inline operator fun <reified T : Any> get(
argumentTypes: Array<out Class<*>>,
arguments: Array<out Any?>,
@ -122,15 +127,20 @@ object Proxy {
container,
)
operator fun <T : Any> get(clazz: Class<T>, container: MutableProxyContainer = defaultContainer()) =
get(clazz, container, Class<T>::newInstance)
operator fun <T : Any> get(
clazz: Class<T>,
container: MutableProxyContainer = defaultContainer(),
useDirectAccessor: Boolean = false,
) =
get(clazz, container, useDirectAccessor, Class<T>::newInstance)
operator fun <T : Any> get(
clazz: Class<T>,
argumentTypes: Array<out Class<*>>,
arguments: Array<out Any?>,
container: MutableProxyContainer = defaultContainer(),
) = get(clazz, container) {
useDirectAccessor: Boolean = false,
) = get(clazz, container, useDirectAccessor) {
it.getConstructor(*argumentTypes).newInstance(*arguments)
}

View File

@ -68,7 +68,7 @@ class Example {
@Test
fun test() {
val (t, container) = Proxy.get<TestClass>()
val (t, container) = Proxy.get<TestClass>(useDirectAccessor = true)
val getA = GetA(t)
println(getA.t == t)

View File

@ -1,15 +0,0 @@
package cn.tursom.proxy
fun b() {
repeat(9) { i -> repeat(i) { j -> print("$j*$i=${i * j} ") };println() }
}
fun a() {
repeat(9) { i -> repeat(i) { j -> print("$j*$i=${i * j} ") };println() }
}
fun main() {
(1..9).map { i -> println((1..i).map { "$it*$i=${i * it}" }) }
}

View File

@ -14,11 +14,11 @@ class ExtSqlDialect(
override fun createSqlFormatter(database: Database, beautifySql: Boolean, indentSize: Int): SqlFormatter {
val formatter = sqlDialect.createSqlFormatter(database, beautifySql, indentSize)
val (proxyFormatter, container) = Proxy.get(formatter.javaClass) { InstantAllocator(it) }
run {
val extSqlFormatter = ExtSqlFormatter(formatter)
extSqlFormatter.registerVisitor(DirectSqlExpression.visitor)
container.addProxy(extSqlFormatter)
}
val extSqlFormatter = ExtSqlFormatter(formatter)
extSqlFormatter.registerVisitor(DirectSqlExpression.visitor)
container.addProxy(extSqlFormatter)
formatter.javaClass.allFieldsSequence.forEach { field ->
field.isAccessible = true
field.set(proxyFormatter, field.get(formatter))

View File

@ -1,13 +1,12 @@
package cn.tursom.database.ktorm.ext
import cn.tursom.proxy.function.ProxyMethod
import cn.tursom.reflect.asm.ReflectAsmKtField
import org.ktorm.expression.SqlExpression
import org.ktorm.expression.SqlFormatter
class ExtSqlFormatter(
private val prevFormatter: SqlFormatter,
) : ProxyMethod {
) {
companion object {
private val builderField = ReflectAsmKtField.get<SqlFormatter, StringBuilder>("_builder")
}

View File

@ -20,3 +20,11 @@ internal class ExtSqlDialectTest {
println(formatter.sql)
}
}
data class User(var name: String, var age: Int)
fun main() {
}

5
ts-gradle/README.md Normal file
View File

@ -0,0 +1,5 @@
## 模块介绍
本模块负责管理各种通用的 gradle 插件,并提供给本项目使用。目前已有的各种插件如下:
- ts-gradle-env: 提供各种环境支持,包括将 yaml 与 properties 文件的内容读取到 ext 中,以及提供一些

View File

@ -1,5 +1,5 @@
include("ts-gradle-env")
include("ts-gradle-no-test")
include("ts-gradle-test")
include("ts-gradle-install")
include("ts-gradle-publish")
include("ts-gradle-repos")

View File

@ -1,8 +0,0 @@
gradlePlugin {
plugins {
create("ts-gradle-no-test") {
id = "ts-gradle-no-test"
implementationClass = "cn.tursom.gradle.NoTestPlugin"
}
}
}

View File

@ -1,31 +0,0 @@
package cn.tursom.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
class NoTestPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.excludeTest()
}
}
fun Project.excludeTest() {
if (gradle.startParameter.taskNames.firstOrNull { taskName ->
taskName.contains("test", true)
} == null) {
try {
tasks.run {
named("test") { it.enabled = false }
named("testClasses") { it.enabled = false }
named("compileTestJava") { it.enabled = false }
try {
named("compileTestKotlin") { it.enabled = false }
} catch (_: Exception) {
}
named("processTestResources") { it.enabled = false }
}
} catch (e: Exception) {
println("W: exclude tests failed with ${e.javaClass.name}: ${e.message}")
}
}
}

View File

@ -0,0 +1,8 @@
gradlePlugin {
plugins {
create("ts-gradle-test") {
id = "ts-gradle-test"
implementationClass = "cn.tursom.gradle.TestPlugin"
}
}
}

View File

@ -0,0 +1,38 @@
package cn.tursom.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.testing.Test
class TestPlugin : Plugin<Project> {
override fun apply(target: Project) {
if (target.isTestTask()) {
target.tasks.withType(Test::class.java) {
it.jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED")
}
} else {
target.excludeTest()
}
}
}
fun Project.excludeTest() {
try {
tasks.run {
named("test") { it.enabled = false }
named("testClasses") { it.enabled = false }
named("compileTestJava") { it.enabled = false }
try {
named("compileTestKotlin") { it.enabled = false }
} catch (_: Exception) {
}
named("processTestResources") { it.enabled = false }
}
} catch (e: Exception) {
println("W: exclude tests failed with ${e.javaClass.name}: ${e.message}")
}
}
fun Project.isTestTask() = gradle.startParameter.taskNames.any { taskName ->
taskName.contains("test", true)
}