Forbid @Synchronized annotation on suspend functions
and lambdas. With warning for now. #KT-27333
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.psi.KtAnnotated
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.unwrapParenthesesLabelsAndAnnotations
|
||||
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
object SynchronizedAnnotationOnLambdaChecker : AdditionalAnnotationChecker {
|
||||
override fun checkEntries(
|
||||
entries: List<KtAnnotationEntry>,
|
||||
actualTargets: List<KotlinTarget>,
|
||||
trace: BindingTrace,
|
||||
annotated: KtAnnotated?,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
if (entries.isEmpty()) return
|
||||
|
||||
val annotation = entries.find { trace.get(BindingContext.ANNOTATION, it)?.fqName == SYNCHRONIZED_ANNOTATION_FQ_NAME } ?: return
|
||||
|
||||
val literal = (annotated?.unwrapParenthesesLabelsAndAnnotations() as? KtLambdaExpression)?.functionLiteral ?: return
|
||||
val descriptor = trace.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, literal]
|
||||
if (descriptor is FunctionDescriptor && descriptor.isSuspend) {
|
||||
trace.report(ErrorsJvm.SYNCHRONIZED_ON_SUSPEND.on(annotation))
|
||||
}
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.findSynchronizedAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
object SynchronizedOnInlineMethodChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor is FunctionDescriptor && descriptor.isInline) {
|
||||
val annotation = descriptor.findSynchronizedAnnotation()
|
||||
if (annotation != null) {
|
||||
val reportOn = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: declaration
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_INLINE.on(reportOn))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -195,6 +195,10 @@ class SynchronizedAnnotationChecker : DeclarationChecker {
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_IN_INTERFACE.on(annotationEntry))
|
||||
} else if (descriptor.modality == Modality.ABSTRACT) {
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT.on(annotationEntry))
|
||||
} else if (descriptor.isInline) {
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_INLINE.on(annotationEntry))
|
||||
} else if (descriptor.isSuspend) {
|
||||
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_SUSPEND.on(annotationEntry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -217,6 +217,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION, "Value classes without @JvmInline annotation are not supported yet");
|
||||
MAP.put(JVM_INLINE_WITHOUT_VALUE_CLASS, "@JvmInline annotation is only applicable to value classes");
|
||||
|
||||
MAP.put(SYNCHRONIZED_ON_SUSPEND, "@Synchronized annotation is not applicable to suspend functions and lambdas");
|
||||
|
||||
MAP.put(TYPEOF_SUSPEND_TYPE, "Suspend functional types are not supported in typeOf");
|
||||
MAP.put(TYPEOF_EXTENSION_FUNCTION_TYPE, "Extension function types are not supported in typeOf");
|
||||
MAP.put(TYPEOF_ANNOTATED_TYPE, "Annotated types are not supported in typeOf");
|
||||
|
||||
@@ -52,6 +52,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<PsiElement> SYNCHRONIZED_ON_SUSPEND = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
+3
-3
@@ -39,7 +39,6 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
SuspendInFunInterfaceChecker(),
|
||||
BadInheritedJavaSignaturesChecker,
|
||||
JvmMultifileClassStateChecker,
|
||||
SynchronizedOnInlineMethodChecker,
|
||||
DefaultCheckerInTailrec,
|
||||
FunctionDelegateMemberNameClashChecker,
|
||||
ClassInheritsJavaSealedClassChecker
|
||||
@@ -57,7 +56,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
RuntimeAssertionsOnExtensionReceiverCallChecker,
|
||||
ApiVersionIsAtLeastArgumentsChecker,
|
||||
InconsistentOperatorFromJavaCallChecker,
|
||||
PolymorphicSignatureCallChecker
|
||||
PolymorphicSignatureCallChecker,
|
||||
),
|
||||
|
||||
additionalTypeCheckers = listOf(
|
||||
@@ -74,7 +73,8 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
|
||||
additionalAnnotationCheckers = listOf(
|
||||
FileClassAnnotationsChecker,
|
||||
ExplicitMetadataChecker
|
||||
ExplicitMetadataChecker,
|
||||
SynchronizedAnnotationOnLambdaChecker,
|
||||
),
|
||||
|
||||
additionalClashResolvers = listOf(
|
||||
|
||||
Reference in New Issue
Block a user