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 package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDeclarationWithBody import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtPropertyAccessor import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils 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.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class ExternalFunChecker : SimpleDeclarationChecker { class ExternalFunChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor !is MemberDescriptor || !descriptor.isExternal) return if (descriptor !is MemberDescriptor || !descriptor.isExternal) return
val trace = context.trace
if (descriptor !is FunctionDescriptor) { if (descriptor !is FunctionDescriptor) {
val target = when (descriptor) { val target = when (descriptor) {
is PropertyDescriptor -> "property" is PropertyDescriptor -> "property"
is ClassDescriptor -> "class" is ClassDescriptor -> "class"
else -> "non-function declaration" 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 return
} }
if (DescriptorUtils.isInterface(descriptor.containingDeclaration)) { 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) { else if (descriptor.modality == Modality.ABSTRACT) {
if (declaration is KtPropertyAccessor) { 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 { 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()) { 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)) { 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 package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile
import org.jetbrains.kotlin.psi.KtDeclaration 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.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils 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.annotations.findJvmFieldAnnotation
import org.jetbrains.kotlin.resolve.jvm.checkers.JvmFieldApplicabilityChecker.Problem.* import org.jetbrains.kotlin.resolve.jvm.checkers.JvmFieldApplicabilityChecker.Problem.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmFieldApplicabilityChecker : SimpleDeclarationChecker { class JvmFieldApplicabilityChecker : DeclarationChecker {
internal enum class Problem(val errorMessage: String) { internal enum class Problem(val errorMessage: String) {
NOT_FINAL("JvmField can only be applied to final property"), 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") DELEGATE("JvmField cannot be applied to delegated property")
} }
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val annotation = descriptor.findJvmFieldAnnotation() ?: return val annotation = descriptor.findJvmFieldAnnotation() ?: return
val problem = when { val problem = when {
descriptor !is PropertyDescriptor -> return descriptor !is PropertyDescriptor -> return
declaration is KtProperty && declaration.hasDelegate() -> DELEGATE declaration is KtProperty && declaration.hasDelegate() -> DELEGATE
!descriptor.hasBackingField(bindingContext) -> return !descriptor.hasBackingField(context.trace.bindingContext) -> return
descriptor.isOverridable -> NOT_FINAL descriptor.isOverridable -> NOT_FINAL
Visibilities.isPrivate(descriptor.visibility) -> PRIVATE Visibilities.isPrivate(descriptor.visibility) -> PRIVATE
descriptor.hasCustomAccessor() -> CUSTOM_ACCESSOR descriptor.hasCustomAccessor() -> CUSTOM_ACCESSOR
@@ -69,7 +64,7 @@ class JvmFieldApplicabilityChecker : SimpleDeclarationChecker {
} }
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return 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() 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.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty 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.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.annotations.findJvmSyntheticAnnotation 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 import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class JvmSyntheticApplicabilityChecker : SimpleDeclarationChecker { class JvmSyntheticApplicabilityChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val annotation = descriptor.findJvmSyntheticAnnotation() ?: return val annotation = descriptor.findJvmSyntheticAnnotation() ?: return
if (declaration is KtProperty && descriptor is VariableDescriptor && declaration.hasDelegate()) { if (declaration is KtProperty && descriptor is VariableDescriptor && declaration.hasDelegate()) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return 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.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration 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.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.annotations.findStrictfpAnnotation 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 import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class StrictfpApplicabilityChecker : SimpleDeclarationChecker { class StrictfpApplicabilityChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val annotation = descriptor.findStrictfpAnnotation() ?: return val annotation = descriptor.findStrictfpAnnotation() ?: return
if (declaration is KtClassOrObject && descriptor is ClassDescriptor) { if (declaration is KtClassOrObject && descriptor is ClassDescriptor) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return 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.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation 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.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class LocalFunInlineChecker : SimpleDeclarationChecker { class LocalFunInlineChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (InlineUtil.isInline(descriptor) && if (InlineUtil.isInline(descriptor) &&
declaration is KtNamedFunction && declaration is KtNamedFunction &&
descriptor is FunctionDescriptor && descriptor is FunctionDescriptor &&
descriptor.visibility == Visibilities.LOCAL) { 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 isLessJVM18 = jvmTarget.bytecodeVersion < JvmTarget.JVM_1_8.bytecodeVersion
private val supportJvmStaticInInterface = languageVersionSettings.supportsFeature(LanguageFeature.JvmStaticInInterface) private val supportJvmStaticInInterface = languageVersionSettings.supportsFeature(LanguageFeature.JvmStaticInInterface)
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor.hasJvmStaticAnnotation()) { if (descriptor.hasJvmStaticAnnotation()) {
if (declaration is KtNamedFunction || if (declaration is KtNamedFunction ||
declaration is KtProperty || declaration is KtProperty ||
declaration is KtPropertyAccessor || declaration is KtPropertyAccessor ||
declaration is KtParameter) { 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 { class JvmNameAnnotationChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val platformNameAnnotation = DescriptorUtils.getJvmNameAnnotation(descriptor) val platformNameAnnotation = DescriptorUtils.getJvmNameAnnotation(descriptor)
if (platformNameAnnotation != null) { if (platformNameAnnotation != null) {
checkDeclaration(descriptor, platformNameAnnotation, diagnosticHolder) checkDeclaration(descriptor, platformNameAnnotation, context.trace)
} }
} }
private fun checkDeclaration( private fun checkDeclaration(descriptor: DeclarationDescriptor, annotation: AnnotationDescriptor, diagnosticHolder: DiagnosticSink) {
descriptor: DeclarationDescriptor,
annotation: AnnotationDescriptor,
diagnosticHolder: DiagnosticSink
) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
if (descriptor is FunctionDescriptor && !isRenamableFunction(descriptor)) { if (descriptor is FunctionDescriptor && !isRenamableFunction(descriptor)) {
@@ -173,55 +151,38 @@ class JvmNameAnnotationChecker : SimpleDeclarationChecker {
} }
} }
class VolatileAnnotationChecker : SimpleDeclarationChecker { class VolatileAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val volatileAnnotation = DescriptorUtils.getVolatileAnnotation(descriptor) val volatileAnnotation = DescriptorUtils.getVolatileAnnotation(descriptor)
if (volatileAnnotation != null) { if (volatileAnnotation != null) {
if (descriptor is PropertyDescriptor && !descriptor.isVar) { if (descriptor is PropertyDescriptor && !descriptor.isVar) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return 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()) { if (declaration is KtProperty && declaration.hasDelegate()) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return 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 { class SynchronizedAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val synchronizedAnnotation = DescriptorUtils.getSynchronizedAnnotation(descriptor) val synchronizedAnnotation = DescriptorUtils.getSynchronizedAnnotation(descriptor)
if (synchronizedAnnotation != null && descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) { if (synchronizedAnnotation != null && descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(synchronizedAnnotation) ?: return 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 { class OverloadsAnnotationChecker: DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
descriptor.findJvmOverloadsAnnotation()?.let { annotation -> descriptor.findJvmOverloadsAnnotation()?.let { annotation ->
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation)
if (annotationEntry != null) { if (annotationEntry != null) {
checkDeclaration(annotationEntry, descriptor, diagnosticHolder) checkDeclaration(annotationEntry, descriptor, context.trace)
} }
} }
} }
@@ -244,13 +205,8 @@ class OverloadsAnnotationChecker : SimpleDeclarationChecker {
} }
} }
class TypeParameterBoundIsNotArrayChecker : SimpleDeclarationChecker { class TypeParameterBoundIsNotArrayChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val typeParameters = (descriptor as? CallableDescriptor)?.typeParameters val typeParameters = (descriptor as? CallableDescriptor)?.typeParameters
?: (descriptor as? ClassDescriptor)?.declaredTypeParameters ?: (descriptor as? ClassDescriptor)?.declaredTypeParameters
?: return ?: return
@@ -258,7 +214,7 @@ class TypeParameterBoundIsNotArrayChecker : SimpleDeclarationChecker {
for (typeParameter in typeParameters) { for (typeParameter in typeParameters) {
if (typeParameter.upperBounds.any { KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it) }) { if (typeParameter.upperBounds.any { KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it) }) {
val element = DescriptorToSourceUtils.descriptorToDeclaration(typeParameter) ?: declaration 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))
} }
} }
} }
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker; import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker;
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext;
import org.jetbrains.kotlin.resolve.checkers.PublishedApiUsageChecker; import org.jetbrains.kotlin.resolve.checkers.PublishedApiUsageChecker;
import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker; import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker;
@@ -276,12 +277,11 @@ public class ModifiersChecker {
} }
public void runDeclarationCheckers( public void runDeclarationCheckers(@NotNull KtDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
@NotNull KtDeclaration declaration, DeclarationCheckerContext context =
@NotNull DeclarationDescriptor descriptor new DeclarationCheckerContext(trace, languageVersionSettings, deprecationResolver, expectActualTracker);
) {
for (DeclarationChecker checker : declarationCheckers) { for (DeclarationChecker checker : declarationCheckers) {
checker.check(declaration, descriptor, trace, trace.getBindingContext(), languageVersionSettings, expectActualTracker); checker.check(declaration, descriptor, context);
} }
OperatorModifierChecker.INSTANCE.check(declaration, descriptor, trace, languageVersionSettings); OperatorModifierChecker.INSTANCE.check(declaration, descriptor, trace, languageVersionSettings);
PublishedApiUsageChecker.INSTANCE.check(declaration, descriptor, trace); PublishedApiUsageChecker.INSTANCE.check(declaration, descriptor, trace);
@@ -296,28 +296,24 @@ public class ModifiersChecker {
} }
} }
@NotNull
private final AnnotationChecker annotationChecker; private final AnnotationChecker annotationChecker;
@NotNull
private final Iterable<DeclarationChecker> declarationCheckers; private final Iterable<DeclarationChecker> declarationCheckers;
@NotNull
private final LanguageVersionSettings languageVersionSettings; private final LanguageVersionSettings languageVersionSettings;
@NotNull
private final ExpectActualTracker expectActualTracker; private final ExpectActualTracker expectActualTracker;
private final DeprecationResolver deprecationResolver;
public ModifiersChecker( public ModifiersChecker(
@NotNull AnnotationChecker annotationChecker, @NotNull AnnotationChecker annotationChecker,
@NotNull Iterable<DeclarationChecker> declarationCheckers, @NotNull Iterable<DeclarationChecker> declarationCheckers,
@NotNull LanguageVersionSettings languageVersionSettings, @NotNull LanguageVersionSettings languageVersionSettings,
@NotNull ExpectActualTracker expectActualTracker @NotNull ExpectActualTracker expectActualTracker,
@NotNull DeprecationResolver deprecationResolver
) { ) {
this.annotationChecker = annotationChecker; this.annotationChecker = annotationChecker;
this.declarationCheckers = declarationCheckers; this.declarationCheckers = declarationCheckers;
this.languageVersionSettings = languageVersionSettings; this.languageVersionSettings = languageVersionSettings;
this.expectActualTracker = expectActualTracker; this.expectActualTracker = expectActualTracker;
this.deprecationResolver = deprecationResolver;
} }
@NotNull @NotNull
@@ -19,28 +19,21 @@ package org.jetbrains.kotlin.resolve.checkers
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isError
object ConstModifierChecker : SimpleDeclarationChecker { object ConstModifierChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor !is VariableDescriptor || !declaration.hasModifier(KtTokens.CONST_KEYWORD)) return if (descriptor !is VariableDescriptor || !declaration.hasModifier(KtTokens.CONST_KEYWORD)) return
val constModifierPsiElement = declaration.modifierList!!.getModifier(KtTokens.CONST_KEYWORD)!! val constModifierPsiElement = declaration.modifierList!!.getModifier(KtTokens.CONST_KEYWORD)!!
val diagnostic = checkCanBeConst(declaration, constModifierPsiElement, descriptor).diagnostic val diagnostic = checkCanBeConst(declaration, constModifierPsiElement, descriptor).diagnostic
if (diagnostic != null) { if (diagnostic != null) {
diagnosticHolder.report(diagnostic) context.trace.report(diagnostic)
} }
} }
@@ -18,39 +18,32 @@ package org.jetbrains.kotlin.resolve.checkers
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.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
class DataClassDeclarationChecker : SimpleDeclarationChecker { class DataClassDeclarationChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor !is ClassDescriptor) return if (descriptor !is ClassDescriptor) return
if (declaration !is KtClassOrObject) return if (declaration !is KtClassOrObject) return
if (descriptor.isData) { if (descriptor.isData) {
if (descriptor.unsubstitutedPrimaryConstructor == null && descriptor.constructors.isNotEmpty()) { if (descriptor.unsubstitutedPrimaryConstructor == null && descriptor.constructors.isNotEmpty()) {
declaration.nameIdentifier?.let { diagnosticHolder.report(Errors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS.on(it)) } declaration.nameIdentifier?.let { context.trace.report(Errors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS.on(it)) }
} }
val primaryConstructor = declaration.primaryConstructor val primaryConstructor = declaration.primaryConstructor
val parameters = primaryConstructor?.valueParameters ?: emptyList() val parameters = primaryConstructor?.valueParameters ?: emptyList()
if (parameters.isEmpty()) { if (parameters.isEmpty()) {
(primaryConstructor?.valueParameterList ?: declaration.nameIdentifier)?.let { (primaryConstructor?.valueParameterList ?: declaration.nameIdentifier)?.let {
diagnosticHolder.report(Errors.DATA_CLASS_WITHOUT_PARAMETERS.on(it)) context.trace.report(Errors.DATA_CLASS_WITHOUT_PARAMETERS.on(it))
} }
} }
for (parameter in parameters) { for (parameter in parameters) {
if (parameter.isVarArg) { if (parameter.isVarArg) {
diagnosticHolder.report(Errors.DATA_CLASS_VARARG_PARAMETER.on(parameter)) context.trace.report(Errors.DATA_CLASS_VARARG_PARAMETER.on(parameter))
} }
if (!parameter.hasValOrVar()) { if (!parameter.hasValOrVar()) {
diagnosticHolder.report(Errors.DATA_CLASS_NOT_PROPERTY_PARAMETER.on(parameter)) context.trace.report(Errors.DATA_CLASS_NOT_PROPERTY_PARAMETER.on(parameter))
} }
} }
} }
@@ -18,37 +18,18 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DeprecationResolver
interface DeclarationChecker { interface DeclarationChecker {
// TODO: Think about encapsulating these parameters into specific class like CheckerParameters when you're about to add another one fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext)
fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
)
} }
interface SimpleDeclarationChecker : DeclarationChecker { class DeclarationCheckerContext(
override fun check( override val trace: BindingTrace,
declaration: KtDeclaration, override val languageVersionSettings: LanguageVersionSettings,
descriptor: DeclarationDescriptor, override val deprecationResolver: DeprecationResolver,
diagnosticHolder: DiagnosticSink, val expectActualTracker: ExpectActualTracker
bindingContext: BindingContext, ) : CheckerContext
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) = check(declaration, descriptor, diagnosticHolder, bindingContext)
fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
)
}
@@ -16,14 +16,12 @@
package org.jetbrains.kotlin.resolve.checkers package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
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.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
@@ -33,24 +31,17 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
class DelegationChecker : DeclarationChecker { class DelegationChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
if (descriptor !is ClassDescriptor) return if (descriptor !is ClassDescriptor) return
if (declaration !is KtClassOrObject) return if (declaration !is KtClassOrObject) return
for (specifier in declaration.superTypeListEntries) { for (specifier in declaration.superTypeListEntries) {
if (specifier is KtDelegatedSuperTypeEntry) { if (specifier is KtDelegatedSuperTypeEntry) {
val superType = specifier.typeReference?.let { bindingContext.get(BindingContext.TYPE, it) } ?: continue val superType = specifier.typeReference?.let { context.trace.get(BindingContext.TYPE, it) } ?: continue
val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
for ((delegated, delegatedTo) in DelegationResolver.getDelegates(descriptor, superTypeDescriptor)) { for ((delegated, delegatedTo) in DelegationResolver.getDelegates(descriptor, superTypeDescriptor)) {
checkDescriptor(declaration, delegated, delegatedTo, diagnosticHolder) checkDescriptor(declaration, delegated, delegatedTo, context.trace)
} }
} }
} }
@@ -18,29 +18,22 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDynamicExtensionAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasDynamicExtensionAnnotation
import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.isDynamic
object DynamicReceiverChecker : SimpleDeclarationChecker { object DynamicReceiverChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor !is CallableDescriptor || declaration !is KtCallableDeclaration || descriptor.hasDynamicExtensionAnnotation()) return if (descriptor !is CallableDescriptor || declaration !is KtCallableDeclaration || descriptor.hasDynamicExtensionAnnotation()) return
// function expression // function expression
if (declaration is KtNamedFunction && declaration.name == null) return if (declaration is KtNamedFunction && declaration.name == null) return
if (descriptor.extensionReceiverParameter?.value?.type?.isDynamic() == true) { if (descriptor.extensionReceiverParameter?.value?.type?.isDynamic() == true) {
diagnosticHolder.report(Errors.DYNAMIC_RECEIVER_NOT_ALLOWED.on(declaration)) context.trace.report(Errors.DYNAMIC_RECEIVER_NOT_ALLOWED.on(declaration))
} }
} }
} }
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.VfsUtilCore
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.AnalysisFlag import org.jetbrains.kotlin.config.AnalysisFlag
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
@@ -32,7 +31,6 @@ import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Compatibility.Compatible import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Compatibility.Compatible
@@ -56,24 +54,17 @@ import org.jetbrains.kotlin.utils.keysToMap
import java.io.File import java.io.File
object ExpectedActualDeclarationChecker : DeclarationChecker { object ExpectedActualDeclarationChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return
if (declaration !is KtNamedDeclaration) return if (declaration !is KtNamedDeclaration) return
if (descriptor !is MemberDescriptor || DescriptorUtils.isEnumEntry(descriptor)) return if (descriptor !is MemberDescriptor || DescriptorUtils.isEnumEntry(descriptor)) return
if (descriptor.isExpect) { if (descriptor.isExpect) {
checkExpectedDeclarationHasActual(declaration, descriptor, diagnosticHolder, descriptor.module, expectActualTracker) checkExpectedDeclarationHasActual(declaration, descriptor, context.trace, descriptor.module, context.expectActualTracker)
} else { } else {
val checkActual = !languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckActual) val checkActual = !context.languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckActual)
checkActualDeclarationHasExpected(declaration, descriptor, diagnosticHolder, checkActual) checkActualDeclarationHasExpected(declaration, descriptor, context.trace, checkActual)
} }
} }
@@ -18,22 +18,14 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.util.CheckResult import org.jetbrains.kotlin.util.CheckResult
import org.jetbrains.kotlin.util.InfixChecks import org.jetbrains.kotlin.util.InfixChecks
class InfixModifierChecker : SimpleDeclarationChecker { class InfixModifierChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val functionDescriptor = descriptor as? FunctionDescriptor ?: return val functionDescriptor = descriptor as? FunctionDescriptor ?: return
if (!functionDescriptor.isInfix) return if (!functionDescriptor.isInfix) return
val modifier = declaration.modifierList?.getModifier(KtTokens.INFIX_KEYWORD) ?: return val modifier = declaration.modifierList?.getModifier(KtTokens.INFIX_KEYWORD) ?: return
@@ -41,6 +33,6 @@ class InfixModifierChecker : SimpleDeclarationChecker {
val checkResult = InfixChecks.check(functionDescriptor) val checkResult = InfixChecks.check(functionDescriptor)
if (checkResult !is CheckResult.IllegalSignature) return if (checkResult !is CheckResult.IllegalSignature) return
diagnosticHolder.report(Errors.INAPPLICABLE_INFIX_MODIFIER.on(modifier, checkResult.error)) context.trace.report(Errors.INAPPLICABLE_INFIX_MODIFIER.on(modifier, checkResult.error))
} }
} }
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.resolve.checkers package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionType import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
@@ -29,22 +28,20 @@ import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
object InlineParameterChecker : SimpleDeclarationChecker { object InlineParameterChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
if (declaration is KtFunction) { if (declaration is KtFunction) {
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD) val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
for (parameter in declaration.valueParameters) { for (parameter in declaration.valueParameters) {
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, parameter) val parameterDescriptor = context.trace.get(BindingContext.VALUE_PARAMETER, parameter)
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) { if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) {
parameter.reportIncorrectInline(KtTokens.NOINLINE_KEYWORD, diagnosticHolder) parameter.reportIncorrectInline(KtTokens.NOINLINE_KEYWORD, context.trace)
parameter.reportIncorrectInline(KtTokens.CROSSINLINE_KEYWORD, diagnosticHolder) parameter.reportIncorrectInline(KtTokens.CROSSINLINE_KEYWORD, context.trace)
} }
if (inline && !parameter.hasModifier(KtTokens.NOINLINE_KEYWORD) && if (inline && !parameter.hasModifier(KtTokens.NOINLINE_KEYWORD) &&
parameterDescriptor?.type?.isSuspendFunctionType == true) { parameterDescriptor?.type?.isSuspendFunctionType == true) {
diagnosticHolder.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter)) context.trace.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
} }
} }
} }
@@ -18,23 +18,16 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
object KClassWithIncorrectTypeArgumentChecker : SimpleDeclarationChecker { object KClassWithIncorrectTypeArgumentChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor !is CallableMemberDescriptor || descriptor.visibility == Visibilities.LOCAL) return if (descriptor !is CallableMemberDescriptor || descriptor.visibility == Visibilities.LOCAL) return
if (declaration !is KtCallableDeclaration || declaration.typeReference != null) return if (declaration !is KtCallableDeclaration || declaration.typeReference != null) return
@@ -58,11 +51,8 @@ object KClassWithIncorrectTypeArgumentChecker : SimpleDeclarationChecker {
} }
if (typeParameterWithoutNotNullableUpperBound != null) { if (typeParameterWithoutNotNullableUpperBound != null) {
diagnosticHolder.report( context.trace.report(
Errors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE.on( Errors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE.on(declaration, typeParameterWithoutNotNullableUpperBound!!)
declaration,
typeParameterWithoutNotNullableUpperBound!!
)
) )
} }
} }
@@ -22,10 +22,8 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.RequireKotlinNames import org.jetbrains.kotlin.resolve.RequireKotlinNames
import org.jetbrains.kotlin.resolve.SINCE_KOTLIN_FQ_NAME import org.jetbrains.kotlin.resolve.SINCE_KOTLIN_FQ_NAME
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
@@ -33,26 +31,15 @@ import org.jetbrains.kotlin.resolve.source.getPsi
abstract class KotlinVersionStringAnnotationValueChecker( abstract class KotlinVersionStringAnnotationValueChecker(
private val annotationFqName: FqName private val annotationFqName: FqName
) : DeclarationChecker { ) : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
val annotation = descriptor.annotations.findAnnotation(annotationFqName) ?: return val annotation = descriptor.annotations.findAnnotation(annotationFqName) ?: return
val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return
if (!version.matches(VERSION_REGEX)) { if (!version.matches(VERSION_REGEX)) {
diagnosticHolder.report( context.trace.report(Errors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE.on(annotation.source.getPsi() ?: declaration, annotationFqName))
Errors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE.on(
annotation.source.getPsi() ?: declaration, annotationFqName
)
)
return return
} }
extraCheck(declaration, annotation, version, diagnosticHolder, languageVersionSettings) extraCheck(declaration, annotation, version, context.trace, context.languageVersionSettings)
} }
open fun extraCheck( open fun extraCheck(
@@ -25,25 +25,18 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtTypeParameter import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil
class ReifiedTypeParameterAnnotationChecker : SimpleDeclarationChecker { class ReifiedTypeParameterAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor is CallableDescriptor && if (descriptor is CallableDescriptor &&
!(InlineUtil.isInline(descriptor) || InlineUtil.isPropertyWithAllAccessorsAreInline(descriptor))) { !(InlineUtil.isInline(descriptor) || InlineUtil.isPropertyWithAllAccessorsAreInline(descriptor))) {
checkTypeParameterDescriptorsAreNotReified(descriptor.typeParameters, diagnosticHolder) checkTypeParameterDescriptorsAreNotReified(descriptor.typeParameters, context.trace)
} }
if (descriptor is ClassDescriptor) { if (descriptor is ClassDescriptor) {
checkTypeParameterDescriptorsAreNotReified(descriptor.declaredTypeParameters, diagnosticHolder) checkTypeParameterDescriptorsAreNotReified(descriptor.declaredTypeParameters, context.trace)
} }
} }
@@ -18,29 +18,22 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
object SuspendOperatorsCheckers : SimpleDeclarationChecker { object SuspendOperatorsCheckers : DeclarationChecker {
private val UNSUPPORTED_OPERATOR_NAMES = setOf( private val UNSUPPORTED_OPERATOR_NAMES = setOf(
OperatorNameConventions.CONTAINS, OperatorNameConventions.CONTAINS,
OperatorNameConventions.GET, OperatorNameConventions.SET OperatorNameConventions.GET, OperatorNameConventions.SET
) )
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor is FunctionDescriptor && descriptor.isSuspend && descriptor.isOperator && if (descriptor is FunctionDescriptor && descriptor.isSuspend && descriptor.isOperator &&
descriptor.name in UNSUPPORTED_OPERATOR_NAMES) { descriptor.name in UNSUPPORTED_OPERATOR_NAMES) {
declaration.modifierList?.getModifier(KtTokens.OPERATOR_KEYWORD)?.let { declaration.modifierList?.getModifier(KtTokens.OPERATOR_KEYWORD)?.let {
diagnosticHolder.report(Errors.UNSUPPORTED.on(it, "suspend operator \"${descriptor.name}\"")) context.trace.report(Errors.UNSUPPORTED.on(it, "suspend operator \"${descriptor.name}\""))
} }
} }
} }
@@ -24,12 +24,9 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
object UnderscoreChecker : DeclarationChecker { object UnderscoreChecker : DeclarationChecker {
@JvmOverloads @JvmOverloads
fun checkIdentifier( fun checkIdentifier(
identifier: PsiElement?, identifier: PsiElement?,
@@ -61,29 +58,22 @@ object UnderscoreChecker : DeclarationChecker {
checkIdentifier(declaration.nameIdentifier, diagnosticHolder, languageVersionSettings, allowSingleUnderscore) checkIdentifier(declaration.nameIdentifier, diagnosticHolder, languageVersionSettings, allowSingleUnderscore)
} }
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
if (declaration is KtProperty && descriptor !is VariableDescriptor) return if (declaration is KtProperty && descriptor !is VariableDescriptor) return
if (declaration is KtCallableDeclaration) { if (declaration is KtCallableDeclaration) {
for (parameter in declaration.valueParameters) { for (parameter in declaration.valueParameters) {
checkNamed( checkNamed(
parameter, diagnosticHolder, languageVersionSettings, parameter, context.trace, context.languageVersionSettings,
allowSingleUnderscore = descriptor is FunctionExpressionDescriptor allowSingleUnderscore = descriptor is FunctionExpressionDescriptor
) )
} }
} }
if (declaration is KtTypeParameterListOwner) { if (declaration is KtTypeParameterListOwner) {
for (typeParameter in declaration.typeParameters) { for (typeParameter in declaration.typeParameters) {
checkNamed(typeParameter, diagnosticHolder, languageVersionSettings) checkNamed(typeParameter, context.trace, context.languageVersionSettings)
} }
} }
if (declaration !is KtNamedDeclaration) return if (declaration !is KtNamedDeclaration) return
checkNamed(declaration, diagnosticHolder, languageVersionSettings) checkNamed(declaration, context.trace, context.languageVersionSettings)
} }
} }
@@ -19,18 +19,14 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
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.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.js.naming.NameSuggestion
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDeclarationChecker { class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
if (AnnotationsUtils.isNativeObject(descriptor)) return if (AnnotationsUtils.isNativeObject(descriptor)) return
if (descriptor.containingDeclaration !is ClassDescriptor) return if (descriptor.containingDeclaration !is ClassDescriptor) return
@@ -40,12 +36,12 @@ class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : Si
if (descriptor is ClassDescriptor) { if (descriptor is ClassDescriptor) {
if (simpleName in PROHIBITED_STATIC_NAMES) { if (simpleName in PROHIBITED_STATIC_NAMES) {
diagnosticHolder.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Function.$simpleName")) context.trace.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Function.$simpleName"))
} }
} }
else if (descriptor is CallableMemberDescriptor) { else if (descriptor is CallableMemberDescriptor) {
if (simpleName in PROHIBITED_MEMBER_NAMES) { if (simpleName in PROHIBITED_MEMBER_NAMES) {
diagnosticHolder.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Object.prototype.$simpleName")) context.trace.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Object.prototype.$simpleName"))
} }
} }
} }
@@ -18,35 +18,33 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
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.types.isDynamic import org.jetbrains.kotlin.types.isDynamic
object JsDynamicDeclarationChecker : SimpleDeclarationChecker { object JsDynamicDeclarationChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, descriptor: DeclarationDescriptor, val trace = context.trace
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
if (declaration is KtProperty && descriptor is VariableDescriptorWithAccessors) { if (declaration is KtProperty && descriptor is VariableDescriptorWithAccessors) {
declaration.delegateExpression?.let { delegateExpression -> declaration.delegateExpression?.let { delegateExpression ->
val provideDelegateCall = bindingContext[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor] val provideDelegateCall = trace[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor]
if (provideDelegateCall != null && provideDelegateCall.resultingDescriptor.returnType?.isDynamic() == true || if (provideDelegateCall != null && provideDelegateCall.resultingDescriptor.returnType?.isDynamic() == true ||
bindingContext.getType(delegateExpression)?.isDynamic() == true trace.getType(delegateExpression)?.isDynamic() == true
) { ) {
diagnosticHolder.report(ErrorsJs.PROPERTY_DELEGATION_BY_DYNAMIC.on(delegateExpression)) trace.report(ErrorsJs.PROPERTY_DELEGATION_BY_DYNAMIC.on(delegateExpression))
} }
} }
} }
else if (declaration is KtClassOrObject) { else if (declaration is KtClassOrObject) {
for (delegateDecl in declaration.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>()) { for (delegateDecl in declaration.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>()) {
val delegateExpr = delegateDecl.delegateExpression ?: continue val delegateExpr = delegateDecl.delegateExpression ?: continue
if (bindingContext.getType(delegateExpr)?.isDynamic() == true) { if (trace.getType(delegateExpr)?.isDynamic() == true) {
diagnosticHolder.report(ErrorsJs.DELEGATION_BY_DYNAMIC.on(delegateExpr)) trace.report(ErrorsJs.DELEGATION_BY_DYNAMIC.on(delegateExpr))
} }
} }
} }
@@ -28,44 +28,45 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
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.descriptorUtil.* import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
object JsExternalChecker : SimpleDeclarationChecker { object JsExternalChecker : DeclarationChecker {
val DEFINED_EXTERNALLY_PROPERTY_NAMES = setOf(FqNameUnsafe("kotlin.js.noImpl"), FqNameUnsafe("kotlin.js.definedExternally")) val DEFINED_EXTERNALLY_PROPERTY_NAMES = setOf(FqNameUnsafe("kotlin.js.noImpl"), FqNameUnsafe("kotlin.js.definedExternally"))
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
bindingContext: BindingContext) {
if (!AnnotationsUtils.isNativeObject(descriptor)) return if (!AnnotationsUtils.isNativeObject(descriptor)) return
val trace = context.trace
if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) { if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) {
if (isDirectlyExternal(declaration, descriptor) && descriptor !is PropertyAccessorDescriptor) { if (isDirectlyExternal(declaration, descriptor) && descriptor !is PropertyAccessorDescriptor) {
diagnosticHolder.report(ErrorsJs.NESTED_EXTERNAL_DECLARATION.on(declaration)) trace.report(ErrorsJs.NESTED_EXTERNAL_DECLARATION.on(declaration))
} }
} }
if (DescriptorUtils.isAnnotationClass(descriptor)) { if (DescriptorUtils.isAnnotationClass(descriptor)) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "annotation class")) trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "annotation class"))
} }
else if (descriptor is ClassDescriptor && descriptor.isData) { else if (descriptor is ClassDescriptor && descriptor.isData) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "data class")) trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "data class"))
} }
else if (descriptor is PropertyAccessorDescriptor && isDirectlyExternal(declaration, descriptor)) { else if (descriptor is PropertyAccessorDescriptor && isDirectlyExternal(declaration, descriptor)) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "property accessor")) trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "property accessor"))
} }
else if (descriptor is ClassDescriptor && descriptor.isInner) { else if (descriptor is ClassDescriptor && descriptor.isInner) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "inner class")) trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "inner class"))
} }
else if (isPrivateMemberOfExternalClass(descriptor)) { else if (isPrivateMemberOfExternalClass(descriptor)) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "private member of class")) trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "private member of class"))
} }
if (descriptor is ClassDescriptor && descriptor.kind != ClassKind.INTERFACE && if (descriptor is ClassDescriptor && descriptor.kind != ClassKind.INTERFACE &&
descriptor.containingDeclaration.let { it is ClassDescriptor && it.kind == ClassKind.INTERFACE } descriptor.containingDeclaration.let { it is ClassDescriptor && it.kind == ClassKind.INTERFACE }
) { ) {
diagnosticHolder.report(ErrorsJs.NESTED_CLASS_IN_EXTERNAL_INTERFACE.on(declaration)) trace.report(ErrorsJs.NESTED_CLASS_IN_EXTERNAL_INTERFACE.on(declaration))
} }
if (descriptor !is PropertyAccessorDescriptor && descriptor.isExtension) { if (descriptor !is PropertyAccessorDescriptor && descriptor.isExtension) {
@@ -74,7 +75,7 @@ object JsExternalChecker : SimpleDeclarationChecker {
is PropertyDescriptor -> "extension property" is PropertyDescriptor -> "extension property"
else -> "extension member" else -> "extension member"
} }
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, target)) trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, target))
} }
if (descriptor is ClassDescriptor && descriptor.kind != ClassKind.ANNOTATION_CLASS) { if (descriptor is ClassDescriptor && descriptor.kind != ClassKind.ANNOTATION_CLASS) {
@@ -83,19 +84,19 @@ object JsExternalChecker : SimpleDeclarationChecker {
superClasses.removeAll { it.fqNameUnsafe == KotlinBuiltIns.FQ_NAMES._enum } superClasses.removeAll { it.fqNameUnsafe == KotlinBuiltIns.FQ_NAMES._enum }
} }
if (superClasses.any { !AnnotationsUtils.isNativeObject(it) && it.fqNameSafe != KotlinBuiltIns.FQ_NAMES.throwable }) { if (superClasses.any { !AnnotationsUtils.isNativeObject(it) && it.fqNameSafe != KotlinBuiltIns.FQ_NAMES.throwable }) {
diagnosticHolder.report(ErrorsJs.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE.on(declaration)) trace.report(ErrorsJs.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE.on(declaration))
} }
} }
if (descriptor is FunctionDescriptor && descriptor.isInline) { if (descriptor is FunctionDescriptor && descriptor.isInline) {
diagnosticHolder.report(ErrorsJs.INLINE_EXTERNAL_DECLARATION.on(declaration)) trace.report(ErrorsJs.INLINE_EXTERNAL_DECLARATION.on(declaration))
} }
if (descriptor is CallableMemberDescriptor && !(descriptor is PropertyAccessorDescriptor && descriptor.isDefault)) { if (descriptor is CallableMemberDescriptor && !(descriptor is PropertyAccessorDescriptor && descriptor.isDefault)) {
for (p in descriptor.valueParameters) { for (p in descriptor.valueParameters) {
if ((p.varargElementType ?: p.type).isExtensionFunctionType) { if ((p.varargElementType ?: p.type).isExtensionFunctionType) {
val ktParam = p.source.getPsi() as? KtParameter ?: declaration val ktParam = p.source.getPsi() as? KtParameter ?: declaration
diagnosticHolder.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(ktParam)) trace.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(ktParam))
} }
} }
@@ -104,21 +105,21 @@ object JsExternalChecker : SimpleDeclarationChecker {
!(descriptor.getter?.isDefault ?: true && descriptor.setter?.isDefault ?: true) !(descriptor.getter?.isDefault ?: true && descriptor.setter?.isDefault ?: true)
if (!propertyWithCustomAccessors && descriptor.returnType?.isExtensionFunctionType ?: false) { if (!propertyWithCustomAccessors && descriptor.returnType?.isExtensionFunctionType ?: false) {
diagnosticHolder.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(declaration)) trace.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(declaration))
} }
} }
if (descriptor is CallableMemberDescriptor && descriptor.isNonAbstractMemberOfInterface() && if (descriptor is CallableMemberDescriptor && descriptor.isNonAbstractMemberOfInterface() &&
!descriptor.isNullableProperty() !descriptor.isNullableProperty()
) { ) {
diagnosticHolder.report(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE.on(declaration)) trace.report(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE.on(declaration))
} }
checkBody(declaration, descriptor, diagnosticHolder, bindingContext) checkBody(declaration, descriptor, trace, trace.bindingContext)
checkDelegation(declaration, descriptor, diagnosticHolder) checkDelegation(declaration, descriptor, trace)
checkAnonymousInitializer(declaration, diagnosticHolder) checkAnonymousInitializer(declaration, trace)
checkEnumEntry(declaration, diagnosticHolder) checkEnumEntry(declaration, trace)
checkConstructorPropertyParam(declaration, descriptor, diagnosticHolder) checkConstructorPropertyParam(declaration, descriptor, trace)
} }
private fun checkBody( private fun checkBody(
@@ -17,28 +17,22 @@
package org.jetbrains.kotlin.js.resolve.diagnostics package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils 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
object JsExternalFileChecker : SimpleDeclarationChecker { object JsExternalFileChecker : DeclarationChecker {
private val annotationFqNames = setOf(AnnotationsUtils.JS_MODULE_ANNOTATION, AnnotationsUtils.JS_QUALIFIER_ANNOTATION) private val annotationFqNames = setOf(AnnotationsUtils.JS_MODULE_ANNOTATION, AnnotationsUtils.JS_QUALIFIER_ANNOTATION)
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (!AnnotationsUtils.isNativeObject(descriptor) && DescriptorUtils.isTopLevelDeclaration(descriptor)) { if (!AnnotationsUtils.isNativeObject(descriptor) && DescriptorUtils.isTopLevelDeclaration(descriptor)) {
AnnotationsUtils.getContainingFileAnnotations(bindingContext, descriptor).asSequence() AnnotationsUtils.getContainingFileAnnotations(context.trace.bindingContext, descriptor).asSequence()
.firstOrNull { it.fqName in annotationFqNames } .firstOrNull { it.fqName in annotationFqNames }
?.let { ?.let {
diagnosticHolder.report(ErrorsJs.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE.on(declaration, it.type)) context.trace.report(ErrorsJs.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE.on(declaration, it.type))
} }
} }
} }
} }
@@ -21,40 +21,33 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
object JsInheritanceChecker : SimpleDeclarationChecker { object JsInheritanceChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (descriptor is FunctionDescriptor && !descriptor.isEffectivelyExternal() && if (descriptor is FunctionDescriptor && !descriptor.isEffectivelyExternal() &&
isOverridingExternalWithOptionalParams(descriptor) isOverridingExternalWithOptionalParams(descriptor)
) { ) {
diagnosticHolder.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS.on(declaration)) context.trace.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS.on(declaration))
} }
else if (descriptor is ClassDescriptor && !descriptor.isEffectivelyExternal()) { else if (descriptor is ClassDescriptor && !descriptor.isEffectivelyExternal()) {
val fakeOverriddenMethod = findFakeMethodOverridingExternalWithOptionalParams(descriptor) val fakeOverriddenMethod = findFakeMethodOverridingExternalWithOptionalParams(descriptor)
if (fakeOverriddenMethod != null) { if (fakeOverriddenMethod != null) {
diagnosticHolder.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE.on( context.trace.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE.on(declaration, fakeOverriddenMethod))
declaration, fakeOverriddenMethod))
} }
} }
if (descriptor is ClassDescriptor && if (descriptor is ClassDescriptor &&
descriptor.defaultType.immediateSupertypes().any { it.isBuiltinFunctionalTypeOrSubtype } descriptor.defaultType.immediateSupertypes().any { it.isBuiltinFunctionalTypeOrSubtype }
) { ) {
diagnosticHolder.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject)) context.trace.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject))
} }
} }
@@ -19,55 +19,47 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
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
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorUtils 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.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
object JsModuleChecker : SimpleDeclarationChecker { object JsModuleChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, val trace = context.trace
descriptor: DeclarationDescriptor, checkSuperClass(declaration, descriptor, trace)
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
checkSuperClass(bindingContext, diagnosticHolder, descriptor, declaration)
if (AnnotationsUtils.getModuleName(descriptor) == null && !AnnotationsUtils.isNonModule(descriptor)) return if (AnnotationsUtils.getModuleName(descriptor) == null && !AnnotationsUtils.isNonModule(descriptor)) return
if (descriptor is PropertyDescriptor && descriptor.isVar) { if (descriptor is PropertyDescriptor && descriptor.isVar) {
diagnosticHolder.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_VAR.on(declaration)) trace.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_VAR.on(declaration))
} }
if (!AnnotationsUtils.isNativeObject(descriptor)) { if (!AnnotationsUtils.isNativeObject(descriptor)) {
diagnosticHolder.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_NON_NATIVE.on(declaration)) trace.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_NON_NATIVE.on(declaration))
} }
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) { if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
val isFileModuleOrNonModule = AnnotationsUtils.getFileModuleName(bindingContext, descriptor) != null || val isFileModuleOrNonModule = AnnotationsUtils.getFileModuleName(trace.bindingContext, descriptor) != null ||
AnnotationsUtils.isFromNonModuleFile(bindingContext, descriptor) AnnotationsUtils.isFromNonModuleFile(trace.bindingContext, descriptor)
if (isFileModuleOrNonModule) { if (isFileModuleOrNonModule) {
diagnosticHolder.report(ErrorsJs.NESTED_JS_MODULE_PROHIBITED.on(declaration)) trace.report(ErrorsJs.NESTED_JS_MODULE_PROHIBITED.on(declaration))
} }
} }
} }
private fun checkSuperClass( private fun checkSuperClass(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
bindingContext: BindingContext,
diagnosticHolder: DiagnosticSink,
descriptor: DeclarationDescriptor,
declaration: KtDeclaration
) {
if (descriptor !is ClassDescriptor) return if (descriptor !is ClassDescriptor) return
val superClass = descriptor.getSuperClassNotAny() ?: return val superClass = descriptor.getSuperClassNotAny() ?: return
val psi = (declaration as KtClassOrObject).superTypeListEntries.firstOrNull { entry -> val psi = (declaration as KtClassOrObject).superTypeListEntries.firstOrNull { entry ->
bindingContext[BindingContext.TYPE, entry.typeReference]?.constructor?.declarationDescriptor == superClass trace[BindingContext.TYPE, entry.typeReference]?.constructor?.declarationDescriptor == superClass
} }
checkJsModuleUsage(bindingContext, diagnosticHolder, descriptor, superClass, psi ?: declaration) checkJsModuleUsage(trace.bindingContext, trace, descriptor, superClass, psi ?: declaration)
} }
} }
@@ -19,30 +19,26 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
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.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
object JsMultipleInheritanceChecker : SimpleDeclarationChecker { object JsMultipleInheritanceChecker : DeclarationChecker {
private val fqNames = listOf( private val fqNames = listOf(
FqNameUnsafe("kotlin.CharSequence.get"), FqNameUnsafe("kotlin.CharSequence.get"),
FqNameUnsafe("kotlin.collections.CharIterator.nextChar") FqNameUnsafe("kotlin.collections.CharIterator.nextChar")
) )
private val simpleNames = fqNames.mapTo(mutableSetOf()) { it.shortName() } private val simpleNames = fqNames.mapTo(mutableSetOf()) { it.shortName() }
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
if (descriptor !is ClassDescriptor) return if (descriptor !is ClassDescriptor) return
for (callable in descriptor.unsubstitutedMemberScope.getContributedDescriptors { it in simpleNames } for (callable in descriptor.unsubstitutedMemberScope.getContributedDescriptors { it in simpleNames }
.filterIsInstance<CallableMemberDescriptor>()) { .filterIsInstance<CallableMemberDescriptor>()) {
if (callable.overriddenDescriptors.size > 1 && callable.overriddenDescriptors.any { it.fqNameUnsafe in fqNames }) { if (callable.overriddenDescriptors.size > 1 && callable.overriddenDescriptors.any { it.fqNameUnsafe in fqNames }) {
diagnosticHolder.report(ErrorsJs.WRONG_MULTIPLE_INHERITANCE.on(declaration, callable)) context.trace.report(ErrorsJs.WRONG_MULTIPLE_INHERITANCE.on(declaration, callable))
} }
} }
} }
@@ -1,56 +1,25 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* * that can be found in the license/LICENSE.txt file.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.js.resolve.diagnostics package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.js.naming.NameSuggestion
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
class JsNameCharsChecker(private val suggestion: NameSuggestion) : SimpleDeclarationChecker { class JsNameCharsChecker(private val suggestion: NameSuggestion) : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
if (descriptor is PropertyAccessorDescriptor && AnnotationsUtils.getJsName(descriptor) == null) return if (descriptor is PropertyAccessorDescriptor && AnnotationsUtils.getJsName(descriptor) == null) return
val suggestedName = suggestion.suggest(descriptor) ?: return val suggestedName = suggestion.suggest(descriptor) ?: return
if (suggestedName.stable && suggestedName.names.any { NameSuggestion.sanitizeName(it) != it }) { if (suggestedName.stable && suggestedName.names.any { NameSuggestion.sanitizeName(it) != it }) {
diagnosticHolder.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(declaration)) context.trace.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(declaration))
} }
} }
} }
@@ -17,22 +17,21 @@
package org.jetbrains.kotlin.js.resolve.diagnostics package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.PredefinedAnnotation import org.jetbrains.kotlin.js.PredefinedAnnotation
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
object JsNameChecker : SimpleDeclarationChecker { object JsNameChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
bindingContext: BindingContext) { val trace = context.trace
if (descriptor is PropertyDescriptor) { if (descriptor is PropertyDescriptor) {
val namedAccessorCount = descriptor.accessors.count { AnnotationsUtils.getJsName(it) != null } val namedAccessorCount = descriptor.accessors.count { AnnotationsUtils.getJsName(it) != null }
if (namedAccessorCount > 0 && namedAccessorCount < descriptor.accessors.size) { if (namedAccessorCount > 0 && namedAccessorCount < descriptor.accessors.size) {
diagnosticHolder.report(ErrorsJs.JS_NAME_IS_NOT_ON_ALL_ACCESSORS.on(declaration)) trace.report(ErrorsJs.JS_NAME_IS_NOT_ON_ALL_ACCESSORS.on(declaration))
} }
} }
@@ -40,27 +39,27 @@ object JsNameChecker : SimpleDeclarationChecker {
val jsNamePsi = jsName.source.getPsi() ?: declaration val jsNamePsi = jsName.source.getPsi() ?: declaration
if (AnnotationsUtils.getNameForAnnotatedObject(descriptor, PredefinedAnnotation.NATIVE) != null) { if (AnnotationsUtils.getNameForAnnotatedObject(descriptor, PredefinedAnnotation.NATIVE) != null) {
diagnosticHolder.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_NAMED_NATIVE.on(jsNamePsi)) trace.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_NAMED_NATIVE.on(jsNamePsi))
} }
if (descriptor is CallableMemberDescriptor && descriptor.overriddenDescriptors.isNotEmpty()) { if (descriptor is CallableMemberDescriptor && descriptor.overriddenDescriptors.isNotEmpty()) {
diagnosticHolder.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE.on(jsNamePsi)) trace.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE.on(jsNamePsi))
} }
when (descriptor) { when (descriptor) {
is ConstructorDescriptor -> { is ConstructorDescriptor -> {
if (descriptor.isPrimary) { if (descriptor.isPrimary) {
diagnosticHolder.report(ErrorsJs.JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED.on(jsNamePsi)) trace.report(ErrorsJs.JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED.on(jsNamePsi))
} }
} }
is PropertyAccessorDescriptor -> { is PropertyAccessorDescriptor -> {
if (AnnotationsUtils.getJsName(descriptor.correspondingProperty) != null) { if (AnnotationsUtils.getJsName(descriptor.correspondingProperty) != null) {
diagnosticHolder.report(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY.on(jsNamePsi)) trace.report(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY.on(jsNamePsi))
} }
} }
is PropertyDescriptor -> { is PropertyDescriptor -> {
if (descriptor.isExtension) { if (descriptor.isExtension) {
diagnosticHolder.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY.on(jsNamePsi)) trace.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY.on(jsNamePsi))
} }
} }
} }
@@ -25,12 +25,13 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils 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.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDeclarationChecker { class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : DeclarationChecker {
companion object { companion object {
private val COMMON_DIAGNOSTICS = setOf( private val COMMON_DIAGNOSTICS = setOf(
Errors.REDECLARATION, Errors.REDECLARATION,
@@ -42,16 +43,11 @@ class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDec
private val clashedFakeOverrides = mutableMapOf<DeclarationDescriptor, Pair<DeclarationDescriptor, DeclarationDescriptor>>() private val clashedFakeOverrides = mutableMapOf<DeclarationDescriptor, Pair<DeclarationDescriptor, DeclarationDescriptor>>()
private val clashedDescriptors = mutableSetOf<Pair<DeclarationDescriptor, String>>() private val clashedDescriptors = mutableSetOf<Pair<DeclarationDescriptor, String>>()
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
// We don't generate JS properties for extension properties, we generate methods instead, so in this case // We don't generate JS properties for extension properties, we generate methods instead, so in this case
// check name clash only for accessors, not properties // check name clash only for accessors, not properties
if (!descriptor.isExtensionProperty) { if (!descriptor.isExtensionProperty) {
checkDescriptor(descriptor, declaration, diagnosticHolder, bindingContext) checkDescriptor(descriptor, declaration, context.trace, context.trace.bindingContext)
} }
} }
@@ -16,26 +16,19 @@
package org.jetbrains.kotlin.js.resolve.diagnostics package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceElement
object JsRuntimeAnnotationChecker : SimpleDeclarationChecker { object JsRuntimeAnnotationChecker : DeclarationChecker {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
for ((annotationDescriptor, _) in descriptor.annotations.getAllAnnotations()) { for ((annotationDescriptor, _) in descriptor.annotations.getAllAnnotations()) {
val annotationClass = annotationDescriptor.annotationClass ?: continue val annotationClass = annotationDescriptor.annotationClass ?: continue
if (annotationClass.getAnnotationRetention() != KotlinRetention.RUNTIME) continue if (annotationClass.getAnnotationRetention() != KotlinRetention.RUNTIME) continue
@@ -43,10 +36,10 @@ object JsRuntimeAnnotationChecker : SimpleDeclarationChecker {
val annotationPsi = (annotationDescriptor.source as? PsiSourceElement)?.psi ?: declaration val annotationPsi = (annotationDescriptor.source as? PsiSourceElement)?.psi ?: declaration
if (descriptor is MemberDescriptor && descriptor.isEffectivelyExternal()) { if (descriptor is MemberDescriptor && descriptor.isEffectivelyExternal()) {
diagnosticHolder.report(ErrorsJs.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION.on(annotationPsi)) context.trace.report(ErrorsJs.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION.on(annotationPsi))
} }
else { else {
diagnosticHolder.report(ErrorsJs.RUNTIME_ANNOTATION_NOT_SUPPORTED.on(annotationPsi)) context.trace.report(ErrorsJs.RUNTIME_ANNOTATION_NOT_SUPPORTED.on(annotationPsi))
} }
} }
} }
@@ -26,23 +26,18 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils 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.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
internal abstract class AbstractNativeAnnotationsChecker(private val requiredAnnotation: PredefinedAnnotation) : SimpleDeclarationChecker { internal abstract class AbstractNativeAnnotationsChecker(private val requiredAnnotation: PredefinedAnnotation) : DeclarationChecker {
open fun additionalCheck(declaration: KtNamedFunction, descriptor: FunctionDescriptor, diagnosticHolder: DiagnosticSink) {} open fun additionalCheck(declaration: KtNamedFunction, descriptor: FunctionDescriptor, diagnosticHolder: DiagnosticSink) {}
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
val annotationDescriptor = descriptor.annotations.findAnnotation(requiredAnnotation.fqName) ?: return val annotationDescriptor = descriptor.annotations.findAnnotation(requiredAnnotation.fqName) ?: return
if (declaration !is KtNamedFunction || descriptor !is FunctionDescriptor) { if (declaration !is KtNamedFunction || descriptor !is FunctionDescriptor) {
@@ -55,10 +50,10 @@ internal abstract class AbstractNativeAnnotationsChecker(private val requiredAnn
if (isMember && (isExtension || !AnnotationsUtils.isNativeObject(descriptor)) || if (isMember && (isExtension || !AnnotationsUtils.isNativeObject(descriptor)) ||
!isMember && !isExtension !isMember && !isExtension
) { ) {
diagnosticHolder.report(ErrorsJs.NATIVE_ANNOTATIONS_ALLOWED_ONLY_ON_MEMBER_OR_EXTENSION_FUN.on(declaration, annotationDescriptor.type)) context.trace.report(ErrorsJs.NATIVE_ANNOTATIONS_ALLOWED_ONLY_ON_MEMBER_OR_EXTENSION_FUN.on(declaration, annotationDescriptor.type))
} }
additionalCheck(declaration, descriptor, diagnosticHolder) additionalCheck(declaration, descriptor, context.trace)
} }
} }
@@ -35,7 +35,8 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
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.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmFieldAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmFieldAnnotation
@@ -46,31 +47,27 @@ val ANDROID_PARCELABLE_CLASS_FQNAME = FqName("android.os.Parcelable")
val ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME = FqName("android.os.Parcelable.Creator") val ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME = FqName("android.os.Parcelable.Creator")
val ANDROID_PARCEL_CLASS_FQNAME = FqName("android.os.Parcel") val ANDROID_PARCEL_CLASS_FQNAME = FqName("android.os.Parcel")
class ParcelableDeclarationChecker : SimpleDeclarationChecker { class ParcelableDeclarationChecker : DeclarationChecker {
private companion object { private companion object {
private val IGNORED_ON_PARCEL_FQNAME = FqName(IgnoredOnParcel::class.java.canonicalName) private val IGNORED_ON_PARCEL_FQNAME = FqName(IgnoredOnParcel::class.java.canonicalName)
} }
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration, val trace = context.trace
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
when (descriptor) { when (descriptor) {
is ClassDescriptor -> checkParcelableClass(descriptor, declaration, diagnosticHolder, bindingContext) is ClassDescriptor -> checkParcelableClass(descriptor, declaration, trace, trace.bindingContext)
is SimpleFunctionDescriptor -> { is SimpleFunctionDescriptor -> {
val containingClass = descriptor.containingDeclaration as? ClassDescriptor val containingClass = descriptor.containingDeclaration as? ClassDescriptor
val ktFunction = declaration as? KtFunction val ktFunction = declaration as? KtFunction
if (containingClass != null && ktFunction != null) { if (containingClass != null && ktFunction != null) {
checkParcelableClassMethod(descriptor, containingClass, ktFunction, diagnosticHolder) checkParcelableClassMethod(descriptor, containingClass, ktFunction, trace)
} }
} }
is PropertyDescriptor -> { is PropertyDescriptor -> {
val containingClass = descriptor.containingDeclaration as? ClassDescriptor val containingClass = descriptor.containingDeclaration as? ClassDescriptor
val ktProperty = declaration as? KtProperty val ktProperty = declaration as? KtProperty
if (containingClass != null && ktProperty != null) { if (containingClass != null && ktProperty != null) {
checkParcelableClassProperty(descriptor, containingClass, ktProperty, diagnosticHolder, bindingContext) checkParcelableClassProperty(descriptor, containingClass, ktProperty, trace, trace.bindingContext)
} }
} }
} }
@@ -16,21 +16,18 @@
package org.jetbrains.kotlin.noarg.diagnostic package org.jetbrains.kotlin.noarg.diagnostic
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.reportFromPlugin import org.jetbrains.kotlin.diagnostics.reportFromPlugin
import org.jetbrains.kotlin.extensions.AnnotationBasedExtension import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.noarg.NO_ARG_CLASS_KEY import org.jetbrains.kotlin.noarg.NO_ARG_CLASS_KEY
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
@@ -39,14 +36,7 @@ class CliNoArgDeclarationChecker(val noArgAnnotationFqNames: List<String>) : Abs
} }
abstract class AbstractNoArgDeclarationChecker : DeclarationChecker, AnnotationBasedExtension { abstract class AbstractNoArgDeclarationChecker : DeclarationChecker, AnnotationBasedExtension {
override fun check( override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings,
expectActualTracker: ExpectActualTracker
) {
// Handle only classes // Handle only classes
if (descriptor !is ClassDescriptor || declaration !is KtClass) return if (descriptor !is ClassDescriptor || declaration !is KtClass) return
if (descriptor.kind != ClassKind.CLASS) return if (descriptor.kind != ClassKind.CLASS) return
@@ -57,7 +47,7 @@ abstract class AbstractNoArgDeclarationChecker : DeclarationChecker, AnnotationB
val superClass = descriptor.getSuperClassOrAny() val superClass = descriptor.getSuperClassOrAny()
if (superClass.constructors.none { it.isNoArgConstructor() } && !superClass.hasSpecialAnnotation(declaration)) { if (superClass.constructors.none { it.isNoArgConstructor() } && !superClass.hasSpecialAnnotation(declaration)) {
val reportTarget = declaration.nameIdentifier ?: declaration.getClassOrInterfaceKeyword() ?: declaration val reportTarget = declaration.nameIdentifier ?: declaration.getClassOrInterfaceKeyword() ?: declaration
diagnosticHolder.reportFromPlugin(ErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS.on(reportTarget), DefaultErrorMessagesNoArg) context.trace.reportFromPlugin(ErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS.on(reportTarget), DefaultErrorMessagesNoArg)
} }
} }
} }