Fix checking repeatablilty of use-site target annotations. KT-26638 fixed
This commit is contained in:
@@ -213,6 +213,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION_WARNING = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Annotations
|
||||
|
||||
+1
@@ -128,6 +128,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE,
|
||||
"Use of this annotation with target ''type'' and use site target ''@{0}'' is deprecated", TO_STRING);
|
||||
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||
MAP.put(REPEATED_ANNOTATION_WARNING, "This annotation is not repeatable");
|
||||
MAP.put(NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION, "The lambda expression here is an inlined argument so this annotation cannot be stored anywhere");
|
||||
|
||||
MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
||||
@@ -36,6 +38,9 @@ class AnnotationChecker(
|
||||
fun check(annotated: KtAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) {
|
||||
val actualTargets = getActualTargetList(annotated, descriptor, trace.bindingContext)
|
||||
checkEntries(annotated.annotationEntries, actualTargets, trace, annotated)
|
||||
if (annotated is KtProperty) {
|
||||
checkPropertyUseSiteTargetAnnotations(annotated, trace)
|
||||
}
|
||||
if (annotated is KtCallableDeclaration) {
|
||||
annotated.typeReference?.let { check(it, trace) }
|
||||
annotated.receiverTypeReference?.let { check(it, trace) }
|
||||
@@ -72,6 +77,33 @@ class AnnotationChecker(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPropertyUseSiteTargetAnnotations(property: KtProperty, trace: BindingTrace) {
|
||||
fun List<KtAnnotationEntry>?.getDescriptors() = this?.mapNotNull { trace.get(BindingContext.ANNOTATION, it)?.annotationClass } ?: listOf()
|
||||
|
||||
val reportError = languageVersionSettings.supportsFeature(LanguageFeature.ProhibitRepeatedUseSiteTargetAnnotations)
|
||||
|
||||
val propertyAnnotations = mapOf(
|
||||
AnnotationUseSiteTarget.PROPERTY_GETTER to property.getter?.annotationEntries.getDescriptors(),
|
||||
AnnotationUseSiteTarget.PROPERTY_SETTER to property.setter?.annotationEntries.getDescriptors(),
|
||||
AnnotationUseSiteTarget.SETTER_PARAMETER to property.setter?.parameter?.annotationEntries.getDescriptors()
|
||||
)
|
||||
|
||||
for (entry in property.annotationEntries) {
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
val classDescriptor = descriptor.annotationClass ?: continue
|
||||
|
||||
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget() ?: property.getDefaultUseSiteTarget(descriptor)
|
||||
val existingAnnotations = propertyAnnotations.get(useSiteTarget) ?: continue
|
||||
if (classDescriptor in existingAnnotations && !classDescriptor.isRepeatableAnnotation()) {
|
||||
if (reportError) {
|
||||
trace.reportDiagnosticOnce(Errors.REPEATED_ANNOTATION.on(entry))
|
||||
} else {
|
||||
trace.report(Errors.REPEATED_ANNOTATION_WARNING.on(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtAnnotated?.getImplicitUseSiteTargetList(): List<AnnotationUseSiteTarget> = when (this) {
|
||||
is KtParameter ->
|
||||
if (ownerFunction is KtPrimaryConstructor) UseSiteTargetsList.T_CONSTRUCTOR_PARAMETER else emptyList()
|
||||
|
||||
+6
-5
@@ -1,21 +1,22 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !LANGUAGE: -ProhibitRepeatedUseSiteTargetAnnotations
|
||||
|
||||
// Ann is not repeatable
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
@get:Ann(10)
|
||||
<!REPEATED_ANNOTATION_WARNING!>@get:Ann(10)<!>
|
||||
val a: String
|
||||
@Ann(20) get() = "foo"
|
||||
|
||||
@set:Ann(10)
|
||||
<!REPEATED_ANNOTATION_WARNING!>@set:Ann(10)<!>
|
||||
var b: String = ""
|
||||
@Ann(20) set(value) { field = value }
|
||||
|
||||
@setparam:Ann(10)
|
||||
<!REPEATED_ANNOTATION_WARNING!>@setparam:Ann(10)<!>
|
||||
var c = " "
|
||||
set(@Ann(20) x) {}
|
||||
|
||||
@get:Ann(10)
|
||||
<!REPEATED_ANNOTATION!>@get:Ann(20)<!>
|
||||
<!REPEATED_ANNOTATION_WARNING!>@get:Ann(10)<!>
|
||||
<!REPEATED_ANNOTATION, REPEATED_ANNOTATION_WARNING!>@get:Ann(20)<!>
|
||||
val d: String
|
||||
@Ann(30) <!REPEATED_ANNOTATION!>@Ann(40)<!> get() = "foo"
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
package
|
||||
|
||||
@setparam:Ann(x = 20) @setparam:Ann(x = 10) public var a: kotlin.String
|
||||
@get:Ann(x = 10) @get:Ann(x = 20) public val a: kotlin.String
|
||||
@set:Ann(x = 10) @set:Ann(x = 20) public var b: kotlin.String
|
||||
@setparam:Ann(x = 20) @setparam:Ann(x = 10) public var c: kotlin.String
|
||||
@get:Ann(x = 10) @get:Ann(x = 20) @get:Ann(x = 30) @get:Ann(x = 40) public val d: kotlin.String
|
||||
|
||||
public final annotation class Ann : kotlin.Annotation {
|
||||
public constructor Ann(/*0*/ x: kotlin.Int)
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !LANGUAGE: +ProhibitRepeatedUseSiteTargetAnnotations
|
||||
|
||||
// Ann is not repeatable
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
<!REPEATED_ANNOTATION!>@get:Ann(10)<!>
|
||||
val a: String
|
||||
@Ann(20) get() = "foo"
|
||||
|
||||
<!REPEATED_ANNOTATION!>@set:Ann(10)<!>
|
||||
var b: String = ""
|
||||
@Ann(20) set(value) { field = value }
|
||||
|
||||
<!REPEATED_ANNOTATION!>@setparam:Ann(10)<!>
|
||||
var c = " "
|
||||
set(@Ann(20) x) {}
|
||||
|
||||
<!REPEATED_ANNOTATION!>@get:Ann(10)<!>
|
||||
<!REPEATED_ANNOTATION!>@get:Ann(20)<!>
|
||||
val d: String
|
||||
@Ann(30) <!REPEATED_ANNOTATION!>@Ann(40)<!> get() = "foo"
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
@get:Ann(x = 10) @get:Ann(x = 20) public val a: kotlin.String
|
||||
@set:Ann(x = 10) @set:Ann(x = 20) public var b: kotlin.String
|
||||
@setparam:Ann(x = 20) @setparam:Ann(x = 10) public var c: kotlin.String
|
||||
@get:Ann(x = 10) @get:Ann(x = 20) @get:Ann(x = 30) @get:Ann(x = 40) public val d: kotlin.String
|
||||
|
||||
public final annotation class Ann : kotlin.Annotation {
|
||||
public constructor Ann(/*0*/ x: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
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
|
||||
}
|
||||
@@ -1449,6 +1449,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/kt26638.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt26638_after.kt")
|
||||
public void testKt26638_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/kt26638_after.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ParamAnnotations.kt")
|
||||
public void testParamAnnotations() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/ParamAnnotations.kt");
|
||||
|
||||
Generated
+5
@@ -1444,6 +1444,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/kt26638.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt26638_after.kt")
|
||||
public void testKt26638_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/kt26638_after.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ParamAnnotations.kt")
|
||||
public void testParamAnnotations() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/ParamAnnotations.kt");
|
||||
|
||||
@@ -98,6 +98,7 @@ enum class LanguageFeature(
|
||||
ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProhibitTypeParametersInAnonymousObjects(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProperInlineFromHigherPlatformDiagnostic(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProhibitRepeatedUseSiteTargetAnnotations(KOTLIN_1_4, kind = BUG_FIX),
|
||||
|
||||
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
|
||||
Reference in New Issue
Block a user