Resolve extension calls on class objects
#KT-3470 Fixed
This commit is contained in:
@@ -19,11 +19,12 @@ package org.jetbrains.jet.lang.resolve;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||
|
||||
public class JetModuleUtil {
|
||||
public static NamespaceType getRootNamespaceType(JetElement expression) {
|
||||
// TODO: this is a stub: at least the modules' root namespaces must be indexed here
|
||||
return new NamespaceType(SpecialNames.ROOT_NAMESPACE, JetScope.EMPTY);
|
||||
return new NamespaceType(SpecialNames.ROOT_NAMESPACE, JetScope.EMPTY, ReceiverValue.NO_RECEIVER);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -52,6 +52,7 @@ import java.util.List;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
|
||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isLHSOfDot;
|
||||
|
||||
@@ -113,7 +114,7 @@ public class CallExpressionResolver {
|
||||
return "Scope for the type parameter on the left hand side of dot";
|
||||
}
|
||||
};
|
||||
return new NamespaceType(referencedName, scopeForStaticMembersResolution);
|
||||
return new NamespaceType(referencedName, scopeForStaticMembersResolution, NO_RECEIVER);
|
||||
}
|
||||
temporaryTrace.commit();
|
||||
return result[0];
|
||||
@@ -154,7 +155,7 @@ public class CallExpressionResolver {
|
||||
}
|
||||
|
||||
JetScope scope = new ChainedScope(classifier, scopes.toArray(new JetScope[scopes.size()]));
|
||||
return new NamespaceType(referencedName, scope);
|
||||
return new NamespaceType(referencedName, scope, new ExpressionReceiver(expression, classObjectType));
|
||||
}
|
||||
return classObjectType;
|
||||
}
|
||||
@@ -195,7 +196,7 @@ public class CallExpressionResolver {
|
||||
else {
|
||||
scope = namespace.getMemberScope();
|
||||
}
|
||||
return new NamespaceType(name, scope);
|
||||
return new NamespaceType(name, scope, NO_RECEIVER);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+18
-9
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls.tasks;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -25,7 +26,6 @@ import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.LibrarySourceHacks;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -34,9 +34,11 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -82,20 +84,27 @@ public class TaskPrioritizer {
|
||||
@NotNull JetReferenceExpression functionReference,
|
||||
@NotNull List<CallableDescriptorCollector<? extends D>> callableDescriptorCollectors
|
||||
) {
|
||||
List<Pair<JetScope, ReceiverValue>> variants = new ArrayList<Pair<JetScope, ReceiverValue>>(2);
|
||||
|
||||
ReceiverValue explicitReceiver = context.call.getExplicitReceiver();
|
||||
JetScope scope;
|
||||
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
||||
// Receiver is a namespace
|
||||
scope = explicitReceiver.getType().getMemberScope();
|
||||
explicitReceiver = NO_RECEIVER;
|
||||
JetType receiverType = explicitReceiver.getType();
|
||||
variants.add(Pair.create(receiverType.getMemberScope(), NO_RECEIVER));
|
||||
ReceiverValue value = ((NamespaceType) receiverType).getReceiverValue();
|
||||
if (value.exists()) {
|
||||
variants.add(Pair.create(context.scope, value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
scope = context.scope;
|
||||
variants.add(Pair.create(context.scope, explicitReceiver));
|
||||
}
|
||||
|
||||
ResolutionTaskHolder<D, F> result =
|
||||
new ResolutionTaskHolder<D, F>(functionReference, context, new MyPriorityProvider<D>(context), null);
|
||||
for (Pair<JetScope, ReceiverValue> pair : variants) {
|
||||
doComputeTasks(pair.second, new TaskPrioritizerContext<D, F>(name, result, context, pair.first, callableDescriptorCollectors));
|
||||
}
|
||||
|
||||
ResolutionTaskHolder<D, F> result = new ResolutionTaskHolder<D, F>(functionReference, context, new MyPriorityProvider<D>(context), null);
|
||||
TaskPrioritizerContext<D, F> c = new TaskPrioritizerContext<D, F>(name, result, context, scope, callableDescriptorCollectors);
|
||||
doComputeTasks(explicitReceiver, c);
|
||||
return result.getTasks();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class SomeClass { class object }
|
||||
|
||||
fun box() =
|
||||
if ((SomeClass.toString() as java.lang.String).matches("SomeClass\\\$object@[0-9a-fA-F]+"))
|
||||
"OK"
|
||||
else
|
||||
"Fail: $SomeClass"
|
||||
@@ -0,0 +1,19 @@
|
||||
trait Tr
|
||||
|
||||
class A { class object }
|
||||
class B { class object : Tr }
|
||||
|
||||
fun Any.f1() {}
|
||||
fun Any?.f2() {}
|
||||
fun Tr.f3() {}
|
||||
fun Tr?.f4() {}
|
||||
fun A.f5() {}
|
||||
|
||||
fun test() {
|
||||
A.f1()
|
||||
A.f2()
|
||||
B.f3()
|
||||
B.f4()
|
||||
A.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f5<!>()
|
||||
B.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f5<!>()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class A {
|
||||
class object {
|
||||
fun foo() = toString()
|
||||
}
|
||||
}
|
||||
|
||||
val a = A.toString()
|
||||
@@ -0,0 +1,11 @@
|
||||
// FILE: A.java
|
||||
public class A {
|
||||
public static void foo() {}
|
||||
public static class Nested {}
|
||||
}
|
||||
|
||||
// FILE: B.kt
|
||||
fun Any?.bar() = 42
|
||||
|
||||
fun f1() = A.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
fun f2() = A.Nested.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
@@ -2674,6 +2674,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/extensions"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("classObject.kt")
|
||||
public void testClassObject() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/classObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ExtensionFunctions.kt")
|
||||
public void testExtensionFunctions() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/ExtensionFunctions.kt");
|
||||
@@ -2704,6 +2709,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/kt2317.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt3470.kt")
|
||||
public void testKt3470() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/kt3470.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt3563.kt")
|
||||
public void testKt3563() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/kt3563.kt");
|
||||
@@ -2714,6 +2724,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/kt819ExtensionProperties.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noClassObjectsInJava.kt")
|
||||
public void testNoClassObjectsInJava() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/noClassObjectsInJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("object.kt")
|
||||
public void testObject() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/extensions/object.kt");
|
||||
|
||||
@@ -743,6 +743,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest("compiler/testData/codegen/box/classes/classObjectNotOfEnum.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classObjectToString.kt")
|
||||
public void testClassObjectToString() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/classes/classObjectToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classObjectWithPrivateGenericMember.kt")
|
||||
public void testClassObjectWithPrivateGenericMember() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/classes/classObjectWithPrivateGenericMember.kt");
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,12 +30,13 @@ import java.util.List;
|
||||
*/
|
||||
public class NamespaceType implements JetType {
|
||||
private final Name name;
|
||||
@NotNull
|
||||
private final JetScope memberScope;
|
||||
private final ReceiverValue receiver;
|
||||
|
||||
public NamespaceType(@NotNull Name name, @NotNull JetScope memberScope) {
|
||||
public NamespaceType(@NotNull Name name, @NotNull JetScope memberScope, @NotNull ReceiverValue receiver) {
|
||||
this.name = name;
|
||||
this.memberScope = memberScope;
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -48,6 +50,11 @@ public class NamespaceType implements JetType {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ReceiverValue getReceiverValue() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
|
||||
Reference in New Issue
Block a user