More correct check for ResolvedCall status everywhere in the IDE + added assert into ResolvedCallImpl

This commit is contained in:
Valentin Kipyatkov
2015-09-28 21:28:55 +03:00
parent 110d53b4a6
commit 45748eb169
15 changed files with 42 additions and 27 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.types.ErrorUtils
public interface ArgumentMapping {
public fun isError(): Boolean
@@ -61,3 +62,7 @@ class ArgumentMatchImpl(override val valueParameter: ValueParameterDescriptor):
return newArgumentMatch
}
}
//TODO: temporary hack until status.isSuccess is not always correct
fun ResolvedCall<*>.isReallySuccess(): Boolean
= status.isSuccess && !ErrorUtils.isError(resultingDescriptor)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.calls.model;
import com.google.common.collect.Maps;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,6 +47,7 @@ import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMP
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableResolvedCall<D> {
private static final Logger LOG = Logger.getInstance(ResolvedCallImpl.class);
public static final Function<MutableResolvedCall<?>, CallableDescriptor> MAP_TO_CANDIDATE = new Function<MutableResolvedCall<?>, CallableDescriptor>() {
@Override
@@ -275,6 +277,9 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
public ArgumentMapping getArgumentMapping(@NotNull ValueArgument valueArgument) {
ArgumentMatch argumentMatch = argumentToParameterMap.get(valueArgument);
if (argumentMatch == null) {
if (ArgumentMappingKt.isReallySuccess(this)) {
LOG.error("ArgumentUnmapped for " + valueArgument + " in successfully resolved call: " + call.getCallElement().getText());
}
return ArgumentUnmapped.INSTANCE$;
}
return argumentMatch;
@@ -28,15 +28,15 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addToStdlib.constant
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.emptyOrSingletonList
import java.util.HashSet
import java.util.*
// Navigation element of the resolved reference
// For property accessor return enclosing property
@@ -168,7 +168,7 @@ public fun JetExpression.readWriteAccess(useResolveForReadWrite: Boolean): Refer
val bindingContext = assignment.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = assignment.getResolvedCall(bindingContext) ?: return ReferenceAccess.READ_WRITE
if (!resolvedCall.status.isSuccess) return ReferenceAccess.READ_WRITE
if (!resolvedCall.isReallySuccess()) return ReferenceAccess.READ_WRITE
return if (resolvedCall.resultingDescriptor.name in OperatorConventions.ASSIGNMENT_OPERATIONS.values())
ReferenceAccess.READ
else
@@ -32,9 +32,9 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import java.util.ArrayList
import java.util.HashMap
import java.util.*
public object OptionalParametersHelper {
public fun detectArgumentsToDropForDefaults(
@@ -42,7 +42,7 @@ public object OptionalParametersHelper {
project: Project,
canDrop: (ValueArgument) -> Boolean = { true }
): Collection<ValueArgument> {
if (!resolvedCall.getStatus().isSuccess()) return emptyList()
if (!resolvedCall.isReallySuccess()) return emptyList()
val descriptor = resolvedCall.getResultingDescriptor()
val parameterToDefaultValue = descriptor.getValueParameters()
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotatedAsHidden
import org.jetbrains.kotlin.resolve.scopes.FileScope
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
@@ -131,7 +132,7 @@ public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection()
when (this) {
is JetCallExpression -> {
val resolvedCall = getResolvedCall(analyze())
return resolvedCall != null && resolvedCall.status.isSuccess && resolvedCall.resultingDescriptor.original == getMethod.original
return resolvedCall != null && resolvedCall.isReallySuccess() && resolvedCall.resultingDescriptor.original == getMethod.original
}
is JetQualifiedExpression -> {
@@ -148,7 +149,7 @@ public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection()
is JetCallExpression -> {
if ((valueArguments.singleOrNull()?.getArgumentExpression() as? JetSimpleNameExpression)?.getReferencedNameAsName() != valueParameterName) return false
val resolvedCall = getResolvedCall(analyze())
return resolvedCall != null && resolvedCall.status.isSuccess && resolvedCall.resultingDescriptor.original == setMethod.original
return resolvedCall != null && resolvedCall.isReallySuccess() && resolvedCall.resultingDescriptor.original == setMethod.original
}
is JetQualifiedExpression -> {
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.utils.getFileScope
@@ -155,7 +156,7 @@ public class RedundantSamConstructorInspection : AbstractKotlinInspection() {
val bindingContext = functionCall.analyze(BodyResolveMode.PARTIAL)
val functionResolvedCall = functionCall.getResolvedCall(bindingContext) ?: return emptyList()
if (!functionResolvedCall.status.isSuccess) return emptyList()
if (!functionResolvedCall.isReallySuccess()) return emptyList()
val samConstructorCalls = functionCall.valueArguments.map {
(it.getArgumentExpression() as? JetCallExpression)
@@ -26,21 +26,21 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.quickfix.moveCaret
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import java.util.ArrayList
import org.jetbrains.kotlin.types.typeUtil.isUnit
import java.util.*
public class DeprecatedCallableAddReplaceWithInspection : IntentionBasedInspection<JetCallableDeclaration>(DeprecatedCallableAddReplaceWithIntention())
@@ -108,7 +108,7 @@ public class DeprecatedCallableAddReplaceWithIntention : JetSelfTargetingRangeIn
for (entry in getAnnotationEntries()) {
entry.analyze()
val resolvedCall = entry.getCalleeExpression().getResolvedCall(bindingContext) ?: continue
if (!resolvedCall.getStatus().isSuccess()) continue
if (!resolvedCall.isReallySuccess()) continue
// if (resolvedCall.getResultingDescriptor() != deprecatedConstructor) continue
//TODO
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -82,7 +83,7 @@ class UsePropertyAccessSyntaxIntention : JetSelfTargetingOffsetIndependentIntent
val resolutionFacade = callExpression.getResolutionFacade()
val bindingContext = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL)
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return null
if (!resolvedCall.getStatus().isSuccess()) return null
if (!resolvedCall.isReallySuccess()) return null
val function = resolvedCall.getResultingDescriptor() as? FunctionDescriptor ?: return null
val resolutionScope = callExpression.getResolutionScope(bindingContext, resolutionFacade)
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.types.expressions.OperatorConventions
public class ReplaceCallWithBinaryOperatorIntention : JetSelfTargetingRangeIntention<JetDotQualifiedExpression>(javaClass(), "Replace call with binary operator"), HighPriorityAction {
@@ -32,7 +33,7 @@ public class ReplaceCallWithBinaryOperatorIntention : JetSelfTargetingRangeInten
val operation = operation(element.calleeName) ?: return null
val resolvedCall = element.toResolvedCall() ?: return null
if (!resolvedCall.getStatus().isSuccess()) return null
if (!resolvedCall.isReallySuccess()) return null
if (resolvedCall.getCall().getTypeArgumentList() != null) return null
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
if ((resolvedCall.getArgumentMapping(argument) as ArgumentMatch).valueParameter.getIndex() != 0) return null
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.idea.intentions.*
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -31,7 +32,7 @@ public class ReplaceContainsIntention : JetSelfTargetingRangeIntention<JetDotQua
if (element.calleeName != OperatorConventions.CONTAINS.asString()) return null
val resolvedCall = element.toResolvedCall() ?: return null
if (!resolvedCall.getStatus().isSuccess()) return null
if (!resolvedCall.isReallySuccess()) return null
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
if ((resolvedCall.getArgumentMapping(argument) as ArgumentMatch).valueParameter.getIndex() != 0) return null
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetSecondaryConstructor
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
public class InsertDelegationCallQuickfix(val isThis: Boolean, element: JetSecondaryConstructor) : JetIntentionAction<JetSecondaryConstructor>(element) {
@@ -48,7 +49,7 @@ public class InsertDelegationCallQuickfix(val isThis: Boolean, element: JetSecon
val descriptor = element.resolveToDescriptor()
// if empty call is ok and it's resolved to another constructor, do not move caret
if (resolvedCall?.getStatus()?.isSuccess() ?: false && resolvedCall!!.getCandidateDescriptor().getOriginal() != descriptor) return
if (resolvedCall?.isReallySuccess() ?: false && resolvedCall!!.getCandidateDescriptor().getOriginal() != descriptor) return
val leftParOffset = newDelegationCall.getValueArgumentList()!!.getLeftParenthesis()!!.getTextOffset()
@@ -57,7 +57,7 @@ class CallableUsageReplacementStrategy(
override fun createReplacer(usage: JetSimpleNameExpression): (() -> JetElement)? {
val bindingContext = usage.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = usage.getResolvedCall(bindingContext) ?: return null
if (!resolvedCall.status.isSuccess) return null
if (!resolvedCall.isReallySuccess()) return null
return {
// copy replacement expression because it is modified by performCallReplacement
performCallReplacement(usage, bindingContext, resolvedCall, replacement.copy())
@@ -430,7 +430,7 @@ private fun introduceNamedArguments(result: JetExpression) {
for (callExpression in callsToProcess) {
val bindingContext = callExpression.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return
if (!resolvedCall.status.isSuccess) return
if (!resolvedCall.isReallySuccess()) return
val argumentsToMakeNamed = callExpression.valueArguments.dropWhile { !it[MAKE_ARGUMENT_NAMED_KEY] }
for (argument in argumentsToMakeNamed) {
@@ -549,7 +549,7 @@ private fun restoreFunctionLiteralArguments(expression: JetExpression) {
if (callExpression.functionLiteralArguments.isNotEmpty()) return
val resolvedCall = callExpression.getResolvedCall(callExpression.analyze(BodyResolveMode.PARTIAL)) ?: return
if (!resolvedCall.status.isSuccess) return
if (!resolvedCall.isReallySuccess()) return
val argumentMatch = resolvedCall.getArgumentMapping(argument) as ArgumentMatch
if (argumentMatch.valueParameter != resolvedCall.resultingDescriptor.valueParameters.last()) return
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
@@ -132,7 +133,7 @@ object ReplaceWithAnnotationAnalyzer {
}
val resolvedCall = expression.getResolvedCall(bindingContext)
if (resolvedCall != null && resolvedCall.status.isSuccess) {
if (resolvedCall != null && resolvedCall.isReallySuccess()) {
val receiver = if (resolvedCall.resultingDescriptor.isExtension)
resolvedCall.extensionReceiver
else
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
interface UsageReplacementStrategy {
@@ -47,7 +48,7 @@ interface UsageReplacementStrategy {
when (target) {
is CallableDescriptor -> {
val resolvedCall = element.getResolvedCall(bindingContext) ?: return null
if (!resolvedCall.status.isSuccess) return null
if (!resolvedCall.isReallySuccess()) return null
val replacement = ReplaceWithAnnotationAnalyzer.analyzeCallableReplacement(replaceWith, target, resolutionFacade) ?: return null
return CallableUsageReplacementStrategy(replacement)
}
@@ -45,10 +45,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch;
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
@@ -122,7 +119,7 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
private boolean shouldSkipUsage(JetCallElement element) {
// TODO: We probable need more clever processing of invalid calls, but for now default to Java-like behaviour
if (resolvedCall == null && !(element instanceof JetDelegatorToSuperCall)) return true;
if (resolvedCall != null && !resolvedCall.getStatus().isSuccess()) {
if (resolvedCall != null && !ArgumentMappingKt.isReallySuccess(resolvedCall)) {
// TODO: investigate why arguments are not recorded for enum constructor call
if (element instanceof JetDelegatorToSuperCall && element.getParent().getParent() instanceof JetEnumEntry) return false;
for (ValueArgument valueArgument : resolvedCall.getCall().getValueArguments()) {