Resolve invoke on any kind of expressions, not only on simple name expressions

This commit is contained in:
Svetlana Isakova
2014-02-04 19:07:06 +04:00
parent c7087d170e
commit a829da185d
31 changed files with 391 additions and 101 deletions
@@ -23,7 +23,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
@@ -38,8 +37,6 @@ import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler;
import org.jetbrains.jet.lang.resolve.calls.tasks.*;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall;
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.calls.util.JetFakeReference;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
@@ -48,7 +45,6 @@ import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lang.types.expressions.LabelResolver;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import javax.inject.Inject;
@@ -57,7 +53,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
@@ -285,31 +280,20 @@ public class CallResolver {
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
}
else if (calleeExpression != null) {
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
if (!KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(calleeType)) {
// checkTypesWithNoCallee(trace, scope, call);
if (!calleeType.isError()) {
context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
}
return checkArgumentTypesAndFail(context);
Call call = new CallTransformer.CallForImplicitInvoke(
context.call.getExplicitReceiver(), expressionReceiver, context.call);
TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call);
OverloadResolutionResults<FunctionDescriptor> invokeResults =
resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
if (invokeResults.isNothing() || invokeResults.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER) {
context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
}
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special("<for expression " + calleeExpression.getText() + ">"), calleeExpression);
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL,
Visibilities.LOCAL);
ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor, JetPsiUtil.isSafeCall(context.call));
resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
resolutionCandidate.setExplicitReceiverKind(ExplicitReceiverKind.RECEIVER_ARGUMENT);
// strictly speaking, this is a hack:
// we need to pass a reference, but there's no reference in the PSI,
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
functionReference = new JetFakeReference(calleeExpression);
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(
Collections.singleton(resolutionCandidate), functionReference, context));
return (OverloadResolutionResultsImpl<FunctionDescriptor>) invokeResults; //todo
}
else {
// checkTypesWithNoCallee(trace, scope, call);
@@ -486,7 +470,9 @@ public class CallResolver {
@NotNull TracingStrategy tracing
) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
if (context.call.getCallType() != Call.CallType.INVOKE) {
context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
}
context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
if (context.dataFlowInfo.hasTypeInfoConstraints()) {
@@ -39,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImp
import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategyForInvoke;
import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
@@ -205,8 +206,9 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
functionCall, context.checkArguments, context.dataFlowInfoForArguments);
// 'invoke' call resolve
TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, functionCall);
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallForInvoke(
basicCallResolutionContext, context.tracing); //todo context.tracing is incorrect
basicCallResolutionContext, tracingForInvoke);
Collection<ResolvedCallWithTrace<FunctionDescriptor>> calls = ((OverloadResolutionResultsImpl<FunctionDescriptor>)results).getResultingCalls();
return Collections2.transform(calls, new Function<ResolvedCallWithTrace<FunctionDescriptor>, ResolvedCallWithTrace<FunctionDescriptor>>() {
@@ -224,7 +226,7 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
final ExpressionReceiver calleeExpressionAsThisObject;
final JetSimpleNameExpression fakeInvokeExpression;
private CallForImplicitInvoke(
public CallForImplicitInvoke(
@NotNull ReceiverValue explicitExtensionReceiver,
@NotNull ExpressionReceiver calleeExpressionAsThisObject,
@NotNull Call call
@@ -256,14 +258,7 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
@NotNull
@Override
public PsiElement getCallElement() {
if (outerCall.getCallElement() instanceof JetCallElement) {
//to report errors properly
JetValueArgumentList list = ((JetCallElement)outerCall.getCallElement()).getValueArgumentList();
if (list != null) {
return list;
}
}
return fakeInvokeExpression;
return outerCall.getCallElement();
}
@NotNull
@@ -90,4 +90,9 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
return create(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
}
public BasicCallResolutionContext replaceCall(@NotNull Call newCall) {
return create(trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
}
}
@@ -100,7 +100,7 @@ public class ResolutionResultsCacheImpl implements ResolutionResultsCache {
@NotNull WritableSlice<CallKey, T> slice
) {
if (expression == null) return null;
for (CallType callType : Lists.newArrayList(DEFAULT, ARRAY_GET_METHOD, ARRAY_SET_METHOD)) {
for (CallType callType : Lists.newArrayList(DEFAULT, ARRAY_GET_METHOD, ARRAY_SET_METHOD, INVOKE)) {
CallKey callKey = CallKey.create(callType, expression);
T context = trace.get(slice, callKey);
if (context != null) {
@@ -46,7 +46,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
public abstract class AbstractTracingStrategy implements TracingStrategy {
private final JetExpression reference;
protected final JetExpression reference;
protected final Call call;
protected AbstractTracingStrategy(@NotNull JetExpression reference, @NotNull Call call) {
@@ -63,11 +63,6 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
}
@Override
public <D extends CallableDescriptor> void unresolvedReferenceWrongReceiver(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> candidates) {
trace.report(UNRESOLVED_REFERENCE_WRONG_RECEIVER.on(reference, candidates));
}
@Override
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
JetElement reportOn;
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls.tasks;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import java.util.Collection;
import static org.jetbrains.jet.lang.resolve.BindingContext.CALL;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
public class TracingStrategyForInvoke extends AbstractTracingStrategy {
public TracingStrategyForInvoke(
@NotNull JetExpression reference,
@NotNull Call call
) {
super(reference, call);
}
@Override
public <D extends CallableDescriptor> void bindReference(
@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall
) {
}
@Override
public <D extends CallableDescriptor> void bindResolvedCall(
@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall
) {
trace.record(RESOLVED_CALL, reference, resolvedCall);
trace.record(CALL, reference, call);
}
@Override
public void unresolvedReference(@NotNull BindingTrace trace) {
}
@Override
public <D extends CallableDescriptor> void unresolvedReferenceWrongReceiver(
@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> candidates
) {
}
}
@@ -26,7 +26,10 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.types.ErrorUtils;
import java.util.Collection;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
public class TracingStrategyImpl extends AbstractTracingStrategy {
@@ -64,4 +67,9 @@ public class TracingStrategyImpl extends AbstractTracingStrategy {
public void unresolvedReference(@NotNull BindingTrace trace) {
trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
}
@Override
public <D extends CallableDescriptor> void unresolvedReferenceWrongReceiver(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> candidates) {
trace.report(UNRESOLVED_REFERENCE_WRONG_RECEIVER.on(reference, candidates));
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls.util;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
/**
*
* This class is used to wrap an expression that occurs in a reference position, such as a function literal, into a reference expression
*/
public class JetFakeReference extends JetReferenceExpression {
private final JetElement actualElement;
public JetFakeReference(@NotNull JetElement actualElement) {
super(actualElement.getNode());
this.actualElement = actualElement;
}
public JetElement getActualElement() {
return actualElement;
}
}
@@ -14,11 +14,11 @@ L0:
r(11)
call(array[11], get)
r(3)
call(array[11], <for expression array[11]>)
call(array[11], invoke)
L1:
1 <END> NEXT:[<SINK>]
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -11,11 +11,11 @@ L0:
mark((f)())
mark((f))
r(f)
call((f), <for expression (f)>)
call((f), invoke)
L1:
1 <END> NEXT:[<SINK>]
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -7,12 +7,11 @@ L0:
1 <START>
2 mark({ this() })
mark(this())
r(this)
call(this, <for expression this>)
call(this, invoke)
L1:
1 <END> NEXT:[<SINK>]
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -0,0 +1,21 @@
class A
class B {
fun A.invoke() = "##"
fun A.invoke(i: Int) = "#${i}"
}
fun foo() = A()
fun B.test(): String {
if (A()() != "##") return "fail1"
if (A()(1) != "#1") return "fail2"
if (foo()() != "##") return "fail3"
if (foo()(42) != "#42") return "fail4"
if ((foo())(42) != "#42") return "fail5"
if ({() -> A()}()() != "##") return "fail6"
if ({() -> A()}()(37) != "#37") return "fail7"
return "OK"
}
fun box(): String = B().test()
@@ -0,0 +1,20 @@
//KT-3217 Invoke convention after function invocation doesn't work
//KT-2728 Can't compile A()()
class A {
fun invoke() = "##"
fun invoke(i: Int) = "#${i}"
}
fun foo() = A()
fun box(): String {
if (A()() != "##") return "fail1"
if (A()(1) != "#1") return "fail2"
if (foo()() != "##") return "fail3"
if (foo()(42) != "#42") return "fail4"
if ((foo())(42) != "#42") return "fail5"
if ({() -> A()}()() != "##") return "fail6"
if ({() -> A()}()(37) != "#37") return "fail7"
return "OK"
}
@@ -0,0 +1,13 @@
//KT-3450 get and invoke are not parsed in one expression
public class A(val s: String) {
public fun get(i: Int) : A = A("$s + $i")
public fun invoke(builder : A.() -> String): String = builder()
}
fun x(y : String) : A = A(y)
fun foo() = x("aaa")[42] { "$s!!" }
fun box() = if (foo() == "aaa + 42!!") "OK" else "fail"
@@ -0,0 +1,5 @@
//KT-3631 String.invoke doesn't work with literals
fun String.invoke(i: Int) = "$this$i"
fun box() = if ("a"(12) == "a12") "OK" else "fail"
@@ -0,0 +1,21 @@
//KT-3772 Invoke and overload resolution ambiguity
open class A {
fun invoke(f: A.() -> Unit) = 1
}
class B {
fun invoke(f: B.() -> Unit) = 2
}
open class C
val C.attr = A()
open class D: C()
val D.attr = B()
fun box(): String {
val d = D()
return if (d.attr {} == 2) "OK" else "fail"
}
@@ -0,0 +1,8 @@
//KT-3821 Invoke convention doesn't work for `this`
class A() {
fun invoke() = 42
fun foo() = this() // Expecting a function type, but found A
}
fun box() = if (A().foo() == 42) "OK" else "fail"
@@ -0,0 +1,9 @@
//KT-3822 Compiler crashes when use invoke convention with `this` in class which extends Function0<T>
class B() : Function0<Boolean> {
override fun invoke() = true
fun foo() = this() // Exception
}
fun box() = if (B().foo()) "OK" else "fail"
@@ -7,4 +7,4 @@ class Z{
}
}
// 2 invoke \(LZ;I\)V
// 1 invoke \(LZ;I\)V
@@ -2,4 +2,4 @@ fun test() {
1.{Int.() -> 2}()
}
// 2 invoke \(I\)I
// 1 invoke \(I\)I
@@ -0,0 +1,23 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
public class A {
public fun get(vararg attrs : Pair<String, String>) : A = this
}
fun String.plus() : A = A()
fun A.div(s : String) : A = A()
fun test() {
(+"node2" / "node3" / "zzz") ["attr" to "value", "a2" to "v2"]
}
//---------
class B {
public fun get(s : String, q : String) : B = this
public fun get(s : Pair<String, String>) : B = this
public fun invoke(q : B.() -> Unit) : B = this
}
val x = B()["a", "v"]["a" to "b"] {} ["q" to "p"] // does not parses around {}
//from library
data class Pair<out A, out B> (val first: A, val second: B)
fun <A,B> A.to(that: B) = Pair(this, that)
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun Int.invoke(i: Int, a: Any) {}
fun Int.invoke(a: Any, i: Int) {}
fun foo(i: Int) {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>i<!>(1, 1)
<!OVERLOAD_RESOLUTION_AMBIGUITY!>5<!>(1, 2)
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class My {
private fun Int.invoke(s: String) {}
}
fun My.foo(i: Int) {
<!INVISIBLE_MEMBER!>i<!>("")
<!INVISIBLE_MEMBER!>1<!>("")
}
@@ -0,0 +1,13 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T>
fun <T> T.invoke(a: A<T>) {}
fun foo(s: String, ai: A<Int>) {
1(ai)
<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>s<!>(ai)
<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>""<!>(ai)
}
@@ -0,0 +1,4 @@
fun foo(i: Int) {
<!FUNCTION_EXPECTED!>i<!>()
<!CALLEE_NOT_A_FUNCTION!>1<!>()
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun String.invoke(i: Int) {}
fun foo(s: String?) {
<!UNSAFE_CALL!>s<!>(1)
<!UNSAFE_CALL!>(s ?: null)<!>(1)
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun String.invoke(i: Int) {}
fun foo(i: Int) {
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>i<!>(1)
<!CALLEE_NOT_A_FUNCTION!>1<!>(1)
}
@@ -5081,6 +5081,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/kt1028.kt");
}
@TestMetadata("kt3450.kt")
public void testKt3450() throws Exception {
doTest("compiler/testData/diagnostics/tests/operatorsOverloading/kt3450.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/overload")
@@ -6041,6 +6046,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
}
@TestMetadata("compiler/testData/diagnostics/tests/resolve/invoke")
@InnerTestClasses({Invoke.Errors.class})
public static class Invoke extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInInvoke() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/resolve/invoke"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -6091,6 +6097,50 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/valNamedInvoke.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/resolve/invoke/errors")
public static class Errors extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInErrors() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/resolve/invoke/errors"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("ambiguityForInvoke.kt")
public void testAmbiguityForInvoke() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/errors/ambiguityForInvoke.kt");
}
@TestMetadata("invisibleInvoke.kt")
public void testInvisibleInvoke() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/errors/invisibleInvoke.kt");
}
@TestMetadata("typeInferenceErrorForInvoke.kt")
public void testTypeInferenceErrorForInvoke() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/errors/typeInferenceErrorForInvoke.kt");
}
@TestMetadata("unresolvedInvoke.kt")
public void testUnresolvedInvoke() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/errors/unresolvedInvoke.kt");
}
@TestMetadata("unsafeCallWithInvoke.kt")
public void testUnsafeCallWithInvoke() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/errors/unsafeCallWithInvoke.kt");
}
@TestMetadata("wrongReceiverTypeForInvoke.kt")
public void testWrongReceiverTypeForInvoke() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverTypeForInvoke.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Invoke");
suite.addTestSuite(Invoke.class);
suite.addTestSuite(Errors.class);
return suite;
}
}
@TestMetadata("compiler/testData/diagnostics/tests/resolve/nestedCalls")
@@ -6142,7 +6192,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
public static Test innerSuite() {
TestSuite suite = new TestSuite("Resolve");
suite.addTestSuite(Resolve.class);
suite.addTestSuite(Invoke.class);
suite.addTest(Invoke.innerSuite());
suite.addTestSuite(NestedCalls.class);
suite.addTestSuite(SpecialConstructions.class);
return suite;
@@ -2878,11 +2878,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/functions/invoke"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("extensionInvokeOnExpr.kt")
public void testExtensionInvokeOnExpr() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/extensionInvokeOnExpr.kt");
}
@TestMetadata("invoke.kt")
public void testInvoke() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/invoke.kt");
}
@TestMetadata("invokeOnExprByConvention.kt")
public void testInvokeOnExprByConvention() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/invokeOnExprByConvention.kt");
}
@TestMetadata("kt3189.kt")
public void testKt3189() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/kt3189.kt");
@@ -2898,6 +2908,31 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/functions/invoke/kt3297.kt");
}
@TestMetadata("kt3450getAndInvoke.kt")
public void testKt3450getAndInvoke() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/kt3450getAndInvoke.kt");
}
@TestMetadata("kt3631invokeOnString.kt")
public void testKt3631invokeOnString() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/kt3631invokeOnString.kt");
}
@TestMetadata("kt3772.kt")
public void testKt3772() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/kt3772.kt");
}
@TestMetadata("kt3821invokeOnThis.kt")
public void testKt3821invokeOnThis() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/kt3821invokeOnThis.kt");
}
@TestMetadata("kt3822invokeOnThis.kt")
public void testKt3822invokeOnThis() throws Exception {
doTest("compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/functions/localFunctions")
@@ -34,6 +34,7 @@ import java.io.File
import java.util.Collections
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall
public abstract class AbstractResolvedCallsTest() : JetLiteFixture() {
override fun createEnvironment(): JetCoreEnvironment = createEnvironmentWithMockJdk(ConfigurationKind.JDK_ONLY)
@@ -72,12 +73,22 @@ public abstract class AbstractResolvedCallsTest() : JetLiteFixture() {
var callFound = false
for ((element, resolvedCall) in analyzeFileAndGetResolvedCallEntries()) {
if (callName.equals(element.getText())) {
fun tryCall(resolvedCall: ResolvedCall<*>, actualName: String? = element.getText()) {
if (callName == null || callName != actualName) return
callFound = true
checkResolvedCall(resolvedCall, element)
}
if (resolvedCall is VariableAsFunctionResolvedCall) {
tryCall(resolvedCall.getFunctionCall(), "invoke")
tryCall(resolvedCall.getVariableCall())
}
else {
tryCall(resolvedCall)
}
}
assertTrue(callFound, "Resolved call for $callName was not found.")
assertTrue(callFound, "Resolved call for $callName was not found")
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lexer.JetTokens;
@@ -32,6 +33,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.BindingContext.CALL;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
class JetInvokeFunctionReference extends JetSimpleReference<JetCallExpression> implements MultiRangeReference {
@@ -48,10 +50,15 @@ class JetInvokeFunctionReference extends JetSimpleReference<JetCallExpression> i
@Override
@NotNull
protected Collection<DeclarationDescriptor> getTargetDescriptors(@NotNull BindingContext context) {
ResolvedCall<?> resolvedCall = context.get(RESOLVED_CALL, getExpression().getCalleeExpression());
JetExpression calleeExpression = getExpression().getCalleeExpression();
ResolvedCall<?> resolvedCall = context.get(RESOLVED_CALL, calleeExpression);
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
return Collections.<DeclarationDescriptor>singleton(((VariableAsFunctionResolvedCall) resolvedCall).getCandidateDescriptor());
}
Call call = context.get(CALL, calleeExpression);
if (call != null && resolvedCall != null && call.getCallType() == Call.CallType.INVOKE) {
return Collections.<DeclarationDescriptor>singleton(resolvedCall.getCandidateDescriptor());
}
return Collections.emptyList();
}