Introduce Language Feature for annotations with wrong targets
#KT-9580 Fixed
This commit is contained in:
@@ -206,6 +206,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
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 = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
|
|||||||
+2
@@ -149,6 +149,8 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not fully supported. Add 'noinline' modifier.");
|
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not fully supported. Add 'noinline' modifier.");
|
||||||
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
||||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
|
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
|
||||||
|
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, "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(NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION, "The lambda expression here is an inlined argument so this annotation cannot be stored anywhere");
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
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.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -38,7 +40,10 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||||
import org.jetbrains.kotlin.types.isError
|
import org.jetbrains.kotlin.types.isError
|
||||||
|
|
||||||
class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) {
|
class AnnotationChecker(
|
||||||
|
private val additionalCheckers: Iterable<AdditionalAnnotationChecker>,
|
||||||
|
private val languageVersionSettings: LanguageVersionSettings
|
||||||
|
) {
|
||||||
|
|
||||||
fun check(annotated: KtAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) {
|
fun check(annotated: KtAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) {
|
||||||
val actualTargets = getActualTargetList(annotated, descriptor, trace)
|
val actualTargets = getActualTargetList(annotated, descriptor, trace)
|
||||||
@@ -144,15 +149,30 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applicableWithUseSiteTarget() = useSiteTarget != null && actualTargets.onlyWithUseSiteTarget.any {
|
fun checkWithUseSiteTargets(additionalTarget: KotlinTarget? = null, useDeprecatedTargets: Boolean = false): Boolean {
|
||||||
it in applicableTargets && KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it
|
if (useSiteTarget == null) return false
|
||||||
|
|
||||||
|
val useSiteMapping = KotlinTarget.USE_SITE_MAPPING[useSiteTarget].let {
|
||||||
|
if (useDeprecatedTargets && it == RECEIVER) KotlinTarget.VALUE_PARAMETER else it
|
||||||
|
}
|
||||||
|
|
||||||
|
val allTargets = actualTargets.onlyWithUseSiteTarget + listOfNotNull(additionalTarget)
|
||||||
|
return allTargets.any { it in applicableTargets && it == useSiteMapping }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check(actualTargets.defaultTargets) || check(actualTargets.canBeSubstituted) || applicableWithUseSiteTarget()) {
|
if (check(actualTargets.defaultTargets) || check(actualTargets.canBeSubstituted) || checkWithUseSiteTargets()) {
|
||||||
checkUselessFunctionLiteralAnnotation()
|
checkUselessFunctionLiteralAnnotation()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!languageVersionSettings.supportsFeature(LanguageFeature.RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes)) {
|
||||||
|
val isAnnotationOnType = TargetLists.T_TYPE_REFERENCE == actualTargets
|
||||||
|
if (isAnnotationOnType && checkWithUseSiteTargets(KotlinTarget.VALUE_PARAMETER, true)) {
|
||||||
|
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE.on(entry, useSiteTarget!!.renderName))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (useSiteTarget != null) {
|
if (useSiteTarget != null) {
|
||||||
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(
|
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(
|
||||||
entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName))
|
entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName))
|
||||||
|
|||||||
Vendored
+7
-10
@@ -1,15 +1,12 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
fun test1(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) {}
|
fun test1(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@setparam:Suppress<!> Int) {}
|
||||||
fun test2(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@param:Suppress<!> Int) {}
|
fun test2(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@param:Suppress<!> Int) {}
|
||||||
fun test3(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@receiver:Suppress<!> Int) {}
|
fun test3(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@receiver:Suppress<!> Int) {}
|
||||||
fun test4(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@field:Suppress<!> Int) {}
|
|
||||||
fun test5(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@set:Suppress<!> Int) {}
|
|
||||||
|
|
||||||
fun test6(): <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int = TODO()
|
fun test4(): <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@setparam:Suppress<!> Int = TODO()
|
||||||
fun test7(i: (<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) -> Unit) {}
|
fun test5(i: (<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@setparam:Suppress<!> Int) -> Unit) {}
|
||||||
|
|
||||||
fun <!INAPPLICABLE_TARGET_ON_PROPERTY, WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int.test8() {}
|
fun ((<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@setparam:Suppress<!> Int) -> Unit).test6() {}
|
||||||
fun ((<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) -> Unit).test9() {}
|
|
||||||
|
|
||||||
fun test10(): ((<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) -> Unit) = TODO()
|
fun test7(): ((<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE!>@setparam:Suppress<!> Int) -> Unit) = TODO()
|
||||||
Vendored
+4
-7
@@ -1,12 +1,9 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public fun test1(/*0*/ i: @setparam:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
public fun test1(/*0*/ i: @setparam:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
||||||
public fun test10(): (@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit
|
|
||||||
public fun test2(/*0*/ i: @param:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
public fun test2(/*0*/ i: @param:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
||||||
public fun test3(/*0*/ i: @receiver:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
public fun test3(/*0*/ i: @receiver:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
||||||
public fun test4(/*0*/ i: @field:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
public fun test4(): @setparam:kotlin.Suppress(names = {}) kotlin.Int
|
||||||
public fun test5(/*0*/ i: @set:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
public fun test5(/*0*/ i: (@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||||
public fun test6(): @setparam:kotlin.Suppress(names = {}) kotlin.Int
|
public fun test7(): (@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit
|
||||||
public fun test7(/*0*/ i: (@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
public fun ((@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit).test6(): kotlin.Unit
|
||||||
public fun @setparam:kotlin.Suppress(names = {}) kotlin.Int.test8(): kotlin.Unit
|
|
||||||
public fun ((@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit).test9(): kotlin.Unit
|
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// !LANGUAGE: +RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
fun test1(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) {}
|
||||||
|
fun test2(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@param:Suppress<!> Int) {}
|
||||||
|
fun test3(i: <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@receiver:Suppress<!> Int) {}
|
||||||
|
|
||||||
|
fun test4(): <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int = TODO()
|
||||||
|
fun test5(i: (<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) -> Unit) {}
|
||||||
|
|
||||||
|
fun ((<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) -> Unit).test6() {}
|
||||||
|
|
||||||
|
fun test7(): ((<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@setparam:Suppress<!> Int) -> Unit) = TODO()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun test1(/*0*/ i: @setparam:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
||||||
|
public fun test2(/*0*/ i: @param:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
||||||
|
public fun test3(/*0*/ i: @receiver:kotlin.Suppress(names = {}) kotlin.Int): kotlin.Unit
|
||||||
|
public fun test4(): @setparam:kotlin.Suppress(names = {}) kotlin.Int
|
||||||
|
public fun test5(/*0*/ i: (@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun test7(): (@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit
|
||||||
|
public fun ((@setparam:kotlin.Suppress(names = {}) kotlin.Int) -> kotlin.Unit).test6(): kotlin.Unit
|
||||||
@@ -1688,6 +1688,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/wrongParamAnnotationsOnTypes.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/wrongParamAnnotationsOnTypes.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("wrongParamAnnotationsOnTypesError.kt")
|
||||||
|
public void testWrongParamAnnotationsOnTypesError() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/wrongParamAnnotationsOnTypesError.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -1688,6 +1688,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/wrongParamAnnotationsOnTypes.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/wrongParamAnnotationsOnTypes.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("wrongParamAnnotationsOnTypesError.kt")
|
||||||
|
public void testWrongParamAnnotationsOnTypesError() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/wrongParamAnnotationsOnTypesError.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ enum class LanguageFeature(
|
|||||||
|
|
||||||
RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3),
|
RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3),
|
||||||
NestedClassesInEnumEntryShouldBeInner(KOTLIN_1_3),
|
NestedClassesInEnumEntryShouldBeInner(KOTLIN_1_3),
|
||||||
|
RestrictionOfWrongAnnotationsWithUseSiteTargetsOnTypes(KOTLIN_1_3),
|
||||||
|
|
||||||
// Experimental features
|
// Experimental features
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user