diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java index 246083acff6..8e856487338 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java @@ -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); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index bd0cb4c74fc..b4a4c0100f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 5f5b9ef845c..1ae1e1d185e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -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> callableDescriptorCollectors ) { + List> variants = new ArrayList>(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 result = + new ResolutionTaskHolder(functionReference, context, new MyPriorityProvider(context), null); + for (Pair pair : variants) { + doComputeTasks(pair.second, new TaskPrioritizerContext(name, result, context, pair.first, callableDescriptorCollectors)); } - ResolutionTaskHolder result = new ResolutionTaskHolder(functionReference, context, new MyPriorityProvider(context), null); - TaskPrioritizerContext c = new TaskPrioritizerContext(name, result, context, scope, callableDescriptorCollectors); - doComputeTasks(explicitReceiver, c); return result.getTasks(); } diff --git a/compiler/testData/codegen/box/classes/classObjectToString.kt b/compiler/testData/codegen/box/classes/classObjectToString.kt new file mode 100644 index 00000000000..b6fdee98c38 --- /dev/null +++ b/compiler/testData/codegen/box/classes/classObjectToString.kt @@ -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" diff --git a/compiler/testData/diagnostics/tests/extensions/classObject.kt b/compiler/testData/diagnostics/tests/extensions/classObject.kt new file mode 100644 index 00000000000..762a9d836d7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/classObject.kt @@ -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.f5() + B.f5() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/kt3470.kt b/compiler/testData/diagnostics/tests/extensions/kt3470.kt new file mode 100644 index 00000000000..720e19f2009 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/kt3470.kt @@ -0,0 +1,7 @@ +class A { + class object { + fun foo() = toString() + } +} + +val a = A.toString() diff --git a/compiler/testData/diagnostics/tests/extensions/noClassObjectsInJava.kt b/compiler/testData/diagnostics/tests/extensions/noClassObjectsInJava.kt new file mode 100644 index 00000000000..619baea05d3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/noClassObjectsInJava.kt @@ -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.bar() +fun f2() = A.Nested.bar() diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 62b71a4fd3e..992e316f8c5 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 73317b40af1..0470bcdac46 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/NamespaceType.java b/core/descriptors/src/org/jetbrains/jet/lang/types/NamespaceType.java index be405b4ebb1..b9b60d73c47 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/NamespaceType.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/NamespaceType.java @@ -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() {