[scripting] Make properties from destructing declarations available with reflection
This commit is contained in:
committed by
teamcityserver
parent
1c16f2f8c9
commit
58831eacca
+10
-1
@@ -212,6 +212,15 @@ protected constructor(
|
|||||||
}.toList()
|
}.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun collectDescriptorsFromDestructingDeclaration(
|
||||||
|
result: MutableSet<DeclarationDescriptor>,
|
||||||
|
declaration: KtDestructuringDeclaration,
|
||||||
|
nameFilter: (Name) -> Boolean,
|
||||||
|
location: LookupLocation,
|
||||||
|
) {
|
||||||
|
// MultiDeclarations are not supported on global level by default
|
||||||
|
}
|
||||||
|
|
||||||
protected fun computeDescriptorsFromDeclaredElements(
|
protected fun computeDescriptorsFromDeclaredElements(
|
||||||
kindFilter: DescriptorKindFilter,
|
kindFilter: DescriptorKindFilter,
|
||||||
nameFilter: (Name) -> Boolean,
|
nameFilter: (Name) -> Boolean,
|
||||||
@@ -258,7 +267,7 @@ protected constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KtDestructuringDeclaration -> {
|
is KtDestructuringDeclaration -> {
|
||||||
// MultiDeclarations are not supported on global level
|
collectDescriptorsFromDestructingDeclaration(result, declaration, nameFilter, location)
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException("Unsupported declaration kind: " + declaration)
|
else -> throw IllegalArgumentException("Unsupported declaration kind: " + declaration)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -2,7 +2,14 @@ package
|
|||||||
|
|
||||||
public final class DestructuringDeclarationsScript : kotlin.script.templates.standard.ScriptTemplateWithArgs {
|
public final class DestructuringDeclarationsScript : kotlin.script.templates.standard.ScriptTemplateWithArgs {
|
||||||
public constructor DestructuringDeclarationsScript(/*0*/ args: kotlin.Array<kotlin.String>)
|
public constructor DestructuringDeclarationsScript(/*0*/ args: kotlin.Array<kotlin.String>)
|
||||||
|
public final val a1: kotlin.Int
|
||||||
|
public final val a2: kotlin.String
|
||||||
public final override /*1*/ /*fake_override*/ val args: kotlin.Array<kotlin.String>
|
public final override /*1*/ /*fake_override*/ val args: kotlin.Array<kotlin.String>
|
||||||
|
public final val b1: kotlin.Int
|
||||||
|
public final val b2: kotlin.String
|
||||||
|
public final val c1: [ERROR : component1() return type]
|
||||||
|
public final val d1: kotlin.Int
|
||||||
|
public final val e1: kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
Vendored
+3
@@ -2,7 +2,10 @@ package
|
|||||||
|
|
||||||
public final class ResolveInitializerOfDestructuringDeclarationOnce : kotlin.script.templates.standard.ScriptTemplateWithArgs {
|
public final class ResolveInitializerOfDestructuringDeclarationOnce : kotlin.script.templates.standard.ScriptTemplateWithArgs {
|
||||||
public constructor ResolveInitializerOfDestructuringDeclarationOnce(/*0*/ args: kotlin.Array<kotlin.String>)
|
public constructor ResolveInitializerOfDestructuringDeclarationOnce(/*0*/ args: kotlin.Array<kotlin.String>)
|
||||||
|
public final val a: kotlin.Unit
|
||||||
public final override /*1*/ /*fake_override*/ val args: kotlin.Array<kotlin.String>
|
public final override /*1*/ /*fake_override*/ val args: kotlin.Array<kotlin.String>
|
||||||
|
public final val b: kotlin.Unit
|
||||||
|
public final val c: kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
+17
@@ -6,8 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.scripting.resolve
|
package org.jetbrains.kotlin.scripting.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
|
||||||
@@ -53,6 +56,20 @@ class LazyScriptClassMemberScope(
|
|||||||
override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
|
override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun collectDescriptorsFromDestructingDeclaration(
|
||||||
|
result: MutableSet<DeclarationDescriptor>,
|
||||||
|
declaration: KtDestructuringDeclaration,
|
||||||
|
nameFilter: (Name) -> Boolean,
|
||||||
|
location: LookupLocation
|
||||||
|
) {
|
||||||
|
for (entry in declaration.entries) {
|
||||||
|
val name = entry.nameAsSafeName
|
||||||
|
if (nameFilter(name) && name.identifierOrNullIfSpecial != "_") {
|
||||||
|
result.addAll(getContributedVariables(name, location))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val IMPLICIT_RECEIVER_PARAM_NAME_PREFIX = "\$\$implicitReceiver"
|
const val IMPLICIT_RECEIVER_PARAM_NAME_PREFIX = "\$\$implicitReceiver"
|
||||||
const val IMPORTED_SCRIPT_PARAM_NAME_PREFIX = "\$\$importedScript"
|
const val IMPORTED_SCRIPT_PARAM_NAME_PREFIX = "\$\$importedScript"
|
||||||
|
|||||||
+28
@@ -9,6 +9,9 @@ import junit.framework.TestCase
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated
|
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.full.createInstance
|
||||||
|
import kotlin.reflect.full.declaredMembers
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.toScriptSource
|
import kotlin.script.experimental.host.toScriptSource
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
@@ -46,6 +49,31 @@ class ScriptCompilerTest : TestCase() {
|
|||||||
assertEquals("Clazz", nestedClasses[0].simpleName)
|
assertEquals("Clazz", nestedClasses[0].simpleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testDestructingDeclarations() {
|
||||||
|
val res = compileToClass(
|
||||||
|
"""
|
||||||
|
val c = 3
|
||||||
|
val (a, b) = 1 to 2
|
||||||
|
val (_, d, _) = listOf('1', '2', '3')
|
||||||
|
""".trimIndent().toScriptSource()
|
||||||
|
)
|
||||||
|
|
||||||
|
val kClass = res.valueOrThrow()
|
||||||
|
val scriptInstance = kClass.createInstance()
|
||||||
|
val members = kClass.declaredMembers
|
||||||
|
val namesToMembers = members.associateBy { it.name }
|
||||||
|
|
||||||
|
fun prop(name: String) = namesToMembers[name]!! as KProperty<*>
|
||||||
|
fun propValue(name: String) = prop(name).call(scriptInstance)
|
||||||
|
fun propType(name: String) = prop(name).returnType.classifier as KClass<*>
|
||||||
|
|
||||||
|
assertEquals(1, propValue("a"))
|
||||||
|
assertEquals(Int::class, propType("b"))
|
||||||
|
assertEquals(3, propValue("c"))
|
||||||
|
assertEquals(Char::class, propType("d"))
|
||||||
|
assertNull(namesToMembers["_"])
|
||||||
|
}
|
||||||
|
|
||||||
fun compile(
|
fun compile(
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
cfgBody: ScriptCompilationConfiguration.Builder.() -> Unit
|
cfgBody: ScriptCompilationConfiguration.Builder.() -> Unit
|
||||||
|
|||||||
Reference in New Issue
Block a user