From 6ba32ed62475ac39332b6e8b0d53429a2be3f3b8 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 27 Jun 2016 16:36:29 +0300 Subject: [PATCH] Refactor CallChecker and subclasses Encapsulate everything that is needed in checkers into CallCheckerContext. Pass an instance of this context instead of BasicCallResolutionContext to checkers. Also pass an instance of the element to report errors on: this is useful because before this, every checker had its own way of determining where should the error be reported on. Some of them, for example, were not doing anything if Call#calleeExpression returned null, which is wrong, see operatorCall.kt #KT-12875 Open --- .../load/kotlin/JavaAnnotationCallChecker.kt | 28 ++++---- .../AdditionalBuiltInsMembersChecker.kt | 13 ++-- .../checkers/JavaClassOnCompanionChecker.kt | 11 +-- .../checkers/MissingDependencyClassChecker.kt | 11 +-- ...otectedInSuperClassCompanionCallChecker.kt | 11 +-- .../ProtectedSyntheticExtensionCallChecker.kt | 14 ++-- .../jvm/checkers/ReflectionAPICallChecker.kt | 11 +-- .../SuperCallWithDefaultArgumentsChecker.kt | 11 +-- .../checkers/TraitDefaultMethodCallChecker.kt | 19 ++---- ...portedSyntheticCallableReferenceChecker.kt | 13 ++-- .../resolve/jvm/diagnostics/ErrorsJvm.java | 9 ++- .../jetbrains/kotlin/diagnostics/Errors.java | 4 +- .../resolve/ConstructorHeaderCallChecker.kt | 28 ++++---- .../kotlin/resolve/calls/CallCompleter.kt | 11 +-- .../resolve/calls/checkers/CallChecker.kt | 35 +++++----- .../CallReturnsArrayOfNothingChecker.kt | 14 ++-- .../checkers/CapturingInClosureChecker.kt | 12 ++-- .../calls/checkers/InfixCallChecker.kt | 13 ++-- .../resolve/calls/checkers/InlineChecker.java | 68 +++++++++---------- .../calls/checkers/InlineCheckerWrapper.kt | 12 ++-- .../calls/checkers/InvokeConventionChecker.kt | 6 +- .../calls/checkers/OperatorCallChecker.kt | 18 ++--- .../ProtectedConstructorCallChecker.kt | 10 +-- ...ifiedTypeParameterSubstitutionChecker.java | 43 ++++-------- .../resolve/calls/checkers/SafeCallChecker.kt | 9 +-- .../calls/checkers/coroutineCallChecker.kt | 23 +++---- .../BasicExpressionTypingVisitor.java | 14 ++-- .../tests/defaultArguments/superCall.kt | 6 +- .../tests/j+k/differentFilename.kt | 2 +- .../diagnostics/tests/j+k/traitDefaultCall.kt | 2 +- .../headerCallChecker/operatorCall.kt | 13 ++++ .../headerCallChecker/operatorCall.txt | 18 +++++ .../testsWithStdLib/ArrayOfNothing.kt | 8 +-- .../CallCompanionProtectedNonStatic.kt | 12 ++-- .../reified/reifiedNothingSubstitution.kt | 4 +- .../checkers/DiagnosticsTestGenerated.java | 6 ++ .../js/resolve/diagnostics/JsCallChecker.kt | 9 +-- .../AndroidExtensionPropertiesCallChecker.kt | 17 ++--- 38 files changed, 278 insertions(+), 290 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.kt create mode 100644 compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationCallChecker.kt index 70c5fdfac48..8fd74f918ab 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/JavaAnnotationCallChecker.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.load.kotlin +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0 @@ -25,14 +26,14 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm -class JavaAnnotationCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class JavaAnnotationCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val resultingDescriptor = resolvedCall.resultingDescriptor.original if (resultingDescriptor !is JavaConstructorDescriptor || resultingDescriptor.containingDeclaration.kind != ClassKind.ANNOTATION_CLASS) return @@ -41,7 +42,7 @@ class JavaAnnotationCallChecker : SimpleCallChecker { reportDeprecatedJavaAnnotation(resolvedCall, context) } - private fun reportDeprecatedJavaAnnotation(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { + private fun reportDeprecatedJavaAnnotation(resolvedCall: ResolvedCall<*>, context: CallCheckerContext) { val annotationEntry = resolvedCall.call.callElement as? KtAnnotationEntry ?: return val type = context.trace.get(BindingContext.TYPE, annotationEntry.typeReference) ?: return JavaAnnotationMapper.javaToKotlinNameMap[type.constructor.declarationDescriptor?.let { DescriptorUtils.getFqNameSafe(it) }]?.let { @@ -49,25 +50,20 @@ class JavaAnnotationCallChecker : SimpleCallChecker { } } - private fun reportErrorsOnPositionedArguments(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { + private fun reportErrorsOnPositionedArguments(resolvedCall: ResolvedCall<*>, context: CallCheckerContext) { getJavaAnnotationCallValueArgumentsThatShouldBeNamed(resolvedCall).forEach { reportOnValueArgument(context, it, ErrorsJvm.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION) } } private fun reportOnValueArgument( - context: BasicCallResolutionContext, - argument: Map.Entry, + context: CallCheckerContext, + arguments: Map.Entry, diagnostic: DiagnosticFactory0 ) { - argument.value.arguments.forEach { - if (it.getArgumentExpression() != null) { - context.trace.report( - diagnostic.on( - it.getArgumentExpression()!! - ) - ) - } + for (valueArgument in arguments.value.arguments) { + val argumentExpression = valueArgument.getArgumentExpression() ?: continue + context.trace.report(diagnostic.on(argumentExpression)) } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/AdditionalBuiltInsMembersChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/AdditionalBuiltInsMembersChecker.kt index c8d2acd933e..905e6692796 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/AdditionalBuiltInsMembersChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/AdditionalBuiltInsMembersChecker.kt @@ -30,21 +30,16 @@ import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DeclarationChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker -import org.jetbrains.kotlin.resolve.calls.checkers.elementToReportOn -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence object AdditionalBuiltInsMembersCallChecker : CallChecker { - override fun check( - resolvedCall: ResolvedCall<*>, - context: BasicCallResolutionContext, - languageFeatureSettings: LanguageFeatureSettings - ) { - if (languageFeatureSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + if (context.languageFeatureSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return - reportErrorIfAdditionalBuiltinDescriptor(resultingDescriptor, context.trace, resolvedCall.elementToReportOn) + reportErrorIfAdditionalBuiltinDescriptor(resultingDescriptor, context.trace, reportOn) } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaClassOnCompanionChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaClassOnCompanionChecker.kt index defa5cab0d9..b4bc473cc26 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaClassOnCompanionChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaClassOnCompanionChecker.kt @@ -16,19 +16,20 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.TypeProjectionImpl -class JavaClassOnCompanionChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class JavaClassOnCompanionChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.resultingDescriptor if (descriptor !is PropertyDescriptor || descriptor.name.asString() != "javaClass") return @@ -45,7 +46,7 @@ class JavaClassOnCompanionChecker : SimpleCallChecker { val arguments = listOf(TypeProjectionImpl(containingClass.defaultType)) val expectedType = KotlinTypeFactory.simpleType(Annotations.EMPTY, javaLangClass.typeConstructor, arguments, actualType.isMarkedNullable) - context.trace.report(ErrorsJvm.JAVA_CLASS_ON_COMPANION.on(resolvedCall.call.callElement, actualType, expectedType)) + context.trace.report(ErrorsJvm.JAVA_CLASS_ON_COMPANION.on(reportOn, actualType, expectedType)) } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/MissingDependencyClassChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/MissingDependencyClassChecker.kt index 96528f46fc4..64c0b73afd1 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/MissingDependencyClassChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/MissingDependencyClassChecker.kt @@ -16,12 +16,13 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.checkers.isComputingDeferredType -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm @@ -29,10 +30,10 @@ import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize -class MissingDependencyClassChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class MissingDependencyClassChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { for (classId in collectNotFoundClasses(resolvedCall.resultingDescriptor)) { - context.trace.report(ErrorsJvm.MISSING_DEPENDENCY_CLASS.on(resolvedCall.call.callElement, classId.asSingleFqName())) + context.trace.report(ErrorsJvm.MISSING_DEPENDENCY_CLASS.on(reportOn, classId.asSingleFqName())) } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedInSuperClassCompanionCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedInSuperClassCompanionCallChecker.kt index f65df8d6da7..bbe3359d61a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedInSuperClassCompanionCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedInSuperClassCompanionCallChecker.kt @@ -16,18 +16,19 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm -class ProtectedInSuperClassCompanionCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class ProtectedInSuperClassCompanionCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val targetDescriptor = resolvedCall.resultingDescriptor.original // Protected non-JVM static if (targetDescriptor.visibility != Visibilities.PROTECTED) return @@ -42,7 +43,7 @@ class ProtectedInSuperClassCompanionCallChecker : SimpleCallChecker { if (!parentClassDescriptors.any { DescriptorUtils.isSubclass(it, companionOwnerDescriptor) }) return // Called not within the same companion object or its owner class if (companionDescriptor !in parentClassDescriptors && companionOwnerDescriptor !in parentClassDescriptors) { - context.trace.report(ErrorsJvm.SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC.on(resolvedCall.call.callElement)) + context.trace.report(ErrorsJvm.SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC.on(reportOn)) } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt index eba444166e3..0b4602b808b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt @@ -16,10 +16,11 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast @@ -27,8 +28,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor -object ProtectedSyntheticExtensionCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +object ProtectedSyntheticExtensionCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.resultingDescriptor val sourceFunction = when (descriptor) { @@ -46,10 +47,11 @@ object ProtectedSyntheticExtensionCallChecker : SimpleCallChecker { val receiverValue = resolvedCall.extensionReceiver as ReceiverValue val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getPredictableTypes( - DataFlowValueFactory.createDataFlowValue(receiverValue, context)) + DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor) + ) if (receiverTypes.none { Visibilities.isVisible(getReceiverValueWithSmartCast(null, it), sourceFunction, from) }) { - context.trace.report(Errors.INVISIBLE_MEMBER.on(resolvedCall.call.callElement, descriptor, descriptor.visibility, from)) + context.trace.report(Errors.INVISIBLE_MEMBER.on(reportOn, descriptor, descriptor.visibility, from)) } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ReflectionAPICallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ReflectionAPICallChecker.kt index e808eaaa2c9..98f0e645c70 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ReflectionAPICallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ReflectionAPICallChecker.kt @@ -16,13 +16,14 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies @@ -34,7 +35,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions * If there's no Kotlin reflection implementation found in the classpath, checks that there are no usages * of reflection API which will fail at runtime. */ -class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageManager: StorageManager) : SimpleCallChecker { +class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageManager: StorageManager) : CallChecker { private val isReflectionAvailable by storageManager.createLazyValue { module.findClassAcrossModuleDependencies(JvmAbi.REFLECTION_FACTORY_IMPL) != null } @@ -44,7 +45,7 @@ class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageMana setOf(reflectionTypes.kProperty0, reflectionTypes.kProperty1, reflectionTypes.kProperty2) } - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { if (isReflectionAvailable) return val descriptor = resolvedCall.resultingDescriptor @@ -63,6 +64,6 @@ class ReflectionAPICallChecker(private val module: ModuleDescriptor, storageMana kPropertyClasses.any { kProperty -> DescriptorUtils.isSubclass(containingClass, kProperty) } -> return } - context.trace.report(NO_REFLECTION_IN_CLASS_PATH.on(resolvedCall.getCall().getCallElement())) + context.trace.report(NO_REFLECTION_IN_CLASS_PATH.on(reportOn)) } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt index 90d73674892..0f8788ac84e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt @@ -16,17 +16,18 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression import org.jetbrains.kotlin.resolve.calls.callUtil.usesDefaultArguments -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm -class SuperCallWithDefaultArgumentsChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class SuperCallWithDefaultArgumentsChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val superCallExpression = getSuperCallExpression(resolvedCall.call) if (superCallExpression == null || !resolvedCall.usesDefaultArguments()) return - context.trace.report(ErrorsJvm.SUPER_CALL_WITH_DEFAULT_PARAMETERS.on(superCallExpression.parent, resolvedCall.resultingDescriptor.name.asString())) + context.trace.report(ErrorsJvm.SUPER_CALL_WITH_DEFAULT_PARAMETERS.on(reportOn, resolvedCall.resultingDescriptor.name.asString())) } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/TraitDefaultMethodCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/TraitDefaultMethodCallChecker.kt index 84152ef0739..cf6377811c9 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/TraitDefaultMethodCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/TraitDefaultMethodCallChecker.kt @@ -16,20 +16,18 @@ package org.jetbrains.kotlin.resolve.jvm.checkers -import com.intellij.psi.util.PsiTreeUtil +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor -import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm -class TraitDefaultMethodCallChecker : SimpleCallChecker { - - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class TraitDefaultMethodCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { if (getSuperCallExpression(resolvedCall.call) == null) return val targetDescriptor = resolvedCall.resultingDescriptor.original @@ -40,13 +38,8 @@ class TraitDefaultMethodCallChecker : SimpleCallChecker { val classifier = DescriptorUtils.getParentOfType(context.scope.ownerDescriptor, ClassifierDescriptor::class.java) if (classifier != null && DescriptorUtils.isInterface(classifier)) { - context.trace.report( - ErrorsJvm.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on( - PsiTreeUtil.getParentOfType(resolvedCall.call.callElement, KtExpression::class.java)!! - ) - ) + context.trace.report(ErrorsJvm.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn)) } } - } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt index eaa003456b1..a2ae3d5488b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/UnsupportedSyntheticCallableReferenceChecker.kt @@ -16,22 +16,23 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor -class UnsupportedSyntheticCallableReferenceChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { - val expression = context.call.callElement +class UnsupportedSyntheticCallableReferenceChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + val expression = resolvedCall.call.callElement if (expression !is KtNameReferenceExpression || expression.parent !is KtCallableReferenceExpression) return // TODO: support references to synthetic Java extension properties (KT-8575) if (resolvedCall.resultingDescriptor is SyntheticJavaPropertyDescriptor) { - context.trace.report(UNSUPPORTED.on(expression, "reference to the synthetic extension property for a Java get/set method")) + context.trace.report(UNSUPPORTED.on(reportOn, "reference to the synthetic extension property for a Java get/set method")) } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index f325333ab09..282e8571588 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.KtAnnotationEntry; import org.jetbrains.kotlin.psi.KtDeclaration; -import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.types.KotlinType; @@ -74,12 +73,12 @@ public interface ErrorsJvm { DiagnosticFactory0 NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES = DiagnosticFactory1.create(ERROR); - DiagnosticFactory0 INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory0.create(WARNING); - DiagnosticFactory2 JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING); + DiagnosticFactory2 JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING); DiagnosticFactory2 JAVA_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR); DiagnosticFactory2 DUPLICATE_CLASS_NAMES = DiagnosticFactory2.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index dbcdaddbcc4..017a83a7506 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -75,7 +75,7 @@ public interface Errors { DiagnosticFactory3.create(ERROR); DiagnosticFactory3 INVISIBLE_MEMBER = DiagnosticFactory3.create(ERROR, CALL_ELEMENT); - DiagnosticFactory1 PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL = DiagnosticFactory1.create(ERROR); // Exposed visibility group DiagnosticFactory3 EXPOSED_PROPERTY_TYPE = DiagnosticFactory3.create(ERROR); @@ -812,7 +812,7 @@ public interface Errors { DiagnosticFactory0 INLINE_PROPERTY_WITH_BACKING_FIELD = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); - DiagnosticFactory0 NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR); // Error sets diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ConstructorHeaderCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ConstructorHeaderCallChecker.kt index 07c94a965fb..063f4209652 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ConstructorHeaderCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ConstructorHeaderCallChecker.kt @@ -16,12 +16,13 @@ package org.jetbrains.kotlin.resolve +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtInstanceExpressionWithLabel -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind @@ -29,26 +30,27 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf -object ConstructorHeaderCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +object ConstructorHeaderCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val dispatchReceiverClass = resolvedCall.dispatchReceiver.classDescriptorForImplicitReceiver val extensionReceiverClass = resolvedCall.extensionReceiver.classDescriptorForImplicitReceiver + val callElement = resolvedCall.call.callElement val labelReferenceClass = - (resolvedCall.call.callElement as? KtInstanceExpressionWithLabel)?.let { - instanceExpressionWithLabel -> - context.trace.get(BindingContext.REFERENCE_TARGET, instanceExpressionWithLabel.instanceReference) as? ClassDescriptor + if (callElement is KtInstanceExpressionWithLabel) { + context.trace.get(BindingContext.REFERENCE_TARGET, callElement.instanceReference) as? ClassDescriptor } + else null if (dispatchReceiverClass == null && extensionReceiverClass == null && labelReferenceClass == null) return - if (context.scope.parentsWithSelf.any() { - it is LexicalScope && it.kind == LexicalScopeKind.CONSTRUCTOR_HEADER - && (it.ownerDescriptor as ConstructorDescriptor).containingDeclaration in - setOf(dispatchReceiverClass, extensionReceiverClass, labelReferenceClass) + val classes = setOf(dispatchReceiverClass, extensionReceiverClass, labelReferenceClass) + + if (context.scope.parentsWithSelf.any { scope -> + scope is LexicalScope && scope.kind == LexicalScopeKind.CONSTRUCTOR_HEADER && + (scope.ownerDescriptor as ConstructorDescriptor).containingDeclaration in classes }) { - context.trace.report( - Errors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(context.call.calleeExpression ?: return, resolvedCall.resultingDescriptor)) + context.trace.report(Errors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(reportOn, resolvedCall.resultingDescriptor)) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index f69b460155d..0e7a82cbbc0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode. import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext import org.jetbrains.kotlin.resolve.calls.context.CallPosition @@ -83,14 +84,16 @@ class CallCompleter( } if (resolvedCall != null) { - for (callChecker in callCheckers) { - callChecker.check(resolvedCall, context, languageFeatureSettings) - } - val element = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.variableCall.call.calleeExpression else resolvedCall.call.calleeExpression + val reportOn = element ?: resolvedCall.call.callElement + + val callCheckerContext = CallCheckerContext(context, languageFeatureSettings) + for (callChecker in callCheckers) { + callChecker.check(resolvedCall, reportOn, callCheckerContext) + } for (validator in symbolUsageValidators) { validator.validateCall(resolvedCall, context.trace, element!!) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt index be9525adcbb..e14e6abb1b8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt @@ -16,30 +16,30 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.LanguageFeatureSettings -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo +import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.types.DeferredType import org.jetbrains.kotlin.types.KotlinType interface CallChecker { - // TODO: Think about encapsulating these parameters into specific class like CheckerParameters when you're about to add another one - fun check( - resolvedCall: ResolvedCall<*>, - context: BasicCallResolutionContext, - languageFeatureSettings: LanguageFeatureSettings - ) + fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) } -interface SimpleCallChecker : CallChecker { - override fun check( - resolvedCall: ResolvedCall<*>, - context: BasicCallResolutionContext, - languageFeatureSettings: LanguageFeatureSettings - ) = check(resolvedCall, context) - - fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) +class CallCheckerContext( + val trace: BindingTrace, + val scope: LexicalScope, + val languageFeatureSettings: LanguageFeatureSettings, + val dataFlowInfo: DataFlowInfo, + val isAnnotationContext: Boolean +) { + constructor(c: ResolutionContext<*>, languageFeatureSettings: LanguageFeatureSettings) : this( + c.trace, c.scope, languageFeatureSettings, c.dataFlowInfo, c.isAnnotationContext + ) } // Use this utility to avoid premature computation of deferred return type of a resolved callable descriptor. @@ -48,6 +48,3 @@ interface SimpleCallChecker : CallChecker { @Suppress("unused") fun CallChecker.isComputingDeferredType(type: KotlinType) = type is DeferredType && type.isComputing - -val ResolvedCall<*>.elementToReportOn: KtElement - get() = call.calleeExpression ?: call.callElement diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallReturnsArrayOfNothingChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallReturnsArrayOfNothingChecker.kt index 2767e4579fb..7aa767d82d1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallReturnsArrayOfNothingChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallReturnsArrayOfNothingChecker.kt @@ -16,20 +16,16 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing -class CallReturnsArrayOfNothingChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { - val returnType = resolvedCall.resultingDescriptor.returnType - - if (returnType.containsArrayOfNothing()) { - val callElement = resolvedCall.call.callElement - val diagnostic = Errors.UNSUPPORTED.on(callElement, "Array in return type is illegal") - context.trace.report(diagnostic) +class CallReturnsArrayOfNothingChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + if (resolvedCall.resultingDescriptor.returnType.containsArrayOfNothing()) { + context.trace.report(Errors.UNSUPPORTED.on(reportOn, "Array in return type is illegal")) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt index 7e0ba0f7ed3..ab1571240d6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt @@ -16,21 +16,21 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext.CAPTURED_IN_CLOSURE import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.types.expressions.CaptureKind -class CapturingInClosureChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class CapturingInClosureChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val variableResolvedCall = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.variableCall else resolvedCall val variableDescriptor = variableResolvedCall.resultingDescriptor as? VariableDescriptor if (variableDescriptor != null) { @@ -68,9 +68,9 @@ class CapturingInClosureChecker : SimpleCallChecker { if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return false if (InlineUtil.isInlinedArgument(scopeDeclaration as KtFunction, context, false)) { - val scopeContainerParent = scopeContainer.containingDeclaration - assert(scopeContainerParent != null) { "parent is null for " + scopeContainer } - return !isCapturedVariable(variableParent, scopeContainerParent!!) || isCapturedInInline(context, scopeContainerParent, variableParent) + val scopeContainerParent = scopeContainer.containingDeclaration ?: error("parent is null for $scopeContainer") + return !isCapturedVariable(variableParent, scopeContainerParent) || + isCapturedInInline(context, scopeContainerParent, variableParent) } return false } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InfixCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InfixCallChecker.kt index c1d013b5736..a29533441ad 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InfixCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InfixCallChecker.kt @@ -17,12 +17,10 @@ package org.jetbrains.kotlin.resolve.calls.checkers import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.config.LanguageFeatureSettings import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtOperationReferenceExpression -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic @@ -30,14 +28,15 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.types.ErrorUtils class InfixCallChecker : CallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext, languageFeatureSettings: LanguageFeatureSettings) { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val functionDescriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return - if (functionDescriptor.isDynamic() || ErrorUtils.isError(functionDescriptor)) return + if (functionDescriptor.isInfix || functionDescriptor.isDynamic() || ErrorUtils.isError(functionDescriptor)) return val element = ((resolvedCall as? VariableAsFunctionResolvedCall)?.variableCall ?: resolvedCall).call.calleeExpression - if (isInfixCall(element) && !functionDescriptor.isInfix) { - val operationRefExpression = element as? KtOperationReferenceExpression ?: return + if (isInfixCall(element)) { val containingDeclarationName = functionDescriptor.containingDeclaration.fqNameUnsafe.asString() - context.trace.report(Errors.INFIX_MODIFIER_REQUIRED.on(operationRefExpression, functionDescriptor, containingDeclarationName)) + context.trace.report(Errors.INFIX_MODIFIER_REQUIRED.on( + reportOn as? KtOperationReferenceExpression ?: return, functionDescriptor, containingDeclarationName + )) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java index 55e64dfb689..e4f766a9022 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java @@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.FunctionTypesKt; -import org.jetbrains.kotlin.config.LanguageFeatureSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.lexer.KtToken; @@ -28,7 +27,6 @@ import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; @@ -49,7 +47,7 @@ import static org.jetbrains.kotlin.diagnostics.Errors.USAGE_IS_NOT_INLINABLE; import static org.jetbrains.kotlin.resolve.inline.InlineUtil.allowsNonLocalReturns; import static org.jetbrains.kotlin.resolve.inline.InlineUtil.checkNonLocalReturnUsage; -class InlineChecker implements SimpleCallChecker { +class InlineChecker implements CallChecker { private final FunctionDescriptor descriptor; private final Set inlinableParameters = new LinkedHashSet(); private final boolean isEffectivelyPublicApiFunction; @@ -68,17 +66,8 @@ class InlineChecker implements SimpleCallChecker { } @Override - public void check( - @NotNull ResolvedCall resolvedCall, - @NotNull BasicCallResolutionContext context, - @NotNull LanguageFeatureSettings languageFeatureSettings - ) { - SimpleCallChecker.DefaultImpls.check(this, resolvedCall, context, languageFeatureSettings); - } - - @Override - public void check(@NotNull ResolvedCall resolvedCall, @NotNull BasicCallResolutionContext context) { - KtExpression expression = context.call.getCalleeExpression(); + public void check(@NotNull ResolvedCall resolvedCall, @NotNull PsiElement reportOn, @NotNull CallCheckerContext context) { + KtExpression expression = resolvedCall.getCall().getCalleeExpression(); if (expression == null) { return; } @@ -90,7 +79,7 @@ class InlineChecker implements SimpleCallChecker { if (inlinableParameters.contains(targetDescriptor)) { if (!isInsideCall(expression)) { - context.trace.report(USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor)); + context.getTrace().report(USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor)); } } @@ -133,10 +122,8 @@ class InlineChecker implements SimpleCallChecker { return parent != null; } - - private void checkValueParameter( - @NotNull BasicCallResolutionContext context, + @NotNull CallCheckerContext context, @NotNull CallableDescriptor targetDescriptor, @NotNull ValueArgument targetArgument, @NotNull ValueParameterDescriptor targetParameterDescriptor @@ -150,20 +137,20 @@ class InlineChecker implements SimpleCallChecker { if (argumentCallee != null && inlinableParameters.contains(argumentCallee)) { if (InlineUtil.isInline(targetDescriptor) && isInlinableParameter(targetParameterDescriptor)) { if (allowsNonLocalReturns(argumentCallee) && !allowsNonLocalReturns(targetParameterDescriptor)) { - context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression)); + context.getTrace().report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression)); } else { checkNonLocalReturn(context, argumentCallee, argumentExpression); } } else { - context.trace.report(USAGE_IS_NOT_INLINABLE.on(argumentExpression, argumentExpression, descriptor)); + context.getTrace().report(USAGE_IS_NOT_INLINABLE.on(argumentExpression, argumentExpression, descriptor)); } } } private void checkCallWithReceiver( - @NotNull BasicCallResolutionContext context, + @NotNull CallCheckerContext context, @NotNull CallableDescriptor targetDescriptor, @Nullable ReceiverValue receiver, @Nullable KtExpression expression @@ -194,13 +181,13 @@ class InlineChecker implements SimpleCallChecker { @Nullable private static CallableDescriptor getCalleeDescriptor( - @NotNull BasicCallResolutionContext context, + @NotNull CallCheckerContext context, @NotNull KtExpression expression, boolean unwrapVariableAsFunction ) { if (!(expression instanceof KtSimpleNameExpression || expression instanceof KtThisExpression)) return null; - ResolvedCall thisCall = CallUtilKt.getResolvedCall(expression, context.trace.getBindingContext()); + ResolvedCall thisCall = CallUtilKt.getResolvedCall(expression, context.getTrace().getBindingContext()); if (unwrapVariableAsFunction && thisCall instanceof VariableAsFunctionResolvedCall) { return ((VariableAsFunctionResolvedCall) thisCall).getVariableCall().getResultingDescriptor(); } @@ -208,27 +195,27 @@ class InlineChecker implements SimpleCallChecker { } private void checkLambdaInvokeOrExtensionCall( - @NotNull BasicCallResolutionContext context, + @NotNull CallCheckerContext context, @NotNull CallableDescriptor lambdaDescriptor, @NotNull CallableDescriptor callDescriptor, @NotNull KtExpression receiverExpression ) { boolean inlinableCall = isInvokeOrInlineExtension(callDescriptor); if (!inlinableCall) { - context.trace.report(USAGE_IS_NOT_INLINABLE.on(receiverExpression, receiverExpression, descriptor)); + context.getTrace().report(USAGE_IS_NOT_INLINABLE.on(receiverExpression, receiverExpression, descriptor)); } else { checkNonLocalReturn(context, lambdaDescriptor, receiverExpression); } } - public void checkRecursion( - @NotNull BasicCallResolutionContext context, + private void checkRecursion( + @NotNull CallCheckerContext context, @NotNull CallableDescriptor targetDescriptor, @NotNull KtElement expression ) { if (targetDescriptor.getOriginal() == descriptor) { - context.trace.report(Errors.RECURSION_IN_INLINE.on(expression, expression, descriptor)); + context.getTrace().report(Errors.RECURSION_IN_INLINE.on(expression, expression, descriptor)); } } @@ -250,10 +237,17 @@ class InlineChecker implements SimpleCallChecker { return isInvoke || InlineUtil.isInline(descriptor); } - private void checkVisibilityAndAccess(@NotNull CallableDescriptor declarationDescriptor, @NotNull KtElement expression, @NotNull BasicCallResolutionContext context){ - boolean declarationDescriptorIsPublicApi = DescriptorUtilsKt.isEffectivelyPublicApi(declarationDescriptor) || isDefinedInInlineFunction(declarationDescriptor); - if (isEffectivelyPublicApiFunction && !declarationDescriptorIsPublicApi && declarationDescriptor.getVisibility() != Visibilities.LOCAL) { - context.trace.report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor)); + private void checkVisibilityAndAccess( + @NotNull CallableDescriptor declarationDescriptor, + @NotNull KtElement expression, + @NotNull CallCheckerContext context + ) { + boolean declarationDescriptorIsPublicApi = DescriptorUtilsKt.isEffectivelyPublicApi(declarationDescriptor) || + isDefinedInInlineFunction(declarationDescriptor); + if (isEffectivelyPublicApiFunction && + !declarationDescriptorIsPublicApi && + declarationDescriptor.getVisibility() != Visibilities.LOCAL) { + context.getTrace().report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor)); } else { checkPrivateClassMemberAccess(declarationDescriptor, expression, context); @@ -263,11 +257,11 @@ class InlineChecker implements SimpleCallChecker { private void checkPrivateClassMemberAccess( @NotNull DeclarationDescriptor declarationDescriptor, @NotNull KtElement expression, - @NotNull BasicCallResolutionContext context + @NotNull CallCheckerContext context ) { if (!isEffectivelyPrivateApiFunction) { if (DescriptorUtilsKt.isInsidePrivateClass(declarationDescriptor)) { - context.trace.report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor)); + context.getTrace().report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor)); } } } @@ -285,14 +279,14 @@ class InlineChecker implements SimpleCallChecker { } private void checkNonLocalReturn( - @NotNull BasicCallResolutionContext context, + @NotNull CallCheckerContext context, @NotNull CallableDescriptor inlinableParameterDescriptor, @NotNull KtExpression parameterUsage ) { if (!allowsNonLocalReturns(inlinableParameterDescriptor)) return; - if (!checkNonLocalReturnUsage(descriptor, parameterUsage, context.trace)) { - context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(parameterUsage, parameterUsage)); + if (!checkNonLocalReturnUsage(descriptor, parameterUsage, context.getTrace())) { + context.getTrace().report(NON_LOCAL_RETURN_NOT_ALLOWED.on(parameterUsage, parameterUsage)); } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineCheckerWrapper.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineCheckerWrapper.kt index b6459fab3a6..70f5bb090ce 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineCheckerWrapper.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineCheckerWrapper.kt @@ -16,17 +16,17 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.inline.InlineUtil import java.lang.ref.WeakReference -class InlineCheckerWrapper : SimpleCallChecker { - private var checkersCache: WeakReference>? = null +class InlineCheckerWrapper : CallChecker { + private var checkersCache: WeakReference>? = null - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { if (context.isAnnotationContext) return var parentDescriptor: DeclarationDescriptor? = context.scope.ownerDescriptor @@ -34,14 +34,14 @@ class InlineCheckerWrapper : SimpleCallChecker { while (parentDescriptor != null) { if (InlineUtil.isInline(parentDescriptor)) { val checker = getChecker(parentDescriptor as FunctionDescriptor) - checker.check(resolvedCall, context) + checker.check(resolvedCall, reportOn, context) } parentDescriptor = parentDescriptor.containingDeclaration } } - private fun getChecker(descriptor: FunctionDescriptor): SimpleCallChecker { + private fun getChecker(descriptor: FunctionDescriptor): CallChecker { val map = checkersCache?.get() ?: hashMapOf() checkersCache = checkersCache ?: WeakReference(map) return map.getOrPut(descriptor) { InlineChecker(descriptor) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InvokeConventionChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InvokeConventionChecker.kt index 1ec18a240ee..57f06fd62d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InvokeConventionChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InvokeConventionChecker.kt @@ -16,15 +16,15 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver -class InvokeConventionChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class InvokeConventionChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { if (resolvedCall is VariableAsFunctionResolvedCallImpl) { val functionCall = resolvedCall.functionCall val variableCall = resolvedCall.variableCall diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt index 9a4b8147d1b..a028efbae40 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt @@ -17,14 +17,12 @@ package org.jetbrains.kotlin.resolve.calls.checkers import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.config.LanguageFeatureSettings import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic @@ -36,17 +34,13 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_MINUS import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_PLUS class OperatorCallChecker : CallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext, languageFeatureSettings: LanguageFeatureSettings) { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val functionDescriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return if (!checkNotErrorOrDynamic(functionDescriptor)) return val element = resolvedCall.call.calleeExpression ?: resolvedCall.call.callElement val call = resolvedCall.call - fun isInvokeCall(): Boolean = call is CallTransformer.CallForImplicitInvoke - - fun isMultiDeclaration(): Boolean = call.callElement is KtDestructuringDeclarationEntry - if (resolvedCall is VariableAsFunctionResolvedCall && call is CallTransformer.CallForImplicitInvoke && call.itIsVariableAsFunctionCall) { val outerCall = call.outerCall @@ -56,7 +50,7 @@ class OperatorCallChecker : CallChecker { } } - if (isMultiDeclaration() || isInvokeCall()) { + if (call.callElement is KtDestructuringDeclarationEntry || call is CallTransformer.CallForImplicitInvoke) { if (!functionDescriptor.isOperator) { report(call.callElement, functionDescriptor, context.trace) } @@ -66,7 +60,7 @@ class OperatorCallChecker : CallChecker { val isConventionOperator = element is KtOperationReferenceExpression && element.getNameForConventionalOperation() != null if (isConventionOperator || element is KtArrayAccessExpression) { if (!functionDescriptor.isOperator) { - report(element, functionDescriptor, context.trace) + report(reportOn, functionDescriptor, context.trace) } if (isConventionOperator) { checkDeprecatedUnaryConventions(call, functionDescriptor, context.trace) @@ -85,16 +79,16 @@ class OperatorCallChecker : CallChecker { } companion object { - fun report(element: PsiElement, descriptor: FunctionDescriptor, sink: DiagnosticSink) { + fun report(reportOn: PsiElement, descriptor: FunctionDescriptor, sink: DiagnosticSink) { if (!checkNotErrorOrDynamic(descriptor)) return val containingDeclaration = descriptor.containingDeclaration val containingDeclarationName = containingDeclaration.fqNameUnsafe.asString() - sink.report(Errors.OPERATOR_MODIFIER_REQUIRED.on(element, descriptor, containingDeclarationName)) + sink.report(Errors.OPERATOR_MODIFIER_REQUIRED.on(reportOn, descriptor, containingDeclarationName)) } private fun checkNotErrorOrDynamic(functionDescriptor: FunctionDescriptor): Boolean { - return (!functionDescriptor.isDynamic() && !ErrorUtils.isError(functionDescriptor)) + return !functionDescriptor.isDynamic() && !ErrorUtils.isError(functionDescriptor) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt index 7a4489b1602..f11edff30bd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt @@ -16,18 +16,18 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf -object ProtectedConstructorCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +object ProtectedConstructorCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.resultingDescriptor as? ConstructorDescriptor ?: return val constructorOwner = descriptor.containingDeclaration.original val scopeOwner = context.scope.ownerDescriptor @@ -36,7 +36,7 @@ object ProtectedConstructorCallChecker : SimpleCallChecker { // Error already reported if (!Visibilities.isVisibleWithAnyReceiver(descriptor, scopeOwner)) return - val calleeExpression = resolvedCall.call.calleeExpression ?: return + val calleeExpression = resolvedCall.call.calleeExpression // Permit constructor super-calls when (calleeExpression) { @@ -53,7 +53,7 @@ object ProtectedConstructorCallChecker : SimpleCallChecker { // of constructor owner @Suppress("DEPRECATION") if (Visibilities.findInvisibleMember(Visibilities.FALSE_IF_PROTECTED, descriptor, scopeOwner) == descriptor) { - context.trace.report(Errors.PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL.on(calleeExpression, descriptor)) + context.trace.report(Errors.PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL.on(reportOn, descriptor)) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java index c2124d56434..f8e3bbc9723 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java @@ -17,35 +17,24 @@ package org.jetbrains.kotlin.resolve.calls.checkers; import com.intellij.psi.PsiElement; +import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.config.LanguageFeatureSettings; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.diagnostics.Errors; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.KtExpression; -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; +import org.jetbrains.kotlin.psi.KtTypeProjection; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import java.util.Map; -public class ReifiedTypeParameterSubstitutionChecker implements SimpleCallChecker { +public class ReifiedTypeParameterSubstitutionChecker implements CallChecker { @Override - public void check( - @NotNull ResolvedCall resolvedCall, - @NotNull BasicCallResolutionContext context, - @NotNull LanguageFeatureSettings languageFeatureSettings - ) { - SimpleCallChecker.DefaultImpls.check(this, resolvedCall, context, languageFeatureSettings); - } - - @Override - public void check(@NotNull ResolvedCall resolvedCall, @NotNull BasicCallResolutionContext context) { + public void check(@NotNull ResolvedCall resolvedCall, @NotNull PsiElement reportOn, @NotNull CallCheckerContext context) { Map typeArguments = resolvedCall.getTypeArguments(); for (Map.Entry entry : typeArguments.entrySet()) { TypeParameterDescriptor parameter = entry.getKey(); @@ -56,42 +45,34 @@ public class ReifiedTypeParameterSubstitutionChecker implements SimpleCallChecke continue; } + KtTypeProjection typeProjection = CollectionsKt.getOrNull(resolvedCall.getCall().getTypeArguments(), parameter.getIndex()); + PsiElement reportErrorOn = typeProjection != null ? typeProjection : reportOn; + if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor && !((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) { - context.trace.report( - Errors.TYPE_PARAMETER_AS_REIFIED.on(getElementToReport(context, parameter.getIndex()), parameter) - ); + context.getTrace().report(Errors.TYPE_PARAMETER_AS_REIFIED.on(reportErrorOn, parameter)); } else if (TypeUtilsKt.cannotBeReified(argument)) { - context.trace.report( - Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument)); + context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument)); } // REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847) //else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) { - // context.trace.report( - // Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument)); + // context.getTrace().report(Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(reportErrorOn, argument)); //} } } + /* private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable"); private static boolean hasPureReifiableAnnotation(@NotNull TypeParameterDescriptor parameter) { return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME) || isTypeParameterOfKotlinArray(parameter); } + */ private static boolean isTypeParameterOfKotlinArray(@NotNull TypeParameterDescriptor parameter) { DeclarationDescriptor container = parameter.getContainingDeclaration(); return container instanceof ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray((ClassDescriptor) container); } - - @NotNull - private static PsiElement getElementToReport(@NotNull BasicCallResolutionContext context, int parameterIndex) { - if (context.call.getTypeArguments().size() > parameterIndex) { - return context.call.getTypeArguments().get(parameterIndex); - } - KtExpression callee = context.call.getCalleeExpression(); - return callee != null ? callee : context.call.getCallElement(); - } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/SafeCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/SafeCallChecker.kt index c06bcdf3a5c..c8252c84fd6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/SafeCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/SafeCallChecker.kt @@ -16,17 +16,18 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind -class SafeCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +class SafeCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val operationNode = resolvedCall.call.callOperationNode ?: return - if (operationNode.elementType == KtTokens.SAFE_ACCESS && resolvedCall.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER) { + if (operationNode.elementType == KtTokens.SAFE_ACCESS && + resolvedCall.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER) { context.trace.report(Errors.UNEXPECTED_SAFE_CALL.on(operationNode.psi)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt index b30dcb6537b..1c74bba1fb8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt @@ -16,18 +16,17 @@ package org.jetbrains.kotlin.resolve.calls.checkers +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageFeatureSettings import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue import org.jetbrains.kotlin.resolve.inline.InlineUtil -object CoroutineSuspendCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { +object CoroutineSuspendCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return if (!descriptor.isSuspend || descriptor.initialSignatureDescriptor == null) return @@ -35,23 +34,17 @@ object CoroutineSuspendCallChecker : SimpleCallChecker { val callElement = resolvedCall.call.callElement as KtExpression if (!InlineUtil.checkNonLocalReturnUsage(dispatchReceiverOwner, callElement, context.trace)) { - context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(resolvedCall.call.calleeExpression ?: callElement)) + context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(reportOn)) } } } object BuilderFunctionsCallChecker : CallChecker { - override fun check( - resolvedCall: ResolvedCall<*>, - context: BasicCallResolutionContext, - languageFeatureSettings: LanguageFeatureSettings - ) { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return - if (descriptor.valueParameters.any { it.isCoroutine } - && !languageFeatureSettings.supportsFeature(LanguageFeature.Coroutines)) { - context.trace.report( - Errors.UNSUPPORTED_FEATURE.on( - resolvedCall.call.calleeExpression ?: resolvedCall.call.callElement, LanguageFeature.Coroutines)) + if (descriptor.valueParameters.any { it.isCoroutine } && + !context.languageFeatureSettings.supportsFeature(LanguageFeature.Coroutines)) { + context.trace.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.Coroutines)) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 4dd3b07b7b2..106319eb77a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -39,8 +39,7 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver; import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver; import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker; -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; -import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode; +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext; import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl; @@ -586,10 +585,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { trace.record(RESOLVED_CALL, call, resolvedCall); trace.record(CALL, expression, call); - BasicCallResolutionContext resolutionContext = - BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE); + CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageFeatureSettings); for (CallChecker checker : components.callCheckers) { - checker.check(resolvedCall, resolutionContext, components.languageFeatureSettings); + checker.check(resolvedCall, expression, callCheckerContext); } for (SymbolUsageValidator validator : components.symbolUsageValidators) { validator.validateCall(resolvedCall, trace, expression); @@ -894,11 +892,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (resolvedCall != null) { // Call must be validated with the actual, not temporary trace in order to report operator diagnostic // Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace - BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create( - context.replaceBindingTrace(trace), resolvedCall.getCall(), CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS + CallCheckerContext callCheckerContext = new CallCheckerContext( + trace, context.scope, components.languageFeatureSettings, context.dataFlowInfo, context.isAnnotationContext ); for (CallChecker checker : components.callCheckers) { - checker.check(resolvedCall, callResolutionContext, components.languageFeatureSettings); + checker.check(resolvedCall, expression, callCheckerContext); } } } diff --git a/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt b/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt index 2ce8f15966f..d1c64d8efcb 100644 --- a/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt +++ b/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt @@ -13,13 +13,13 @@ abstract class A { open class B : A() { fun test() { super.foo("123") - super.foo() + super.foo() super.foo2("123") - super.foo2() + super.foo2() super.foo3("123") - super.foo3() + super.foo3() } override fun foo3(a: String) { diff --git a/compiler/testData/diagnostics/tests/j+k/differentFilename.kt b/compiler/testData/diagnostics/tests/j+k/differentFilename.kt index 5e01db67778..bcd78450d20 100644 --- a/compiler/testData/diagnostics/tests/j+k/differentFilename.kt +++ b/compiler/testData/diagnostics/tests/j+k/differentFilename.kt @@ -19,7 +19,7 @@ class F { // FILE: main.kt fun main(x: A) { x.b().bar() - x.f().foobaz() + x.f().foobaz() D().baz() } diff --git a/compiler/testData/diagnostics/tests/j+k/traitDefaultCall.kt b/compiler/testData/diagnostics/tests/j+k/traitDefaultCall.kt index 17060c15e0a..1c0f1eeec22 100644 --- a/compiler/testData/diagnostics/tests/j+k/traitDefaultCall.kt +++ b/compiler/testData/diagnostics/tests/j+k/traitDefaultCall.kt @@ -8,7 +8,7 @@ public interface Test { // FILE: test.kt interface KTrait : Test { fun ktest() { - super.test() + super.test() test() } diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.kt new file mode 100644 index 00000000000..ee44e12d707 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.kt @@ -0,0 +1,13 @@ +open class C(val x: Int) + +class D : C { + constructor() : super( + { + val s = "" + s() + ""() // TODO: see KT-12875 + 42 + }()) + + operator fun String.invoke() { } +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.txt new file mode 100644 index 00000000000..bbf1ca98059 --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.txt @@ -0,0 +1,18 @@ +package + +public open class C { + public constructor C(/*0*/ x: kotlin.Int) + public final val x: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class D : C { + public constructor D() + public final override /*1*/ /*fake_override*/ val x: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final operator fun kotlin.String.invoke(): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt b/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt index 20422b72462..9fe87c40e27 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt @@ -38,17 +38,17 @@ fun test4( ) {} fun test5() { - arrayOf<Nothing>() - Array<Nothing>(10) { throw Exception() } + arrayOf<Nothing>() + Array<Nothing>(10) { throw Exception() } } fun foo(): Array = (object {} as Any) as Array -fun test6() = foo() +fun test6() = foo() class B(val array: Array) fun bar() = B>(arrayOf()) -fun test7() = bar() +fun test7() = bar() diff --git a/compiler/testData/diagnostics/testsWithStdLib/CallCompanionProtectedNonStatic.kt b/compiler/testData/diagnostics/testsWithStdLib/CallCompanionProtectedNonStatic.kt index 2da2f08a17e..ac714408aac 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/CallCompanionProtectedNonStatic.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/CallCompanionProtectedNonStatic.kt @@ -44,24 +44,24 @@ class Derived : Base() { fun test() { foo() // Ok gav() // Ok - bar() - baz() + bar() + baz() } inner class DerivedInner { fun fromDerivedInner() { foo() // Ok gav() // Ok - bar() - baz() + bar() + baz() } } companion object { fun test2() { gav() // Ok - bar() - baz() + bar() + baz() } } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/reified/reifiedNothingSubstitution.kt b/compiler/testData/diagnostics/testsWithStdLib/reified/reifiedNothingSubstitution.kt index c16e6b28ba5..1354c9bb4b6 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/reified/reifiedNothingSubstitution.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/reified/reifiedNothingSubstitution.kt @@ -5,8 +5,8 @@ inline fun foo(block: () -> T): String = block().toString() inline fun javaClass(): Class = T::class.java fun box() { - val a = arrayOf(null!!) - val b = Array<Nothing?>(5) { null!! } + val a = arrayOf(null!!) + val b = Array<Nothing?>(5) { null!! } val c = foo() { null!! } val d = foo { null!! } val e = foo { "1" as Nothing } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 11cdd2a008b..7047a0f0999 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -16703,6 +16703,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("operatorCall.kt") + public void testOperatorCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/operatorCall.kt"); + doTest(fileName); + } + @TestMetadata("passingInstance.kt") public void testPassingInstance() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/headerCallChecker/passingInstance.kt"); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt index 07126f1c404..27fe7f788ae 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt @@ -24,6 +24,7 @@ import com.google.gwt.dev.js.rhino.CodePosition import com.google.gwt.dev.js.rhino.ErrorReporter import com.google.gwt.dev.js.rhino.Utils.isEndOfLine import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 @@ -36,8 +37,8 @@ import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry import org.jetbrains.kotlin.psi.KtStringTemplateExpression import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.TemporaryBindingTrace -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.StringValue @@ -47,7 +48,7 @@ import org.jetbrains.kotlin.types.TypeUtils class JsCallChecker( private val constantExpressionEvaluator: ConstantExpressionEvaluator -) : SimpleCallChecker { +) : CallChecker { companion object { private val JS_PATTERN: DescriptorPredicate = PatternBuilder.pattern("kotlin.js.js(String)") @@ -62,7 +63,7 @@ class JsCallChecker( } } - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { if (context.isAnnotationContext || !resolvedCall.isJsCall()) return val expression = resolvedCall.call.callElement diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecker.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecker.kt index b09407cb0d9..f2f80fca5cc 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecker.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecker.kt @@ -16,27 +16,28 @@ package org.jetbrains.kotlin.android.synthetic.diagnostic +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid.* import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.resolve.calls.checkers.SimpleCallChecker -import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -class AndroidExtensionPropertiesCallChecker : SimpleCallChecker { - override fun check(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { - val expression = context.call.calleeExpression ?: return +class AndroidExtensionPropertiesCallChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + reportOn as? KtExpression ?: return val propertyDescriptor = resolvedCall.resultingDescriptor as? PropertyDescriptor ?: return val containingPackage = propertyDescriptor.containingDeclaration as? AndroidSyntheticPackageFragmentDescriptor ?: return val androidSyntheticProperty = propertyDescriptor as? AndroidSyntheticProperty ?: return - with (context.trace) { - checkUnresolvedWidgetType(expression, androidSyntheticProperty) - checkDeprecated(expression, containingPackage) + with(context.trace) { + checkUnresolvedWidgetType(reportOn, androidSyntheticProperty) + checkDeprecated(reportOn, containingPackage) } }