KT-14196 Do not allow class literal with expression in annotation arguments
This commit is contained in:
+12
-1
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.resolve.constants.evaluate
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.text.LiteralFormatUtil
|
||||
import org.jetbrains.kotlin.KtNodeType
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -37,6 +36,7 @@ import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
@@ -131,6 +131,17 @@ class ConstantExpressionEvaluator(
|
||||
if (constant.usesNonConstValAsConstant) {
|
||||
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
|
||||
}
|
||||
|
||||
if (argumentExpression is KtClassLiteralExpression) {
|
||||
val lhsExpression = argumentExpression.receiverExpression
|
||||
if (lhsExpression != null) {
|
||||
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
|
||||
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObject) {
|
||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
annotation class Ann(val k: KClass<*>)
|
||||
annotation class AnnArray(val kk: Array<KClass<*>>)
|
||||
|
||||
object AnObject
|
||||
|
||||
class C {
|
||||
companion object
|
||||
}
|
||||
|
||||
fun foo() = "foo"
|
||||
|
||||
@Ann(<!ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL!>"foo"::class<!>)
|
||||
fun test1() {}
|
||||
|
||||
@Ann(String::class)
|
||||
fun test2() {}
|
||||
|
||||
@Ann(AnObject::class)
|
||||
fun test4() {}
|
||||
|
||||
@Ann(C::class)
|
||||
fun test5() {}
|
||||
|
||||
@Ann(C.Companion::class)
|
||||
fun test6() {}
|
||||
|
||||
@Ann(<!ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL!>foo()::class<!>)
|
||||
fun test7() {}
|
||||
|
||||
@AnnArray(arrayOf(<!ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL!>""::class<!>, String::class, AnObject::class))
|
||||
fun test8() {}
|
||||
@@ -0,0 +1,47 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.String
|
||||
@Ann(k = kotlin.String::class) public fun test1(): kotlin.Unit
|
||||
@Ann(k = kotlin.String::class) public fun test2(): kotlin.Unit
|
||||
@Ann(k = AnObject::class) public fun test4(): kotlin.Unit
|
||||
@Ann(k = C::class) public fun test5(): kotlin.Unit
|
||||
@Ann(k = C.Companion::class) public fun test6(): kotlin.Unit
|
||||
@Ann(k = kotlin.String::class) public fun test7(): kotlin.Unit
|
||||
@AnnArray(kk = {kotlin.String::class, kotlin.String::class, AnObject::class}) public fun test8(): kotlin.Unit
|
||||
|
||||
public object AnObject {
|
||||
private constructor AnObject()
|
||||
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
|
||||
}
|
||||
|
||||
public final annotation class Ann : kotlin.Annotation {
|
||||
public constructor Ann(/*0*/ k: kotlin.reflect.KClass<*>)
|
||||
public final val k: kotlin.reflect.KClass<*>
|
||||
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
|
||||
}
|
||||
|
||||
public final annotation class AnnArray : kotlin.Annotation {
|
||||
public constructor AnnArray(/*0*/ kk: kotlin.Array<kotlin.reflect.KClass<*>>)
|
||||
public final val kk: kotlin.Array<kotlin.reflect.KClass<*>>
|
||||
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
|
||||
}
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
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
|
||||
|
||||
public companion object Companion {
|
||||
private constructor Companion()
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -2992,6 +2992,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inAnnotationArguments.kt")
|
||||
public void testInAnnotationArguments() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("integerValueType.kt")
|
||||
public void testIntegerValueType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/integerValueType.kt");
|
||||
|
||||
Reference in New Issue
Block a user