Introduce DeclarationCheckerContext, remove SimpleDeclarationChecker

This commit is contained in:
Alexander Udalov
2018-01-03 12:55:59 +01:00
parent 4cb5483c13
commit 8cd7686535
33 changed files with 249 additions and 527 deletions
@@ -17,55 +17,50 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class ExternalFunChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class ExternalFunChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is MemberDescriptor || !descriptor.isExternal) return
val trace = context.trace
if (descriptor !is FunctionDescriptor) {
val target = when (descriptor) {
is PropertyDescriptor -> "property"
is ClassDescriptor -> "class"
else -> "non-function declaration"
}
diagnosticHolder.report(Errors.WRONG_MODIFIER_TARGET.on(declaration, KtTokens.EXTERNAL_KEYWORD, target))
trace.report(Errors.WRONG_MODIFIER_TARGET.on(declaration, KtTokens.EXTERNAL_KEYWORD, target))
return
}
if (DescriptorUtils.isInterface(descriptor.containingDeclaration)) {
diagnosticHolder.report(ErrorsJvm.EXTERNAL_DECLARATION_IN_INTERFACE.on(declaration))
trace.report(ErrorsJvm.EXTERNAL_DECLARATION_IN_INTERFACE.on(declaration))
}
else if (descriptor.modality == Modality.ABSTRACT) {
if (declaration is KtPropertyAccessor) {
diagnosticHolder.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT.on(declaration.property))
trace.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT.on(declaration.property))
}
else {
diagnosticHolder.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT.on(declaration))
trace.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT.on(declaration))
}
}
if (descriptor !is ConstructorDescriptor && declaration is KtDeclarationWithBody && declaration.hasBody()) {
diagnosticHolder.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY.on(declaration))
trace.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY.on(declaration))
}
if (InlineUtil.isInline(descriptor)) {
diagnosticHolder.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_INLINED.on(declaration))
trace.report(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_INLINED.on(declaration))
}
}
}
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -25,12 +24,13 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
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
class JvmFieldApplicabilityChecker : SimpleDeclarationChecker {
class JvmFieldApplicabilityChecker : DeclarationChecker {
internal enum class Problem(val errorMessage: String) {
NOT_FINAL("JvmField can only be applied to final property"),
@@ -44,18 +44,13 @@ class JvmFieldApplicabilityChecker : SimpleDeclarationChecker {
DELEGATE("JvmField cannot be applied to delegated property")
}
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val annotation = descriptor.findJvmFieldAnnotation() ?: return
val problem = when {
descriptor !is PropertyDescriptor -> return
declaration is KtProperty && declaration.hasDelegate() -> DELEGATE
!descriptor.hasBackingField(bindingContext) -> return
!descriptor.hasBackingField(context.trace.bindingContext) -> return
descriptor.isOverridable -> NOT_FINAL
Visibilities.isPrivate(descriptor.visibility) -> PRIVATE
descriptor.hasCustomAccessor() -> CUSTOM_ACCESSOR
@@ -69,7 +64,7 @@ class JvmFieldApplicabilityChecker : SimpleDeclarationChecker {
}
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_FIELD.on(annotationEntry, problem.errorMessage))
context.trace.report(ErrorsJvm.INAPPLICABLE_JVM_FIELD.on(annotationEntry, problem.errorMessage))
}
private fun PropertyDescriptor.hasCustomAccessor()
@@ -18,27 +18,20 @@ package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.annotations.findJvmSyntheticAnnotation
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmSyntheticApplicabilityChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class JvmSyntheticApplicabilityChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val annotation = descriptor.findJvmSyntheticAnnotation() ?: return
if (declaration is KtProperty && descriptor is VariableDescriptor && declaration.hasDelegate()) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
diagnosticHolder.report(ErrorsJvm.JVM_SYNTHETIC_ON_DELEGATE.on(annotationEntry))
context.trace.report(ErrorsJvm.JVM_SYNTHETIC_ON_DELEGATE.on(annotationEntry))
}
}
}
@@ -18,26 +18,20 @@ package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.annotations.findStrictfpAnnotation
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class StrictfpApplicabilityChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class StrictfpApplicabilityChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val annotation = descriptor.findStrictfpAnnotation() ?: return
if (declaration is KtClassOrObject && descriptor is ClassDescriptor) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
diagnosticHolder.report(ErrorsJvm.STRICTFP_ON_CLASS.on(annotationEntry))
context.trace.report(ErrorsJvm.STRICTFP_ON_CLASS.on(annotationEntry))
}
}
}
@@ -27,52 +27,39 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class LocalFunInlineChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class LocalFunInlineChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (InlineUtil.isInline(descriptor) &&
declaration is KtNamedFunction &&
descriptor is FunctionDescriptor &&
descriptor.visibility == Visibilities.LOCAL) {
diagnosticHolder.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, "Local inline functions"))
context.trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, "Local inline functions"))
}
}
}
class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVersionSettings) : SimpleDeclarationChecker {
class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVersionSettings) : DeclarationChecker {
private val isLessJVM18 = jvmTarget.bytecodeVersion < JvmTarget.JVM_1_8.bytecodeVersion
private val supportJvmStaticInInterface = languageVersionSettings.supportsFeature(LanguageFeature.JvmStaticInInterface)
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor.hasJvmStaticAnnotation()) {
if (declaration is KtNamedFunction ||
declaration is KtProperty ||
declaration is KtPropertyAccessor ||
declaration is KtParameter) {
checkDeclaration(declaration, descriptor, diagnosticHolder)
checkDeclaration(declaration, descriptor, context.trace)
}
}
}
@@ -130,24 +117,15 @@ class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVe
}
}
class JvmNameAnnotationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class JvmNameAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val platformNameAnnotation = DescriptorUtils.getJvmNameAnnotation(descriptor)
if (platformNameAnnotation != null) {
checkDeclaration(descriptor, platformNameAnnotation, diagnosticHolder)
checkDeclaration(descriptor, platformNameAnnotation, context.trace)
}
}
private fun checkDeclaration(
descriptor: DeclarationDescriptor,
annotation: AnnotationDescriptor,
diagnosticHolder: DiagnosticSink
) {
private fun checkDeclaration(descriptor: DeclarationDescriptor, annotation: AnnotationDescriptor, diagnosticHolder: DiagnosticSink) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
if (descriptor is FunctionDescriptor && !isRenamableFunction(descriptor)) {
@@ -173,55 +151,38 @@ class JvmNameAnnotationChecker : SimpleDeclarationChecker {
}
}
class VolatileAnnotationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class VolatileAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val volatileAnnotation = DescriptorUtils.getVolatileAnnotation(descriptor)
if (volatileAnnotation != null) {
if (descriptor is PropertyDescriptor && !descriptor.isVar) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
diagnosticHolder.report(ErrorsJvm.VOLATILE_ON_VALUE.on(annotationEntry))
context.trace.report(ErrorsJvm.VOLATILE_ON_VALUE.on(annotationEntry))
}
if (declaration is KtProperty && declaration.hasDelegate()) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
diagnosticHolder.report(ErrorsJvm.VOLATILE_ON_DELEGATE.on(annotationEntry))
context.trace.report(ErrorsJvm.VOLATILE_ON_DELEGATE.on(annotationEntry))
}
}
}
}
class SynchronizedAnnotationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class SynchronizedAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val synchronizedAnnotation = DescriptorUtils.getSynchronizedAnnotation(descriptor)
if (synchronizedAnnotation != null && descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(synchronizedAnnotation) ?: return
diagnosticHolder.report(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT.on(annotationEntry))
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT.on(annotationEntry))
}
}
}
class OverloadsAnnotationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class OverloadsAnnotationChecker: DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
descriptor.findJvmOverloadsAnnotation()?.let { annotation ->
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation)
if (annotationEntry != null) {
checkDeclaration(annotationEntry, descriptor, diagnosticHolder)
checkDeclaration(annotationEntry, descriptor, context.trace)
}
}
}
@@ -244,13 +205,8 @@ class OverloadsAnnotationChecker : SimpleDeclarationChecker {
}
}
class TypeParameterBoundIsNotArrayChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
class TypeParameterBoundIsNotArrayChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val typeParameters = (descriptor as? CallableDescriptor)?.typeParameters
?: (descriptor as? ClassDescriptor)?.declaredTypeParameters
?: return
@@ -258,8 +214,8 @@ class TypeParameterBoundIsNotArrayChecker : SimpleDeclarationChecker {
for (typeParameter in typeParameters) {
if (typeParameter.upperBounds.any { KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it) }) {
val element = DescriptorToSourceUtils.descriptorToDeclaration(typeParameter) ?: declaration
diagnosticHolder.report(ErrorsJvm.UPPER_BOUND_CANNOT_BE_ARRAY.on(element))
context.trace.report(ErrorsJvm.UPPER_BOUND_CANNOT_BE_ARRAY.on(element))
}
}
}
}
}