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.psi.JetElement;
|
||||||
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
|
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||||
|
|
||||||
public class JetModuleUtil {
|
public class JetModuleUtil {
|
||||||
public static NamespaceType getRootNamespaceType(JetElement expression) {
|
public static NamespaceType getRootNamespaceType(JetElement expression) {
|
||||||
// TODO: this is a stub: at least the modules' root namespaces must be indexed here
|
// 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.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
|
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.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||||
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isLHSOfDot;
|
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 "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();
|
temporaryTrace.commit();
|
||||||
return result[0];
|
return result[0];
|
||||||
@@ -154,7 +155,7 @@ public class CallExpressionResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JetScope scope = new ChainedScope(classifier, scopes.toArray(new JetScope[scopes.size()]));
|
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;
|
return classObjectType;
|
||||||
}
|
}
|
||||||
@@ -195,7 +196,7 @@ public class CallExpressionResolver {
|
|||||||
else {
|
else {
|
||||||
scope = namespace.getMemberScope();
|
scope = namespace.getMemberScope();
|
||||||
}
|
}
|
||||||
return new NamespaceType(name, scope);
|
return new NamespaceType(name, scope, NO_RECEIVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
+18
-9
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls.tasks;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.JetReferenceExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
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.autocasts.AutoCastServiceImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
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.ExpressionReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
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.NamespaceType;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -82,20 +84,27 @@ public class TaskPrioritizer {
|
|||||||
@NotNull JetReferenceExpression functionReference,
|
@NotNull JetReferenceExpression functionReference,
|
||||||
@NotNull List<CallableDescriptorCollector<? extends D>> callableDescriptorCollectors
|
@NotNull List<CallableDescriptorCollector<? extends D>> callableDescriptorCollectors
|
||||||
) {
|
) {
|
||||||
|
List<Pair<JetScope, ReceiverValue>> variants = new ArrayList<Pair<JetScope, ReceiverValue>>(2);
|
||||||
|
|
||||||
ReceiverValue explicitReceiver = context.call.getExplicitReceiver();
|
ReceiverValue explicitReceiver = context.call.getExplicitReceiver();
|
||||||
JetScope scope;
|
|
||||||
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
||||||
// Receiver is a namespace
|
JetType receiverType = explicitReceiver.getType();
|
||||||
scope = explicitReceiver.getType().getMemberScope();
|
variants.add(Pair.create(receiverType.getMemberScope(), NO_RECEIVER));
|
||||||
explicitReceiver = NO_RECEIVER;
|
ReceiverValue value = ((NamespaceType) receiverType).getReceiverValue();
|
||||||
|
if (value.exists()) {
|
||||||
|
variants.add(Pair.create(context.scope, value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
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();
|
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);
|
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")
|
@TestMetadata("ExtensionFunctions.kt")
|
||||||
public void testExtensionFunctions() throws Exception {
|
public void testExtensionFunctions() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/extensions/ExtensionFunctions.kt");
|
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");
|
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")
|
@TestMetadata("kt3563.kt")
|
||||||
public void testKt3563() throws Exception {
|
public void testKt3563() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/extensions/kt3563.kt");
|
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");
|
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")
|
@TestMetadata("object.kt")
|
||||||
public void testObject() throws Exception {
|
public void testObject() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/extensions/object.kt");
|
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");
|
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")
|
@TestMetadata("classObjectWithPrivateGenericMember.kt")
|
||||||
public void testClassObjectWithPrivateGenericMember() throws Exception {
|
public void testClassObjectWithPrivateGenericMember() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/classes/classObjectWithPrivateGenericMember.kt");
|
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.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -29,12 +30,13 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class NamespaceType implements JetType {
|
public class NamespaceType implements JetType {
|
||||||
private final Name name;
|
private final Name name;
|
||||||
@NotNull
|
|
||||||
private final JetScope memberScope;
|
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.name = name;
|
||||||
this.memberScope = memberScope;
|
this.memberScope = memberScope;
|
||||||
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -48,6 +50,11 @@ public class NamespaceType implements JetType {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ReceiverValue getReceiverValue() {
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public TypeConstructor getConstructor() {
|
public TypeConstructor getConstructor() {
|
||||||
|
|||||||
Reference in New Issue
Block a user