Prohibit synchronized methods on interface members
#KT-9310 Fixed
This commit is contained in:
-9
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmFieldAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.checkers.JvmFieldApplicabilityChecker.Problem.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
@@ -112,12 +111,4 @@ class JvmFieldApplicabilityChecker : DeclarationChecker {
|
||||
|
||||
private fun PropertyDescriptor.hasBackingField(bindingContext: BindingContext) =
|
||||
bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, this) ?: false
|
||||
|
||||
private fun PropertyDescriptor.isInsideCompanionObjectOfInterface(): Boolean {
|
||||
val containingClass = containingDeclaration as? ClassDescriptor ?: return false
|
||||
if (!DescriptorUtils.isCompanionObject(containingClass)) return false
|
||||
|
||||
val outerClassKind = (containingClass.containingDeclaration as? ClassDescriptor)?.kind
|
||||
return outerClassKind == ClassKind.INTERFACE || outerClassKind == ClassKind.ANNOTATION_CLASS
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -34,8 +34,8 @@ import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithCorres
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.findSynchronizedAnnotation
|
||||
@@ -183,11 +183,20 @@ class VolatileAnnotationChecker : DeclarationChecker {
|
||||
class SynchronizedAnnotationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val synchronizedAnnotation = descriptor.findSynchronizedAnnotation()
|
||||
if (synchronizedAnnotation != null && descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
|
||||
if (synchronizedAnnotation != null && descriptor is FunctionDescriptor) {
|
||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(synchronizedAnnotation) ?: return
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT.on(annotationEntry))
|
||||
if (isInInterface(descriptor)) {
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_IN_INTERFACE.on(annotationEntry))
|
||||
} else if (descriptor.modality == Modality.ABSTRACT) {
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT.on(annotationEntry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInInterface(descriptor: FunctionDescriptor): Boolean =
|
||||
DescriptorUtils.isInterface(descriptor.containingDeclaration) ||
|
||||
(descriptor.propertyIfAccessor.isInsideCompanionObjectOfInterface() &&
|
||||
(descriptor.hasJvmStaticAnnotation() || descriptor.propertyIfAccessor.hasJvmStaticAnnotation()))
|
||||
}
|
||||
|
||||
class OverloadsAnnotationChecker: DeclarationChecker {
|
||||
@@ -245,3 +254,11 @@ class TypeParameterBoundIsNotArrayChecker : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun CallableMemberDescriptor.isInsideCompanionObjectOfInterface(): Boolean {
|
||||
val containingClass = containingDeclaration as? ClassDescriptor ?: return false
|
||||
if (!DescriptorUtils.isCompanionObject(containingClass)) return false
|
||||
|
||||
val outerClassKind = (containingClass.containingDeclaration as? ClassDescriptor)?.kind
|
||||
return outerClassKind == ClassKind.INTERFACE || outerClassKind == ClassKind.ANNOTATION_CLASS
|
||||
}
|
||||
|
||||
+1
@@ -58,6 +58,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(VOLATILE_ON_DELEGATE, "'@Volatile' annotation cannot be used on delegated properties");
|
||||
MAP.put(SYNCHRONIZED_ON_ABSTRACT, "'@Synchronized' annotation cannot be used on abstract functions");
|
||||
MAP.put(SYNCHRONIZED_ON_INLINE, "'@Synchronized' annotation has no effect on inline functions");
|
||||
MAP.put(SYNCHRONIZED_IN_INTERFACE, "'@Synchronized' annotation cannot be used on interface members");
|
||||
MAP.put(EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT, "External declaration can not be abstract");
|
||||
MAP.put(EXTERNAL_DECLARATION_CANNOT_HAVE_BODY, "External declaration can not have a body");
|
||||
MAP.put(EXTERNAL_DECLARATION_IN_INTERFACE, "Members of interfaces can not be external");
|
||||
|
||||
@@ -49,6 +49,7 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_DELEGATE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_ON_ABSTRACT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> SYNCHRONIZED_ON_INLINE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ABSTRACT = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
Reference in New Issue
Block a user