Fix annotation construction with array literals
Turns out the issue happens to be that ArrayValue uses a list of values which needs to be translated to an array of the percise type before it is used by callBy This also addresses handling of arguments after a vararg in an annotation
This commit is contained in:
committed by
Ilya Chernikov
parent
8cb4f59114
commit
f0bc52222d
plugins/scripting/scripting-compiler/testData/compiler/constructAnnotations/SimpleTestAnnotation.kts
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
@file:TestAnnotation("option")
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
@file:TestAnnotation()
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
@file:TestAnnotation(options = ["option"])
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
@file:TestAnnotation(options = arrayOf("option"))
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
@file:TestAnnotation(options = emptyArray())
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
|
||||
@file:AnnotationWithVarArgAndArray("option", moreOptions = ["otherOption"])
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.scripting.compiler.test
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.script.loadScriptingPlugin
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.TestDisposable
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptDiagnosticsMessageCollector
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.createCompilationContextFromEnvironment
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.getScriptKtFile
|
||||
import org.jetbrains.kotlin.scripting.resolve.InvalidScriptResolverAnnotation
|
||||
import org.jetbrains.kotlin.scripting.resolve.getScriptCollectedData
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
import java.io.File
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.toScriptSource
|
||||
import kotlin.script.experimental.jvm.jvm
|
||||
|
||||
private const val testDataPath = "plugins/scripting/scripting-compiler/testData/compiler/constructAnnotations"
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
@Repeatable
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
private annotation class TestAnnotation(vararg val options: String)
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
@Repeatable
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
private annotation class AnnotationWithVarArgAndArray(vararg val options: String, val moreOptions: Array<String>)
|
||||
|
||||
class ConstructAnnotationTest : TestCase() {
|
||||
private val testRootDisposable: Disposable = TestDisposable()
|
||||
|
||||
fun testAnnotationEmptyVarArg() {
|
||||
val annotations = annotations("TestAnnotationEmptyVarArg.kts", TestAnnotation::class)
|
||||
.valueOrThrow()
|
||||
.filterIsInstance(TestAnnotation::class.java)
|
||||
|
||||
assertEquals(annotations.count(), 1)
|
||||
assert(annotations.first().options.isEmpty())
|
||||
}
|
||||
|
||||
fun testBasicVarArgTestAnnotation() {
|
||||
val annotations = annotations("SimpleTestAnnotation.kts", TestAnnotation::class)
|
||||
.valueOrThrow()
|
||||
.filterIsInstance(TestAnnotation::class.java)
|
||||
|
||||
assertEquals(annotations.count(), 1)
|
||||
assertEquals(annotations.first().options.toList(), listOf("option"))
|
||||
}
|
||||
|
||||
fun testAnnotationWithArrayLiteral() {
|
||||
val annotations = annotations("TestAnnotationWithArrayLiteral.kts", TestAnnotation::class)
|
||||
.valueOrThrow()
|
||||
.filterIsInstance(TestAnnotation::class.java)
|
||||
|
||||
assertEquals(annotations.count(), 1)
|
||||
assertEquals(annotations.first().options.toList(), listOf("option"))
|
||||
}
|
||||
|
||||
fun testAnnotationWithArrayOfFunction() {
|
||||
val annotations = annotations("TestAnnotationWithArrayOfFunction.kts", TestAnnotation::class)
|
||||
.valueOrThrow()
|
||||
.filterIsInstance(TestAnnotation::class.java)
|
||||
|
||||
assertEquals(annotations.count(), 1)
|
||||
assertEquals(annotations.first().options.toList(), listOf("option"))
|
||||
}
|
||||
|
||||
fun testAnnotationWithEmptyArrayFunction() {
|
||||
val annotations = annotations("TestAnnotationWithEmptyArrayFunction.kts", TestAnnotation::class)
|
||||
.valueOrThrow()
|
||||
.filterIsInstance(TestAnnotation::class.java)
|
||||
|
||||
assertEquals(annotations.count(), 1)
|
||||
assert(annotations.first().options.isEmpty())
|
||||
}
|
||||
|
||||
fun testArrayAfterVarArgInAnnotation() {
|
||||
val annotations = annotations("TestAnnotationWithVarArgAndArray.kts", AnnotationWithVarArgAndArray::class)
|
||||
.valueOrThrow()
|
||||
.filterIsInstance(AnnotationWithVarArgAndArray::class.java)
|
||||
|
||||
assertEquals(annotations.count(), 1)
|
||||
assertEquals(annotations.first().options.toList(), listOf("option"))
|
||||
assertEquals(annotations.first().moreOptions.toList(), listOf("otherOption"))
|
||||
}
|
||||
|
||||
private fun annotations(filename: String, vararg classes: KClass<out Annotation>): ResultWithDiagnostics<List<Annotation>> {
|
||||
val file = File(testDataPath, filename)
|
||||
val compilationConfiguration = KotlinTestUtils.newConfiguration(ConfigurationKind.NO_KOTLIN_REFLECT, TestJdkKind.MOCK_JDK).apply {
|
||||
addKotlinSourceRoot(file.path)
|
||||
loadScriptingPlugin(this)
|
||||
}
|
||||
val configuration = ScriptCompilationConfiguration {
|
||||
defaultImports(*classes)
|
||||
jvm {
|
||||
refineConfiguration {
|
||||
onAnnotations(*classes) {
|
||||
it.compilationConfiguration.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val messageCollector = ScriptDiagnosticsMessageCollector(null)
|
||||
val environment = KotlinCoreEnvironment.createForTests(
|
||||
testRootDisposable, compilationConfiguration, EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||
)
|
||||
val context = createCompilationContextFromEnvironment(configuration, environment, messageCollector)
|
||||
val source = file.toScriptSource()
|
||||
val ktFile = getScriptKtFile(
|
||||
source,
|
||||
configuration,
|
||||
context.environment.project,
|
||||
messageCollector
|
||||
).valueOr { return it }
|
||||
|
||||
if (messageCollector.hasErrors()) {
|
||||
return makeFailureResult(messageCollector.diagnostics)
|
||||
}
|
||||
|
||||
val data = getScriptCollectedData(ktFile, configuration, environment.project, null)
|
||||
val annotations = data[ScriptCollectedData.foundAnnotations] ?: emptyList()
|
||||
|
||||
annotations
|
||||
.filterIsInstance(InvalidScriptResolverAnnotation::class.java)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.let { invalid ->
|
||||
val reports = invalid.map { "Failed to resolve annotation of type ${it.name} due to ${it.error}".asErrorDiagnostics() }
|
||||
return makeFailureResult(reports)
|
||||
}
|
||||
|
||||
return annotations.asSuccess()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user