Control-Flow: Compute type predicates for arguments of unresolved calls
This commit is contained in:
@@ -17,11 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.cfg;
|
package org.jetbrains.kotlin.cfg;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.util.SmartFMap;
|
import com.intellij.util.SmartFMap;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
|
import com.intellij.util.containers.MultiMap;
|
||||||
import kotlin.KotlinPackage;
|
import kotlin.KotlinPackage;
|
||||||
import kotlin.jvm.functions.Function0;
|
import kotlin.jvm.functions.Function0;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
@@ -43,8 +45,15 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
|
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
|
||||||
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||||
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilPackage;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
@@ -220,9 +229,90 @@ public class JetControlFlowProcessor {
|
|||||||
return createNonSyntheticValue(to, Arrays.asList(from), kind);
|
return createNonSyntheticValue(to, Arrays.asList(from), kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Map<PseudoValue, TypePredicate> getTypeMapForUnresolvedCall(@NotNull JetElement to, List<PseudoValue> arguments) {
|
||||||
|
Call call = CallUtilPackage.getCall(to, trace.getBindingContext());
|
||||||
|
if (call == null) return null;
|
||||||
|
|
||||||
|
JetExpression callee = call.getCalleeExpression();
|
||||||
|
if (callee == null) return null;
|
||||||
|
|
||||||
|
Collection<FunctionDescriptor> candidates = KotlinPackage.sortBy(
|
||||||
|
KotlinPackage.filterIsInstance(
|
||||||
|
BindingContextUtilPackage.getReferenceTargets(callee, trace.getBindingContext()),
|
||||||
|
FunctionDescriptor.class
|
||||||
|
),
|
||||||
|
new Function1<FunctionDescriptor, Comparable>() {
|
||||||
|
@Override
|
||||||
|
public Comparable invoke(FunctionDescriptor descriptor) {
|
||||||
|
return DescriptorRenderer.DEBUG_TEXT.render(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (candidates.isEmpty()) return null;
|
||||||
|
|
||||||
|
ReceiverValue explicitReceiver = call.getExplicitReceiver();
|
||||||
|
int argValueOffset = explicitReceiver.exists() ? 1 : 0;
|
||||||
|
|
||||||
|
MultiMap<PseudoValue, TypePredicate> valuesToPredicates = new MultiMap<PseudoValue, TypePredicate>(arguments.size(), 1);
|
||||||
|
|
||||||
|
candidateLoop:
|
||||||
|
for (FunctionDescriptor candidate : candidates) {
|
||||||
|
ResolvedCallImpl<FunctionDescriptor> candidateCall = ResolvedCallImpl.create(
|
||||||
|
ResolutionCandidate.create(call,
|
||||||
|
candidate,
|
||||||
|
call.getDispatchReceiver(),
|
||||||
|
explicitReceiver,
|
||||||
|
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||||
|
null),
|
||||||
|
new DelegatingBindingTrace(trace.getBindingContext(), "Compute type predicates for unresolved call arguments"),
|
||||||
|
TracingStrategy.EMPTY,
|
||||||
|
new DataFlowInfoForArgumentsImpl(call)
|
||||||
|
);
|
||||||
|
ValueArgumentsToParametersMapper.Status status = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
|
||||||
|
call,
|
||||||
|
TracingStrategy.EMPTY,
|
||||||
|
candidateCall,
|
||||||
|
Sets.<ValueArgument>newLinkedHashSet()
|
||||||
|
);
|
||||||
|
if (!status.isSuccess()) continue;
|
||||||
|
|
||||||
|
Map<ValueParameterDescriptor, ResolvedValueArgument> candidateArgumentMap = candidateCall.getValueArguments();
|
||||||
|
List<? extends ValueArgument> callArguments = call.getValueArguments();
|
||||||
|
for (int i = 0; i < callArguments.size(); i++) {
|
||||||
|
int valueIndex = i + argValueOffset;
|
||||||
|
if (valueIndex >= arguments.size()) continue candidateLoop;
|
||||||
|
PseudoValue argumentValue = arguments.get(valueIndex);
|
||||||
|
|
||||||
|
ArgumentMapping mapping = candidateCall.getArgumentMapping(callArguments.get(i));
|
||||||
|
if (!(mapping instanceof ArgumentMatch)) continue candidateLoop;
|
||||||
|
|
||||||
|
ValueParameterDescriptor candidateParameter = ((ArgumentMatch) mapping).getValueParameter();
|
||||||
|
ResolvedValueArgument resolvedArgument = candidateArgumentMap.get(candidateParameter);
|
||||||
|
JetType expectedType = resolvedArgument instanceof VarargValueArgument
|
||||||
|
? candidateParameter.getVarargElementType()
|
||||||
|
: candidateParameter.getType();
|
||||||
|
|
||||||
|
valuesToPredicates.putValue(argumentValue, expectedType != null ? new AllSubtypes(expectedType) : AllTypes.INSTANCE$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SmartFMap<PseudoValue, TypePredicate> result = SmartFMap.emptyMap();
|
||||||
|
for (Map.Entry<PseudoValue, Collection<TypePredicate>> entry : valuesToPredicates.entrySet()) {
|
||||||
|
result = result.plus(entry.getKey(), PseudocodePackage.or(entry.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private PseudoValue createUnresolvedCallByValues(@NotNull JetElement to, @Nullable JetElement valueElement, List<PseudoValue> arguments) {
|
private PseudoValue createUnresolvedCallByValues(@NotNull JetElement to, @Nullable JetElement valueElement, List<PseudoValue> arguments) {
|
||||||
return builder.magic(to, valueElement, arguments, defaultTypeMap(arguments), MagicKind.UNRESOLVED_CALL).getOutputValue();
|
Map<PseudoValue, TypePredicate> typeMap = getTypeMapForUnresolvedCall(to, arguments);
|
||||||
|
if (typeMap == null) {
|
||||||
|
typeMap = defaultTypeMap(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.magic(to, valueElement, arguments, typeMap, MagicKind.UNRESOLVED_CALL).getOutputValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
|||||||
import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET;
|
import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*;
|
import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*;
|
||||||
|
|
||||||
/*package*/ class ValueArgumentsToParametersMapper {
|
public class ValueArgumentsToParametersMapper {
|
||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
STRONG_ERROR(false),
|
STRONG_ERROR(false),
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
== foo ==
|
||||||
|
fun foo(i: Int) {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(i: Int)
|
||||||
|
magic[FAKE_INITIALIZER](i: Int) -> <v0>
|
||||||
|
w(i|<v0>)
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(a: IntArray)
|
||||||
|
magic[FAKE_INITIALIZER](a: IntArray) -> <v0>
|
||||||
|
w(a|<v0>)
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: String, b: Int) {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(a: String)
|
||||||
|
magic[FAKE_INITIALIZER](a: String) -> <v0>
|
||||||
|
w(a|<v0>)
|
||||||
|
v(b: Int)
|
||||||
|
magic[FAKE_INITIALIZER](b: Int) -> <v1>
|
||||||
|
w(b|<v1>)
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo() {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test() {
|
||||||
|
foo(bar())
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
2 mark({ foo(bar()) })
|
||||||
|
mark(bar())
|
||||||
|
magic[UNRESOLVED_CALL](bar()|!<v0>) -> <v1>
|
||||||
|
mark(foo(bar()))
|
||||||
|
magic[UNRESOLVED_CALL](foo(bar())|<v1>, !<v2>) -> <v3>
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(i: Int) {}
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
fun foo(a: String, b: Int) {}
|
||||||
|
fun foo() {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(bar())
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
== foo ==
|
||||||
|
fun foo(i: Int) {}
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](i: Int) -> <v0>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
---------------------
|
||||||
|
<v0>: IntArray NEW: magic[FAKE_INITIALIZER](a: IntArray) -> <v0>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: String, b: Int) {}
|
||||||
|
---------------------
|
||||||
|
<v0>: String NEW: magic[FAKE_INITIALIZER](a: String) -> <v0>
|
||||||
|
<v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo() {}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test() {
|
||||||
|
foo(bar())
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
foo !<v2>: *
|
||||||
|
bar !<v0>: *
|
||||||
|
bar() <v1>: OR{{<: IntArray}, {<: Int}} NEW: magic[UNRESOLVED_CALL](bar()|!<v0>) -> <v1>
|
||||||
|
foo(bar()) <v3>: * NEW: magic[UNRESOLVED_CALL](foo(bar())|<v1>, !<v2>) -> <v3>
|
||||||
|
{ foo(bar()) } <v3>: * COPY
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
== Foo ==
|
||||||
|
open class Foo {
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
fun foo(a: Int, b: Int) {}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(a: IntArray)
|
||||||
|
magic[FAKE_INITIALIZER](a: IntArray) -> <v0>
|
||||||
|
w(a|<v0>)
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: Int, b: Int) {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(a: Int)
|
||||||
|
magic[FAKE_INITIALIZER](a: Int) -> <v0>
|
||||||
|
w(a|<v0>)
|
||||||
|
v(b: Int)
|
||||||
|
magic[FAKE_INITIALIZER](b: Int) -> <v1>
|
||||||
|
w(b|<v1>)
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun Foo.foo(i: Int) {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(i: Int)
|
||||||
|
magic[FAKE_INITIALIZER](i: Int) -> <v0>
|
||||||
|
w(i|<v0>)
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun Foo.foo() {}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
2 mark({})
|
||||||
|
read (Unit)
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test() {
|
||||||
|
Foo().foo(bar())
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
2 mark({ Foo().foo(bar()) })
|
||||||
|
mark(Foo().foo(bar()))
|
||||||
|
mark(Foo())
|
||||||
|
call(Foo(), <init>) -> <v0>
|
||||||
|
mark(bar())
|
||||||
|
magic[UNRESOLVED_CALL](bar()|!<v1>) -> <v2>
|
||||||
|
mark(foo(bar()))
|
||||||
|
call(foo(bar()), foo|<v0>, <v2>) -> <v3>
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
open class Foo {
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
fun foo(a: Int, b: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Foo.foo(i: Int) {}
|
||||||
|
fun Foo.foo() {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Foo().foo(bar())
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
== Foo ==
|
||||||
|
open class Foo {
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
fun foo(a: Int, b: Int) {}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: IntArray) {}
|
||||||
|
---------------------
|
||||||
|
<v0>: IntArray NEW: magic[FAKE_INITIALIZER](a: IntArray) -> <v0>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(a: Int, b: Int) {}
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](a: Int) -> <v0>
|
||||||
|
<v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun Foo.foo(i: Int) {}
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](i: Int) -> <v0>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun Foo.foo() {}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test() {
|
||||||
|
Foo().foo(bar())
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
Foo() <v0>: {<: Foo} NEW: call(Foo(), <init>) -> <v0>
|
||||||
|
bar !<v1>: *
|
||||||
|
bar() <v2>: IntArray NEW: magic[UNRESOLVED_CALL](bar()|!<v1>) -> <v2>
|
||||||
|
foo(bar()) <v3>: * NEW: call(foo(bar()), foo|<v0>, <v2>) -> <v3>
|
||||||
|
Foo().foo(bar()) <v3>: * COPY
|
||||||
|
{ Foo().foo(bar()) } <v3>: * COPY
|
||||||
|
=====================
|
||||||
@@ -616,6 +616,18 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unresolvedCalls.kt")
|
||||||
|
public void testUnresolvedCalls() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCalls.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unresolvedCallsWithReceiver.kt")
|
||||||
|
public void testUnresolvedCallsWithReceiver() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCallsWithReceiver.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unresolvedProperty.kt")
|
@TestMetadata("unresolvedProperty.kt")
|
||||||
public void testUnresolvedProperty() throws Exception {
|
public void testUnresolvedProperty() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedProperty.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedProperty.kt");
|
||||||
|
|||||||
@@ -618,6 +618,18 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unresolvedCalls.kt")
|
||||||
|
public void testUnresolvedCalls() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCalls.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unresolvedCallsWithReceiver.kt")
|
||||||
|
public void testUnresolvedCallsWithReceiver() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCallsWithReceiver.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unresolvedProperty.kt")
|
@TestMetadata("unresolvedProperty.kt")
|
||||||
public void testUnresolvedProperty() throws Exception {
|
public void testUnresolvedProperty() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedProperty.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedProperty.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user