From 36fd8a1a08ce0221b3898406e2be26c98c378b72 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Wed, 29 Oct 2014 15:08:30 +0300 Subject: [PATCH] Set the right call operation node for implicit invoke Make a call for implicit invoke safe if an outer call is safe --- .../jetbrains/jet/lang/psi/JetPsiUtil.java | 5 -- .../jet/lang/psi/psiUtil/jetPsiUtil.kt | 15 ++++- .../jet/lang/resolve/calls/CallResolver.java | 4 +- .../lang/resolve/calls/CallTransformer.java | 64 ++++++++++--------- .../lang/resolve/calls/CandidateResolver.java | 3 +- .../resolve/calls/model/ResolvedCallImpl.java | 9 +-- .../calls/tasks/ResolutionCandidate.java | 32 ++-------- .../calls/tasks/ResolutionTaskHolder.kt | 13 +--- .../BasicExpressionTypingVisitor.java | 2 +- .../ControlStructureTypingUtils.java | 2 +- .../tests/nullableTypes/safeCallWithInvoke.kt | 12 ++++ .../nullableTypes/safeCallWithInvoke.lazy.log | 57 +++++++++++++++++ .../nullableTypes/safeCallWithInvoke.txt | 20 ++++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 ++ 14 files changed, 162 insertions(+), 82 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.kt create mode 100644 compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.lazy.log create mode 100644 compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.txt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index a44600c29c2..560866233ad 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -336,11 +336,6 @@ public class JetPsiUtil { return KotlinBuiltIns.getInstance().getUnit().getName().asString().equals(typeReference.getText()); } - public static boolean isSafeCall(@NotNull Call call) { - ASTNode callOperationNode = call.getCallOperationNode(); - return callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS; - } - // SCRIPT: is declaration in script? public static boolean isScriptDeclaration(@NotNull JetDeclaration namedDeclaration) { return getScript(namedDeclaration) != null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/psiUtil/jetPsiUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/psi/psiUtil/jetPsiUtil.kt index 8ec3d374097..6a3dad45d4a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/psiUtil/jetPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/psiUtil/jetPsiUtil.kt @@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.types.expressions.OperatorConventions import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.PsiComment +import org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke public fun JetCallElement.getCallNameExpression(): JetSimpleNameExpression? { val calleeExpression = getCalleeExpression() @@ -377,4 +378,16 @@ public fun PsiElement.nextLeafSkipWhitespacesAndComments(): PsiElement? { } public fun JetExpression.isDotReceiver(): Boolean = - (getParent() as? JetDotQualifiedExpression)?.getReceiverExpression() == this \ No newline at end of file + (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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index a22df0cc91b..3c83a83d824 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -287,8 +287,8 @@ public class CallResolver { context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(context); } - List> candidates = ResolutionCandidate.convertCollection( - context.call, constructors, JetPsiUtil.isSafeCall(context.call)); + List> candidates = + ResolutionCandidate.convertCollection(context.call, constructors); prioritizedTasks = Collections.singletonList(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY } else if (calleeExpression != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java index 3ef59d6316d..262cc3b2ec2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java @@ -19,7 +19,9 @@ package org.jetbrains.jet.lang.resolve.calls; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; +import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; @@ -105,10 +107,17 @@ public class CallTransformer { boolean hasReceiver = candidate.getExtensionReceiver().exists(); Call variableCall = stripCallArguments(task.call); - ResolutionCandidate variableCandidate = getVariableCallCandidate(candidate, variableCall); + ResolutionCandidate variableCandidate = ResolutionCandidate.create( + variableCall, + candidate.getDescriptor(), + candidate.getDispatchReceiver(), + candidate.getExtensionReceiver(), + candidate.getExplicitReceiverKind() + ); if (!hasReceiver) { CallCandidateResolutionContext context = CallCandidateResolutionContext.create( - ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall); + ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), + task, candidateTrace, task.tracing, variableCall); return Collections.singleton(context); } CallCandidateResolutionContext contextWithReceiver = createContextWithChainedTrace( @@ -116,11 +125,11 @@ public class CallTransformer { Call variableCallWithoutReceiver = stripReceiver(variableCall); ResolutionCandidate candidateWithoutReceiver = ResolutionCandidate.create( - variableCandidate.getCall(), - variableCandidate.getDescriptor(), - variableCandidate.getDispatchReceiver(), + variableCallWithoutReceiver, + candidate.getDescriptor(), + candidate.getDispatchReceiver(), ReceiverValue.NO_RECEIVER, - ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false); + ExplicitReceiverKind.NO_EXPLICIT_RECEIVER); CallCandidateResolutionContext contextWithoutReceiver = createContextWithChainedTrace( candidateWithoutReceiver, variableCallWithoutReceiver, candidateTrace, task, variableCall.getExplicitReceiver()); @@ -137,20 +146,6 @@ public class CallTransformer { return CallCandidateResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call, receiverValue); } - @NotNull - private ResolutionCandidate getVariableCallCandidate( - @NotNull ResolutionCandidate candidate, - @NotNull Call variableCall - ) { - return ResolutionCandidate.create( - variableCall, - candidate.getDescriptor(), - candidate.getDispatchReceiver(), - candidate.getExtensionReceiver(), - candidate.getExplicitReceiverKind(), - candidate.isSafeCall()); - } - private Call stripCallArguments(@NotNull Call call) { return new DelegatingCall(call) { @Override @@ -194,6 +189,12 @@ public class CallTransformer { private Call stripReceiver(@NotNull Call variableCall) { return new DelegatingCall(variableCall) { + @Nullable + @Override + public ASTNode getCallOperationNode() { + return null; + } + @NotNull @Override public ReceiverValue getExplicitReceiver() { @@ -250,10 +251,10 @@ public class CallTransformer { }; public static class CallForImplicitInvoke extends DelegatingCall { - final Call outerCall; - final ReceiverValue explicitExtensionReceiver; - final ExpressionReceiver calleeExpressionAsDispatchReceiver; - final JetSimpleNameExpression fakeInvokeExpression; + private final Call outerCall; + private final ReceiverValue explicitExtensionReceiver; + private final ExpressionReceiver calleeExpressionAsDispatchReceiver; + private final JetSimpleNameExpression fakeInvokeExpression; public CallForImplicitInvoke( @NotNull ReceiverValue explicitExtensionReceiver, @@ -267,6 +268,15 @@ public class CallTransformer { this.fakeInvokeExpression = (JetSimpleNameExpression) JetPsiFactory(call.getCallElement()).createExpression( "invoke"); } + @Nullable + @Override + public ASTNode getCallOperationNode() { + // if an explicit receiver corresponds to the implicit invoke, there is a corresponding call operation node: + // a.b() or a?.b() (where b has an extension function type); + // otherwise it's implicit + return explicitExtensionReceiver.exists() ? super.getCallOperationNode() : null; + } + @NotNull @Override public ReceiverValue getExplicitReceiver() { @@ -284,12 +294,6 @@ public class CallTransformer { return fakeInvokeExpression; } - @NotNull - @Override - public JetElement getCallElement() { - return outerCall.getCallElement(); - } - @NotNull @Override public CallType getCallType() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index b6d8e00ac16..a600c3f686f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.context.*; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; @@ -583,7 +584,7 @@ public class CandidateResolver { D candidateDescriptor = candidateCall.getCandidateDescriptor(); if (TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) return SUCCESS; - boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall(); + boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && PsiUtilPackage.isExplicitSafeCall(candidateCall.getCall()); boolean isSubtypeBySmartCast = SmartCastUtils.isSubTypeBySmartCastIgnoringNullability( receiverArgument, receiverParameter.getType(), context); if (!isSubtypeBySmartCast) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/model/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/model/ResolvedCallImpl.java index 2a6c6628962..5a3653cb0d1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/model/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/model/ResolvedCallImpl.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.ValueArgument; +import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage; import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; @@ -37,7 +38,9 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeSubstitutor; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE; import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS; @@ -74,7 +77,6 @@ public class ResolvedCallImpl implements MutableRe private final ReceiverValue dispatchReceiver; // receiver object of a method private final ReceiverValue extensionReceiver; // receiver of an extension function private final ExplicitReceiverKind explicitReceiverKind; - private final boolean isSafeCall; private final Map typeArguments = Maps.newLinkedHashMap(); private final Map valueArguments = Maps.newLinkedHashMap(); @@ -99,7 +101,6 @@ public class ResolvedCallImpl implements MutableRe this.dispatchReceiver = candidate.getDispatchReceiver(); this.extensionReceiver = candidate.getExtensionReceiver(); this.explicitReceiverKind = candidate.getExplicitReceiverKind(); - this.isSafeCall = candidate.isSafeCall(); this.trace = trace; this.tracing = tracing; this.dataFlowInfoForArguments = dataFlowInfoForArguments; @@ -285,7 +286,7 @@ public class ResolvedCallImpl implements MutableRe @Override public boolean isSafeCall() { - return isSafeCall; + return PsiUtilPackage.isSafeCall(call); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionCandidate.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionCandidate.java index 904217f17e1..f4b3198c734 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionCandidate.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionCandidate.java @@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve.calls.tasks; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; @@ -34,36 +33,29 @@ public class ResolutionCandidate { private ReceiverValue dispatchReceiver; // receiver object of a method private ReceiverValue extensionReceiver; // receiver of an extension function private ExplicitReceiverKind explicitReceiverKind; - private Boolean isSafeCall; private ResolutionCandidate( @NotNull Call call, @NotNull D descriptor, @NotNull ReceiverValue dispatchReceiver, - @NotNull ReceiverValue extensionReceiver, @NotNull ExplicitReceiverKind explicitReceiverKind, @Nullable Boolean isSafeCall + @NotNull ReceiverValue extensionReceiver, @NotNull ExplicitReceiverKind explicitReceiverKind ) { this.call = call; this.candidateDescriptor = descriptor; this.dispatchReceiver = dispatchReceiver; this.extensionReceiver = extensionReceiver; this.explicitReceiverKind = explicitReceiverKind; - this.isSafeCall = isSafeCall; } - /*package*/ static ResolutionCandidate create(@NotNull Call call, @NotNull D descriptor) { - return new ResolutionCandidate(call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null); - } - - /* 'null' for isSafeCall parameter if it should be set later (with 'setSafeCall') */ public static ResolutionCandidate create( - @NotNull Call call, @NotNull D descriptor, @Nullable Boolean isSafeCall + @NotNull Call call, @NotNull D descriptor ) { - return new ResolutionCandidate(call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, isSafeCall); + return new ResolutionCandidate(call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER); } public static ResolutionCandidate create( @NotNull Call call, @NotNull D descriptor, @NotNull ReceiverValue dispatchReceiver, - @NotNull ReceiverValue receiverArgument, @NotNull ExplicitReceiverKind explicitReceiverKind, boolean isSafeCall + @NotNull ReceiverValue receiverArgument, @NotNull ExplicitReceiverKind explicitReceiverKind ) { - return new ResolutionCandidate(call, descriptor, dispatchReceiver, receiverArgument, explicitReceiverKind, isSafeCall); + return new ResolutionCandidate(call, descriptor, dispatchReceiver, receiverArgument, explicitReceiverKind); } public void setDispatchReceiver(@NotNull ReceiverValue dispatchReceiver) { @@ -105,25 +97,15 @@ public class ResolutionCandidate { @NotNull public static List> convertCollection( - @NotNull Call call, @NotNull Collection descriptors, boolean isSafeCall + @NotNull Call call, @NotNull Collection descriptors ) { List> result = Lists.newArrayList(); for (D descriptor : descriptors) { - result.add(create(call, descriptor, isSafeCall)); + result.add(create(call, descriptor)); } return result; } - public void setSafeCall(boolean safeCall) { - assert isSafeCall == null; - isSafeCall = safeCall; - } - - public boolean isSafeCall() { - assert isSafeCall != null; - return isSafeCall; - } - @Override public String toString() { return candidateDescriptor.toString(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTaskHolder.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTaskHolder.kt index d78c1469bf9..3b5dd56ce73 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTaskHolder.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTaskHolder.kt @@ -29,23 +29,12 @@ public class ResolutionTaskHolder( private val priorityProvider: ResolutionTaskHolder.PriorityProvider>, private val tracing: TracingStrategy ) { - private val isSafeCall = JetPsiUtil.isSafeCall(basicCallResolutionContext.call) - private val candidatesList = ArrayList<() -> Collection>>() private var internalTasks: List>? = null - public fun setIsSafeCall(candidates: Collection>): Collection> { - for (candidate in candidates) { - candidate.setSafeCall(isSafeCall) - } - return candidates - } - public fun addCandidates(lazyCandidates: () -> Collection>) { assertNotFinished() - candidatesList.add(storageManager.createLazyValue { - setIsSafeCall(lazyCandidates()).toReadOnlyList() - }) + candidatesList.add(storageManager.createLazyValue { lazyCandidates().toReadOnlyList() }) } public fun addCandidates(candidatesList: List>>) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 5665e91b13f..3b3de48d0b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -420,7 +420,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.emptyList()); ResolutionCandidate resolutionCandidate = ResolutionCandidate.create( - call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false); + call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER); ResolvedCallImpl resolvedCall = ResolvedCallImpl.create(resolutionCandidate, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java index 136c852cefd..813c43482cf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java @@ -72,7 +72,7 @@ public class ControlStructureTypingUtils { SimpleFunctionDescriptorImpl function = createFunctionDescriptorForSpecialConstruction( constructionName.toUpperCase(), argumentNames, isArgumentNullable); TracingStrategy tracing = createTracingForSpecialConstruction(call, constructionName); - ResolutionCandidate resolutionCandidate = ResolutionCandidate.create(call, function, null); + ResolutionCandidate resolutionCandidate = ResolutionCandidate.create(call, function); CallResolver callResolver = expressionTypingServices.getCallResolver(); OverloadResolutionResults results = callResolver.resolveCallWithKnownCandidate( call, tracing, context, resolutionCandidate, dataFlowInfoForArguments); diff --git a/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.kt b/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.kt new file mode 100644 index 00000000000..61b0274e6fc --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.kt @@ -0,0 +1,12 @@ +class A { + val b = B() +} +class B +fun B.invoke(i: Int) = i + +fun foo(i: Int) = i + +fun test(a: A?) { + a?.b(1) //should be no warning + foo(a?.b(1)) //no warning, only error +} diff --git a/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.lazy.log b/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.lazy.log new file mode 100644 index 00000000000..ef848cda1e9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.lazy.log @@ -0,0 +1,57 @@ +DescriptorResolver@0 { + = JetTypeImpl@1['Int'] + = JetTypeImpl@2['Int'] + = MutableClassDescriptor$1@3 +} + +LazyJavaPackageFragmentProvider@4 { + packageFragments('': FqName@5) = LazyJavaPackageFragment@6[''] + packageFragments('A': FqName@7) = null + packageFragments('B': FqName@8) = null + packageFragments('Int': FqName@9) = null + packageFragments('java': FqName@10) = LazyJavaPackageFragment@11['java'] + packageFragments('java.lang': FqName@12) = LazyJavaPackageFragment@13['lang'] + packageFragments('java.lang.A': FqName@14) = null + packageFragments('java.lang.B': FqName@15) = null + packageFragments('java.lang.Int': FqName@16) = null + packageFragments('kotlin': FqName@17) = null + packageFragments('kotlin.A': FqName@18) = null + packageFragments('kotlin.B': FqName@19) = null + packageFragments('kotlin.Int': FqName@20) = null + packageFragments('kotlin.io': FqName@21) = null + packageFragments('kotlin.jvm': FqName@22) = null +} + +LazyJavaPackageFragment@6[''] { + classes('B': Name@23) = null // through LazyPackageFragmentScopeForJavaPackage@24 + classes('Int': Name@25) = null // through LazyPackageFragmentScopeForJavaPackage@24 + classes('b': Name@26) = null // through LazyPackageFragmentScopeForJavaPackage@24 + classes('foo': Name@27) = null // through LazyPackageFragmentScopeForJavaPackage@24 + classes('invoke': Name@28) = null // through LazyPackageFragmentScopeForJavaPackage@24 + deserializedPackageScope = Empty@29 // through LazyPackageFragmentScopeForJavaPackage@24 + functions('B': Name@23) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@24 + functions('b': Name@26) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@24 + functions('foo': Name@27) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@24 + functions('invoke': Name@28) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@24 + memberIndex = computeMemberIndex$1@31 // through LazyPackageFragmentScopeForJavaPackage@24 +} + +LazyJavaPackageFragment@11['java'] { + classes('lang': Name@32) = null // through LazyPackageFragmentScopeForJavaPackage@33 + deserializedPackageScope = Empty@29 // through LazyPackageFragmentScopeForJavaPackage@33 + functions('lang': Name@34) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@33 + memberIndex = computeMemberIndex$1@35 // through LazyPackageFragmentScopeForJavaPackage@33 +} + +LazyJavaPackageFragment@13['lang'] { + classes('B': Name@23) = null // through LazyPackageFragmentScopeForJavaPackage@36 + classes('b': Name@26) = null // through LazyPackageFragmentScopeForJavaPackage@36 + classes('foo': Name@27) = null // through LazyPackageFragmentScopeForJavaPackage@36 + classes('invoke': Name@28) = null // through LazyPackageFragmentScopeForJavaPackage@36 + deserializedPackageScope = Empty@29 // through LazyPackageFragmentScopeForJavaPackage@36 + functions('B': Name@23) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + functions('b': Name@26) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + functions('foo': Name@27) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + functions('invoke': Name@28) = EmptyList@30[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + memberIndex = computeMemberIndex$1@37 // through LazyPackageFragmentScopeForJavaPackage@36 +} diff --git a/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.txt b/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.txt new file mode 100644 index 00000000000..ef36395941b --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.txt @@ -0,0 +1,20 @@ +package + +internal fun foo(/*0*/ i: kotlin.Int): kotlin.Int +internal fun test(/*0*/ a: A?): kotlin.Unit +internal fun B.invoke(/*0*/ i: kotlin.Int): kotlin.Int + +internal final class A { + public constructor A() + internal final val b: B + 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 +} + +internal final class B { + public constructor B() + 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 +} diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index a5b62f5546f..1f6a84db27e 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -7124,6 +7124,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("safeCallWithInvoke.kt") + public void testSafeCallWithInvoke() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.kt"); + doTest(fileName); + } + @TestMetadata("uselessElvis.kt") public void testUselessElvis() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt");