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) } }