From bfe2ddf7c18c10843e26e6e5a117ff11036fbf4d Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 21 Mar 2017 02:49:03 +0300 Subject: [PATCH] Introduce language feature for array literals in annotations --- .../BasicExpressionTypingVisitor.java | 15 +++++++++++++++ .../collectionLiteralsInArgumentPosition.kt | 4 ++++ .../collectionLiteralsWithConstants.kt | 2 ++ .../defaultAnnotationParameterValues.kt | 1 + .../collectionLiteralsInArgumentPosition.txt | 7 ++++--- .../collectionLiteralsWithConstants.txt | 3 ++- .../defaultAnnotationParameterValues.txt | 1 + .../argumentsOfAnnotation.kt | 2 ++ .../argumentsOfAnnotationWithKClass.kt | 2 ++ .../defaultValuesInAnnotation.kt | 2 ++ .../defaultValuesWithConstantsInAnnotation.kt | 2 ++ .../noArrayLiteralsInAnnotationsFeature.kt | 18 ++++++++++++++++++ .../noArrayLiteralsInAnnotationsFeature.txt | 16 ++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ .../kotlin/config/LanguageVersionSettings.kt | 2 ++ 15 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.kt create mode 100644 compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index d105f3dac51..336eeb17f16 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -1517,6 +1517,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public KotlinTypeInfo visitCollectionLiteralExpression( @NotNull KtCollectionLiteralExpression expression, ExpressionTypingContext context ) { + checkSupportsArrayLiterals(expression, context); return resolveCollectionLiteralSpecialMethod(expression, context); } @@ -1781,6 +1782,20 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return resultTypeInfo.replaceType(functionResults.getResultingDescriptor().getReturnType()); } + private void checkSupportsArrayLiterals(KtCollectionLiteralExpression expression, ExpressionTypingContext context) { + if (isInsideAnnotationEntryOrClass(expression) && + !components.languageVersionSettings.supportsFeature(LanguageFeature.ArrayLiteralsInAnnotations)) { + context.trace.report(UNSUPPORTED_FEATURE.on( + expression, TuplesKt.to(LanguageFeature.ArrayLiteralsInAnnotations, components.languageVersionSettings))); + } + } + + private static boolean isInsideAnnotationEntryOrClass(KtCollectionLiteralExpression expression) { + //noinspection unchecked + PsiElement parent = PsiTreeUtil.getParentOfType(expression, KtAnnotationEntry.class, KtClass.class); + return parent instanceof KtAnnotationEntry || (parent instanceof KtClass && ((KtClass) parent).isAnnotation()); + } + private KotlinTypeInfo resolveCollectionLiteralSpecialMethod( @NotNull KtCollectionLiteralExpression collectionLiteralExpression, @NotNull ExpressionTypingContext context diff --git a/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsInArgumentPosition.kt b/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsInArgumentPosition.kt index 4c82af53bdb..39f4efb0d85 100644 --- a/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsInArgumentPosition.kt +++ b/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsInArgumentPosition.kt @@ -15,14 +15,18 @@ fun check(b: Boolean, message: String) { if (!b) throw RuntimeException(message) } +@Suppress("UNSUPPORTED_FEATURE") annotation class Foo(val a: FloatArray = [], val b: Array = [], val c: Array> = []) +@Suppress("UNSUPPORTED_FEATURE") @Foo(a = [1f, 2f, 1 / 0f]) fun test1() {} +@Suppress("UNSUPPORTED_FEATURE") @Foo(b = ["Hello", ", ", "Kot" + "lin"]) fun test2() {} +@Suppress("UNSUPPORTED_FEATURE") @Foo(c = [Int::class, Array::class, Foo::class]) fun test3() {} diff --git a/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsWithConstants.kt b/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsWithConstants.kt index ae30e2bfce0..344de2e3359 100644 --- a/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsWithConstants.kt +++ b/compiler/testData/codegen/box/collectionLiterals/collectionLiteralsWithConstants.kt @@ -14,6 +14,7 @@ fun check(b: Boolean, message: String) { if (!b) throw RuntimeException(message) } +@Suppress("UNSUPPORTED_FEATURE") annotation class Foo(val a: IntArray = [], val b: Array = []) const val ONE_INT = 1 @@ -21,6 +22,7 @@ const val ONE_FLOAT = 1f const val HELLO = "hello" const val C_CHAR = 'c' +@Suppress("UNSUPPORTED_FEATURE") @Foo( a = [ONE_INT, ONE_INT + ONE_FLOAT.toInt(), ONE_INT + 10, (ONE_INT % 1.0).toInt()], b = [HELLO, HELLO + C_CHAR, HELLO + ", Kotlin", C_CHAR.toString() + C_CHAR]) diff --git a/compiler/testData/codegen/box/collectionLiterals/defaultAnnotationParameterValues.kt b/compiler/testData/codegen/box/collectionLiterals/defaultAnnotationParameterValues.kt index 8befc9ddef8..73cfbb23a22 100644 --- a/compiler/testData/codegen/box/collectionLiterals/defaultAnnotationParameterValues.kt +++ b/compiler/testData/codegen/box/collectionLiterals/defaultAnnotationParameterValues.kt @@ -15,6 +15,7 @@ fun check(b: Boolean, message: String) { if (!b) throw RuntimeException(message) } +@Suppress("UNSUPPORTED_FEATURE") annotation class Foo( val a: IntArray = [], val b: IntArray = [1, 2, 3], diff --git a/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsInArgumentPosition.txt b/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsInArgumentPosition.txt index c79d613745d..1344272540a 100644 --- a/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsInArgumentPosition.txt +++ b/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsInArgumentPosition.txt @@ -3,13 +3,14 @@ public final class CollectionLiteralsInArgumentPositionKt { public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String public final static method check(p0: boolean, @org.jetbrains.annotations.NotNull p1: java.lang.String): void private final static method test(p0: kotlin.reflect.KFunction, p1: kotlin.jvm.functions.Function1): void - public final static @Foo method test1(): void - public final static @Foo method test2(): void - public final static @Foo method test3(): void + public final static @Foo @kotlin.Suppress method test1(): void + public final static @Foo @kotlin.Suppress method test2(): void + public final static @Foo @kotlin.Suppress method test3(): void } @java.lang.annotation.Retention @kotlin.Metadata +@kotlin.Suppress public annotation class Foo { public abstract method a(): float[] public abstract method b(): java.lang.String[] diff --git a/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsWithConstants.txt b/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsWithConstants.txt index a8fb845c6b3..23dda5df9a9 100644 --- a/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsWithConstants.txt +++ b/compiler/testData/codegen/light-analysis/collectionLiterals/collectionLiteralsWithConstants.txt @@ -7,11 +7,12 @@ public final class CollectionLiteralsWithConstantsKt { public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String public final static method check(p0: boolean, @org.jetbrains.annotations.NotNull p1: java.lang.String): void private final static method test(p0: kotlin.reflect.KFunction, p1: kotlin.jvm.functions.Function1): void - public final static @Foo method test1(): void + public final static @Foo @kotlin.Suppress method test1(): void } @java.lang.annotation.Retention @kotlin.Metadata +@kotlin.Suppress public annotation class Foo { public abstract method a(): int[] public abstract method b(): java.lang.String[] diff --git a/compiler/testData/codegen/light-analysis/collectionLiterals/defaultAnnotationParameterValues.txt b/compiler/testData/codegen/light-analysis/collectionLiterals/defaultAnnotationParameterValues.txt index 3a867e97a72..00b29489394 100644 --- a/compiler/testData/codegen/light-analysis/collectionLiterals/defaultAnnotationParameterValues.txt +++ b/compiler/testData/codegen/light-analysis/collectionLiterals/defaultAnnotationParameterValues.txt @@ -8,6 +8,7 @@ public final class DefaultAnnotationParameterValuesKt { @java.lang.annotation.Retention @kotlin.Metadata +@kotlin.Suppress public annotation class Foo { public abstract method a(): int[] public abstract method b(): int[] diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.kt b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.kt index 195748831bf..f9d6e64bfa7 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: +ArrayLiteralsInAnnotations + annotation class Foo(val a: IntArray, val b: Array, val c: FloatArray) @Foo([1], ["/"], [1f]) diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.kt b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.kt index 1d9c0f2b10e..2c967f2cde4 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: +ArrayLiteralsInAnnotations + import kotlin.reflect.KClass annotation class Foo(val a: Array> = []) diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.kt b/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.kt index b951527d02f..45e9190ac15 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: +ArrayLiteralsInAnnotations + annotation class Foo( val a: Array = ["/"], val b: Array = [], diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesWithConstantsInAnnotation.kt b/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesWithConstantsInAnnotation.kt index ba318edbc55..d207fc6ff7e 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesWithConstantsInAnnotation.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesWithConstantsInAnnotation.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: +ArrayLiteralsInAnnotations + const val ONE = 1 annotation class Foo( diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.kt b/compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.kt new file mode 100644 index 00000000000..390b9a1d4e9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.kt @@ -0,0 +1,18 @@ +annotation class Foo( + val a: IntArray = [], + val b: FloatArray = [1f, 2f], + val c: Array = ["/"] +) + +@Foo +fun test1() {} + +@Foo(a = [1, 2], c = ["a"]) +fun test2() {} + +@Foo([1], [3f], ["a"]) +fun test3() {} + +fun test4() { + [1, 2] +} diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.txt b/compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.txt new file mode 100644 index 00000000000..4fe23994c9a --- /dev/null +++ b/compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.txt @@ -0,0 +1,16 @@ +package + +@Foo public fun test1(): kotlin.Unit +@Foo(a = {1, 2}, c = {"a"}) public fun test2(): kotlin.Unit +@Foo(a = {1}, b = {3.0.toFloat()}, c = {"a"}) public fun test3(): kotlin.Unit +public fun test4(): kotlin.Unit + +public final annotation class Foo : kotlin.Annotation { + public constructor Foo(/*0*/ a: kotlin.IntArray = ..., /*1*/ b: kotlin.FloatArray = ..., /*2*/ c: kotlin.Array = ...) + public final val a: kotlin.IntArray + public final val b: kotlin.FloatArray + public final val c: kotlin.Array + 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 toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index bfc18d229cc..97c836ecf34 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3375,6 +3375,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesWithConstantsInAnnotation.kt"); doTest(fileName); } + + @TestMetadata("noArrayLiteralsInAnnotationsFeature.kt") + public void testNoArrayLiteralsInAnnotationsFeature() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/collectionLiterals/noArrayLiteralsInAnnotationsFeature.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/constructorConsistency") diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 5423b06fde0..8b2395eb875 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -54,6 +54,8 @@ enum class LanguageFeature( MultiPlatformProjects(sinceVersion = null, defaultState = State.DISABLED), + ArrayLiteralsInAnnotations(sinceVersion = null), + ; val presentableName: String