diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt index a1ea2ec133a..7146c3818d3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/jetPsiUtil.kt @@ -17,26 +17,25 @@ package org.jetbrains.kotlin.psi.psiUtil import com.intellij.extapi.psi.StubBasedPsiElementBase -import com.intellij.lang.ASTNode import com.intellij.openapi.util.TextRange -import com.intellij.psi.* -import com.intellij.psi.search.PsiSearchScopeUtil -import com.intellij.psi.search.SearchScope +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiParameter +import com.intellij.psi.PsiParameterList +import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.stubs.StubElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.JetNodeTypes -import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.lexer.JetTokens -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub -import org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull import java.util.ArrayList import java.util.Collections import kotlin.test.assertTrue +// NOTE: in this file we collect only Kotlin-specific methods working with PSI and not modifying it + public fun JetCallElement.getCallNameExpression(): JetSimpleNameExpression? { val calleeExpression = getCalleeExpression() ?: return null @@ -253,18 +252,6 @@ public fun JetExpression.getAssignmentByLHS(): JetBinaryExpression? { public fun JetExpression.isDotReceiver(): Boolean = (getParent() as? JetDotQualifiedExpression)?.getReceiverExpression() == this -public fun Call.isSafeCall(): Boolean { - if (this is CallForImplicitInvoke) { - //implicit safe 'invoke' - if (getOuterCall().isExplicitSafeCall()) { - return true - } - } - return isExplicitSafeCall() -} - -public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS - public fun JetStringTemplateExpression.getContentRange(): TextRange { val start = getNode().getFirstChildNode().getTextLength() val lastChild = getNode().getLastChildNode() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java index d5c004e802b..6fb3a4db9d3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java @@ -23,8 +23,8 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.resolve.*; +import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext; import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode; import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext; @@ -283,7 +283,7 @@ public class ArgumentTypeResolver { // For an unsafe call, we should not do it, // otherwise not-null will propagate to successive statements // Sample: x?.foo(x.bar()) // Inside foo call, x is not-nullable - if (PsiUtilPackage.isSafeCall(call)) { + if (CallUtilPackage.isSafeCall(call)) { initialDataFlowInfo = initialDataFlowInfo.disequate(receiverDataFlowValue, DataFlowValue.NULL); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java index 799d3bb1330..1b1e243dca2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.resolve.*; +import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.context.*; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl; @@ -637,7 +638,7 @@ public class CandidateResolver { D candidateDescriptor = candidateCall.getCandidateDescriptor(); if (TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) return SUCCESS; - boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && PsiUtilPackage.isExplicitSafeCall(candidateCall.getCall()); + boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && CallUtilPackage.isExplicitSafeCall(candidateCall.getCall()); boolean isSubtypeBySmartCast = SmartCastUtils.isSubTypeBySmartCastIgnoringNullability( receiverArgument, receiverParameter.getType(), context); if (!isSubtypeBySmartCast) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java index 8bd4d35b948..c2ecc238381 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java @@ -25,9 +25,9 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.psi.Call; import org.jetbrains.kotlin.psi.ValueArgument; -import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.resolve.DelegatingBindingTrace; import org.jetbrains.kotlin.resolve.calls.CallResolverUtil; +import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus; import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind; @@ -288,7 +288,7 @@ public class ResolvedCallImpl implements MutableRe @Override public boolean isSafeCall() { - return PsiUtilPackage.isSafeCall(call); + return CallUtilPackage.isSafeCall(call); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt index 25215d6ec3c..182444b7cca 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt @@ -20,15 +20,16 @@ import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext.CALL import org.jetbrains.kotlin.resolve.BindingContext.RESOLVED_CALL import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver +import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.model.* -import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.utils.sure // resolved call @@ -176,6 +177,18 @@ public fun JetExpression.getFunctionResolvedCallWithAssert(context: BindingConte assert(resolvedCall.getResultingDescriptor() is FunctionDescriptor) { "ResolvedCall for this expression must be ResolvedCall: ${this.getTextWithLocation()}" } - [suppress("UNCHECKED_CAST")] + @suppress("UNCHECKED_CAST") return resolvedCall as ResolvedCall } + +public fun Call.isSafeCall(): Boolean { + if (this is CallTransformer.CallForImplicitInvoke) { + //implicit safe 'invoke' + if (getOuterCall().isExplicitSafeCall()) { + return true + } + } + return isExplicitSafeCall() +} + +public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS \ No newline at end of file