diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.kt index f1c54dad7d1..bdd33d4a6d9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/CallableDescriptorCollectors.kt @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.types.ErrorUtils import org.jetbrains.jet.lang.types.JetType import org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource +import org.jetbrains.jet.lang.resolve.DescriptorUtils.isStaticNestedClass public trait CallableDescriptorCollector { @@ -32,6 +33,8 @@ public trait CallableDescriptorCollector { public fun getMembersByName(receiver: JetType, name: Name, bindingTrace: BindingTrace): Collection + public fun getStaticMembersByName(receiver: JetType, name: Name, bindingTrace: BindingTrace): Collection + public fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection } @@ -63,16 +66,22 @@ private object FunctionCollector : CallableDescriptorCollector { val receiverScope = receiver.getMemberScope() - return receiverScope.getFunctions(name) + getConstructors(receiverScope, name) + return receiverScope.getFunctions(name) + getConstructors(receiverScope, name, { !isStaticNestedClass(it) }) + } + + override fun getStaticMembersByName(receiver: JetType, name: Name, bindingTrace: BindingTrace): Collection { + return getConstructors(receiver.getMemberScope(), name, { isStaticNestedClass(it) }) } override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection { return scope.getFunctions(name).filter { it.getExtensionReceiverParameter() != null } } - private fun getConstructors(scope: JetScope, name: Name): Collection { + private fun getConstructors( + scope: JetScope, name: Name, filterClassPredicate: (ClassDescriptor) -> Boolean = { true } + ): Collection { val classifier = scope.getClassifier(name) - if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier) + if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier) || !filterClassPredicate(classifier) // Constructors of singletons shouldn't be callable from the code || classifier.getKind().isSingleton()) { return listOf() @@ -106,6 +115,10 @@ private object VariableCollector : CallableDescriptorCollector { + return listOf() + } + override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection { // property may have an extension function type, we check the applicability later to avoid an early computing of deferred types return (listOf(scope.getLocalVariable(name)) + scope.getProperties(name)).filterNotNull() @@ -126,6 +139,10 @@ private object PropertyCollector : CallableDescriptorCollector { + return filterProperties(VARIABLES_COLLECTOR.getStaticMembersByName(receiver, name, bindingTrace)) + } + override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection { return filterProperties(VARIABLES_COLLECTOR.getExtensionsByName(scope, name, bindingTrace)) } @@ -143,6 +160,10 @@ private class FilteredCollector(private val delegate: Ca return filterOutMembersFromLibrarySource(delegate.getMembersByName(receiver, name, bindingTrace)) } + override fun getStaticMembersByName(receiver: JetType, name: Name, bindingTrace: BindingTrace): Collection { + return filterOutMembersFromLibrarySource(delegate.getStaticMembersByName(receiver, name, bindingTrace)) + } + override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection { return filterOutMembersFromLibrarySource(delegate.getExtensionsByName(scope, name, bindingTrace)) } 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 90faf006682..985121a4c58 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 @@ -119,6 +119,7 @@ public class TaskPrioritizer { Collection implicitReceivers = Sets.newLinkedHashSet(JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope)); if (receiver.exists()) { addCandidatesForExplicitReceiver(receiver, implicitReceivers, c, /*isExplicit=*/true); + addMembers(receiver, c, /*static=*/true, /*isExplicit=*/true); return; } addCandidatesForNoReceiver(implicitReceivers, c); @@ -130,20 +131,7 @@ public class TaskPrioritizer { @NotNull TaskPrioritizerContext c, boolean isExplicit ) { - - List variantsForExplicitReceiver = SmartCastUtils.getSmartCastVariants(explicitReceiver, c.context); - - //members - for (CallableDescriptorCollector callableDescriptorCollector : c.callableDescriptorCollectors) { - Collection> members = Lists.newArrayList(); - for (JetType type : variantsForExplicitReceiver) { - Collection membersForThisVariant = - callableDescriptorCollector.getMembersByName(type, c.name, c.context.trace); - convertWithReceivers(membersForThisVariant, explicitReceiver, - NO_RECEIVER, members, createKind(DISPATCH_RECEIVER, isExplicit), c.context.call); - } - c.result.addCandidates(members); - } + addMembers(explicitReceiver, c, /*static=*/false, isExplicit); for (CallableDescriptorCollector callableDescriptorCollector : c.callableDescriptorCollectors) { //member extensions @@ -159,6 +147,28 @@ public class TaskPrioritizer { } } + private static void addMembers( + ReceiverValue explicitReceiver, + TaskPrioritizerContext c, + boolean staticMembers, + boolean isExplicit + ) { + List variantsForExplicitReceiver = SmartCastUtils.getSmartCastVariants(explicitReceiver, c.context); + + for (CallableDescriptorCollector callableDescriptorCollector : c.callableDescriptorCollectors) { + Collection> members = Lists.newArrayList(); + for (JetType type : variantsForExplicitReceiver) { + Collection membersForThisVariant = + staticMembers + ? callableDescriptorCollector.getStaticMembersByName(type, c.name, c.context.trace) + : callableDescriptorCollector.getMembersByName(type, c.name, c.context.trace); + convertWithReceivers(membersForThisVariant, explicitReceiver, + NO_RECEIVER, members, createKind(DISPATCH_RECEIVER, isExplicit), c.context.call); + } + c.result.addCandidates(members); + } + } + private static ExplicitReceiverKind createKind(ExplicitReceiverKind kind, boolean isExplicit) { if (isExplicit) return kind; return ExplicitReceiverKind.NO_EXPLICIT_RECEIVER; @@ -206,6 +216,11 @@ public class TaskPrioritizer { //nonlocals c.result.addCandidates(nonlocalsList); + + //static (only for better error reporting) + for (ReceiverValue implicitReceiver : implicitReceivers) { + addMembers(implicitReceiver, c, /*static=*/true, /*isExplicit=*/false); + } } private static void addCandidatesForInvoke( diff --git a/compiler/testData/diagnostics/tests/inner/kt5854.kt b/compiler/testData/diagnostics/tests/inner/kt5854.kt new file mode 100644 index 00000000000..a769b4b6ab5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/kt5854.kt @@ -0,0 +1,11 @@ +//KT-5854 Incorrect 'Nested class should be qualified' + +class A { + class Nested { + + } + + fun foo() { + Nested(1) //two errors here, the first one is wrong + } +} diff --git a/compiler/testData/diagnostics/tests/inner/kt5854.txt b/compiler/testData/diagnostics/tests/inner/kt5854.txt new file mode 100644 index 00000000000..71e6f3fd42e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/kt5854.txt @@ -0,0 +1,16 @@ +package + +internal final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + internal final fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + internal final class Nested { + public constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 91eeb50ca3d..ebd8a759a66 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -5979,6 +5979,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("kt5854.kt") + public void testKt5854() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/kt5854.kt"); + doTest(fileName); + } + @TestMetadata("localClass.kt") public void testLocalClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/localClass.kt");