Report more detailed message if use site target is available
This commit is contained in:
@@ -115,6 +115,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<PsiElement, JetModifierKeywordToken, String> REDUNDANT_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, JetModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<JetAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<JetAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<JetAnnotationEntry> REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Annotations
|
||||
@@ -131,14 +132,10 @@ public interface Errors {
|
||||
DiagnosticFactory0<JetExpression> ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetExpression> ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_PROPERTY_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_GET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_SET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_RECEIVER_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_SPARAM_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_PARAM_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Classes and traits
|
||||
|
||||
+2
-5
@@ -122,16 +122,13 @@ public class DefaultErrorMessages {
|
||||
MAP.put(REDUNDANT_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is redundant for ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, 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(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||
|
||||
MAP.put(INAPPLICABLE_FIELD_TARGET, "''@field:'' annotations could be applied only to property declarations");
|
||||
MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}'' annotations could be applied only to property declarations", TO_STRING);
|
||||
MAP.put(INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD, "Property has neither a backing field nor a delegate");
|
||||
MAP.put(INAPPLICABLE_PROPERTY_TARGET, "''@property:'' annotations could be applied only to property declarations");
|
||||
MAP.put(INAPPLICABLE_GET_TARGET, "''@get:'' annotations could be applied only to property declarations");
|
||||
MAP.put(INAPPLICABLE_SET_TARGET, "''@set:'' annotations could be applied only to property declarations");
|
||||
MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "Property must be mutable");
|
||||
MAP.put(INAPPLICABLE_RECEIVER_TARGET, "''@receiver:'' annotations could be applied only to extension function or extension property declarations");
|
||||
MAP.put(INAPPLICABLE_SPARAM_TARGET, "''@sparam:'' annotations could be applied only to property declarations");
|
||||
MAP.put(INAPPLICABLE_PARAM_TARGET, "''@param:'' annotations could be applied only to primary constructor parameters");
|
||||
|
||||
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
||||
|
||||
@@ -84,7 +84,14 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
|
||||
it in applicableTargets && KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it
|
||||
}) return
|
||||
|
||||
trace.report(Errors.WRONG_ANNOTATION_TARGET.on(entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target"))
|
||||
if (useSiteTarget != null) {
|
||||
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(
|
||||
entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName))
|
||||
}
|
||||
else {
|
||||
trace.report(Errors.WRONG_ANNOTATION_TARGET.on(
|
||||
entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target"))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+21
-17
@@ -20,7 +20,9 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
@@ -44,10 +46,10 @@ public object AnnotationUseSiteTargetChecker {
|
||||
val target = annotationWithTarget.target ?: continue
|
||||
|
||||
when (target) {
|
||||
AnnotationUseSiteTarget.FIELD -> checkFieldTargetApplicability(annotated, descriptor, annotation)
|
||||
AnnotationUseSiteTarget.PROPERTY -> checkIfPropertyDescriptor(descriptor, annotation, INAPPLICABLE_PROPERTY_TARGET)
|
||||
AnnotationUseSiteTarget.PROPERTY_GETTER -> checkIfPropertyDescriptor(descriptor, annotation, INAPPLICABLE_GET_TARGET)
|
||||
AnnotationUseSiteTarget.PROPERTY_SETTER -> checkMutableProperty(descriptor, annotation, INAPPLICABLE_SET_TARGET)
|
||||
AnnotationUseSiteTarget.FIELD -> checkFieldTargetApplicability(annotated, descriptor, annotationWithTarget)
|
||||
AnnotationUseSiteTarget.PROPERTY -> checkIfPropertyDescriptor(descriptor, annotationWithTarget)
|
||||
AnnotationUseSiteTarget.PROPERTY_GETTER -> checkIfPropertyDescriptor(descriptor, annotationWithTarget)
|
||||
AnnotationUseSiteTarget.PROPERTY_SETTER -> checkMutableProperty(descriptor, annotationWithTarget)
|
||||
AnnotationUseSiteTarget.RECEIVER -> {
|
||||
if (descriptor !is FunctionDescriptor && descriptor !is PropertyDescriptor) {
|
||||
report(annotation, INAPPLICABLE_RECEIVER_TARGET)
|
||||
@@ -67,7 +69,7 @@ public object AnnotationUseSiteTargetChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
AnnotationUseSiteTarget.SETTER_PARAMETER -> checkMutableProperty(descriptor, annotation, INAPPLICABLE_SPARAM_TARGET)
|
||||
AnnotationUseSiteTarget.SETTER_PARAMETER -> checkMutableProperty(descriptor, annotationWithTarget)
|
||||
AnnotationUseSiteTarget.FILE -> throw IllegalArgumentException("@file annotations are not allowed here")
|
||||
}
|
||||
}
|
||||
@@ -76,36 +78,32 @@ public object AnnotationUseSiteTargetChecker {
|
||||
private fun BindingTrace.checkFieldTargetApplicability(
|
||||
modifierListOwner: JetAnnotated,
|
||||
descriptor: DeclarationDescriptor,
|
||||
annotation: AnnotationDescriptor) {
|
||||
if (checkIfPropertyDescriptor(descriptor, annotation, INAPPLICABLE_FIELD_TARGET)) return
|
||||
annotationWithTarget: AnnotationWithTarget) {
|
||||
if (checkIfPropertyDescriptor(descriptor, annotationWithTarget)) return
|
||||
|
||||
descriptor as PropertyDescriptor
|
||||
val hasDelegate = modifierListOwner is JetProperty && modifierListOwner.hasDelegate()
|
||||
|
||||
if (!hasDelegate && !(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) ?: false)) {
|
||||
report(annotation, INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD)
|
||||
report(annotationWithTarget.annotation, INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD)
|
||||
}
|
||||
}
|
||||
|
||||
private fun BindingTrace.checkMutableProperty(
|
||||
descriptor: DeclarationDescriptor,
|
||||
annotation: AnnotationDescriptor,
|
||||
diagnosticFactory: DiagnosticFactory0<PsiElement>) {
|
||||
checkIfPropertyDescriptor(descriptor, annotation, diagnosticFactory)
|
||||
private fun BindingTrace.checkMutableProperty(descriptor: DeclarationDescriptor, annotationWIthTarget: AnnotationWithTarget) {
|
||||
checkIfPropertyDescriptor(descriptor, annotationWIthTarget)
|
||||
|
||||
if (descriptor is PropertyDescriptor) {
|
||||
if (!descriptor.isVar) {
|
||||
report(annotation, INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE)
|
||||
report(annotationWIthTarget.annotation, INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun BindingTrace.checkIfPropertyDescriptor(
|
||||
descriptor: DeclarationDescriptor,
|
||||
annotation: AnnotationDescriptor,
|
||||
diagnosticFactory: DiagnosticFactory0<PsiElement>): Boolean {
|
||||
annotationWithTarget: AnnotationWithTarget): Boolean {
|
||||
if (descriptor !is PropertyDescriptor) {
|
||||
report(annotation, diagnosticFactory)
|
||||
report(annotationWithTarget, INAPPLICABLE_TARGET_ON_PROPERTY)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -116,4 +114,10 @@ public object AnnotationUseSiteTargetChecker {
|
||||
report(diagnosticFactory.on(annotationEntry))
|
||||
}
|
||||
|
||||
private fun BindingTrace.report(annotationWithTarget: AnnotationWithTarget, diagnosticFactory: DiagnosticFactory1<PsiElement, String>) {
|
||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotationWithTarget.annotation) ?: return
|
||||
report(diagnosticFactory.on(annotationEntry, annotationWithTarget.target?.renderName ?: "invalid target"))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user