Introduce OptionalExpectation for annotations missing on some platforms
This commits adds a new annotation OptionalExpectation to the standard library, which is experimental. To enable its usage, either pass '-Xuse-experimental=kotlin.ExperimentalMultiplatform' as a compiler argument, or '-Xuse-experimental=kotlin.Experimental' and also annotate each usage with `@UseExperimental(ExperimentalMultiplatform::class)` #KT-18882 Fixed
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
@JvmName("bar")
|
||||
fun foo() {}
|
||||
|
||||
fun getJvmName(): JvmName? =
|
||||
Class.forName("LoadJvmNameKt").declaredMethods.single { it.name == "bar" }.getAnnotation(JvmName::class.java)
|
||||
|
||||
fun box(): String {
|
||||
// JvmName is binary-retained and should not be accessible via reflection
|
||||
return if (getJvmName() == null) "OK" else "Fail"
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalMultiplatform
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: common.kt
|
||||
|
||||
@OptionalExpectation
|
||||
expect annotation class Anno(val s: String)
|
||||
|
||||
// FILE: jvm.kt
|
||||
|
||||
import java.lang.reflect.AnnotatedElement
|
||||
|
||||
@Anno("Foo")
|
||||
class Foo @Anno("<init>") constructor(@Anno("x") x: Int) {
|
||||
@Anno("bar")
|
||||
fun bar() {}
|
||||
|
||||
@Anno("getX")
|
||||
var x = x
|
||||
@Anno("setX")
|
||||
set
|
||||
|
||||
@Anno("Nested")
|
||||
interface Nested
|
||||
}
|
||||
|
||||
private fun check(element: AnnotatedElement) {
|
||||
check(element.annotations)
|
||||
}
|
||||
|
||||
private fun check(annotations: Array<Annotation>) {
|
||||
val filtered = annotations.filterNot { it.annotationClass.java.name == "kotlin.Metadata" }
|
||||
if (filtered.isNotEmpty()) {
|
||||
throw AssertionError("Annotations should be empty: $filtered")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo = Foo::class.java
|
||||
check(foo)
|
||||
check(Foo.Nested::class.java)
|
||||
check(foo.declaredMethods.single { it.name == "bar" })
|
||||
check(foo.declaredMethods.single { it.name == "getX" })
|
||||
check(foo.declaredMethods.single { it.name == "setX" })
|
||||
check(foo.constructors.single())
|
||||
check(foo.constructors.single().parameterAnnotations.single())
|
||||
return "OK"
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalMultiplatform
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
@OptionalExpectation
|
||||
expect annotation class Anno(val s: String)
|
||||
|
||||
@Anno("Foo")
|
||||
class Foo @Anno("<init>") constructor(@Anno("x") x: Int) {
|
||||
@Anno("bar")
|
||||
fun bar() {}
|
||||
|
||||
@Anno("getX")
|
||||
var x = x
|
||||
@Anno("setX")
|
||||
set
|
||||
|
||||
@Anno("Nested")
|
||||
interface Nested
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
@kotlin.Metadata
|
||||
public interface Foo$Nested {
|
||||
inner class Foo$Nested
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Foo {
|
||||
private field x: int
|
||||
inner class Foo$Nested
|
||||
public method <init>(p0: int): void
|
||||
public final method bar(): void
|
||||
public final method getX(): int
|
||||
public final method setX(p0: int): void
|
||||
public synthetic deprecated static method x$annotations(): void
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
// ADDITIONAL_COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.ExperimentalMultiplatform
|
||||
|
||||
@OptionalExpectation
|
||||
expect annotation class A()
|
||||
|
||||
expect class C {
|
||||
@A
|
||||
fun f()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
actual class C {
|
||||
actual fun f() {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
actual annotation class A
|
||||
|
||||
actual class C {
|
||||
@A
|
||||
actual fun f() {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
-- Common --
|
||||
Exit code: OK
|
||||
Output:
|
||||
|
||||
-- JVM --
|
||||
Exit code: OK
|
||||
Output:
|
||||
|
||||
-- JS --
|
||||
Exit code: OK
|
||||
Output:
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// WITH_RUNTIME
|
||||
// ADDITIONAL_COMPILER_ARGUMENTS: -Xuse-experimental=kotlin.ExperimentalMultiplatform
|
||||
|
||||
@OptionalExpectation
|
||||
expect annotation class A()
|
||||
|
||||
fun useInSignature(a: A) = a.toString()
|
||||
|
||||
@OptionalExpectation
|
||||
expect class NotAnAnnotationClass
|
||||
|
||||
@OptionalExpectation
|
||||
annotation class NotAnExpectedClass
|
||||
|
||||
|
||||
|
||||
annotation class InOtherAnnotation(val a: A)
|
||||
|
||||
@InOtherAnnotation(A())
|
||||
fun useInOtherAnnotation() {}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun useInReturnType(): A? = null
|
||||
|
||||
annotation class AnotherAnnotation(val a: A)
|
||||
|
||||
@AnotherAnnotation(A())
|
||||
fun useInAnotherAnnotation() {}
|
||||
@@ -0,0 +1,46 @@
|
||||
-- Common --
|
||||
Exit code: COMPILATION_ERROR
|
||||
Output:
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:7:23: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
fun useInSignature(a: A) = a.toString()
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:9:1: error: this annotation is not applicable to target 'class'
|
||||
@OptionalExpectation
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:12:1: error: '@OptionalExpectation' can only be used on an expected annotation class
|
||||
@OptionalExpectation
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:17:43: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
annotation class InOtherAnnotation(val a: A)
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:19:20: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
@InOtherAnnotation(A())
|
||||
^
|
||||
|
||||
-- JVM --
|
||||
Exit code: COMPILATION_ERROR
|
||||
Output:
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:7:23: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
fun useInSignature(a: A) = a.toString()
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:9:1: error: this annotation is not applicable to target 'class'
|
||||
@OptionalExpectation
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:12:1: error: '@OptionalExpectation' can only be used on an expected annotation class
|
||||
@OptionalExpectation
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:17:43: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
annotation class InOtherAnnotation(val a: A)
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:19:20: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
@InOtherAnnotation(A())
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:1:24: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
fun useInReturnType(): A? = null
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:3:43: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
annotation class AnotherAnnotation(val a: A)
|
||||
^
|
||||
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:5:20: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
|
||||
@AnotherAnnotation(A())
|
||||
^
|
||||
Reference in New Issue
Block a user