diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt index f81a587d736..a1c3496b2bf 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt @@ -231,8 +231,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, if (functionExpectedInfos.isEmpty()) return null fun toLookupElement(descriptor: FunctionDescriptor): LookupElement? { - val functionType = functionType(descriptor) - if (functionType == null) return null + val functionType = functionType(descriptor) ?: return null val matchedExpectedInfos = functionExpectedInfos.filter { functionType.isSubtypeOf(it.type) } if (matchedExpectedInfos.isEmpty()) return null diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt index 8be39ffc9ef..f57f51af4fe 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt @@ -34,6 +34,8 @@ import org.jetbrains.jet.plugin.completion.* import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import org.jetbrains.jet.plugin.completion.handlers.WithTailInsertHandler +import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor class ArtificialElementInsertHandler( val textBeforeCaret: String, val textAfterCaret: String, val shortenRefs: Boolean) : InsertHandler{ @@ -155,8 +157,26 @@ fun MutableCollection.addLookupElementsForNullable(factory: () -> } fun functionType(function: FunctionDescriptor): JetType? { + val extensionReceiverType = function.getExtensionReceiverParameter()?.getType() + val memberReceiverType = if (function is ConstructorDescriptor) { + val classDescriptor = function.getContainingDeclaration() + if (classDescriptor.isInner()) { + (classDescriptor.getContainingDeclaration() as? ClassifierDescriptor)?.getDefaultType() + } + else { + null + } + } + else { + (function.getContainingDeclaration() as? ClassifierDescriptor)?.getDefaultType() + } + //TODO: this is to be changed when references to member extensions supported + val receiverType = if (extensionReceiverType != null && memberReceiverType != null) + null + else + extensionReceiverType ?: memberReceiverType return KotlinBuiltIns.getInstance().getFunctionType(function.getAnnotations(), - null, + receiverType, function.getValueParameters().map { it.getType() }, function.getReturnType() ?: return null) } diff --git a/idea/testData/completion/smart/FunctionReference10.kt b/idea/testData/completion/smart/FunctionReference10.kt new file mode 100644 index 00000000000..90a089e4593 --- /dev/null +++ b/idea/testData/completion/smart/FunctionReference10.kt @@ -0,0 +1,19 @@ +class C { + fun foo(s: String): Boolean = true + + fun bar() { + listOf("a").filter() + } + + class object { + fun staticFoo(s: String): Boolean = true + } +} + +fun C.extensionFoo(s: String): Boolean = true +fun globalFoo(s: String): Boolean = true + +// ABSENT: ::foo +// ABSENT: ::staticFoo +// ABSENT: ::extensionFoo +// EXIST: ::globalFoo diff --git a/idea/testData/completion/smart/FunctionReference11.kt b/idea/testData/completion/smart/FunctionReference11.kt new file mode 100644 index 00000000000..5afc765192b --- /dev/null +++ b/idea/testData/completion/smart/FunctionReference11.kt @@ -0,0 +1,19 @@ +import kotlin.platform.platformName + +class C(i: Int){ + class Nested + inner class Inner + + fun bar() { + foo() + } +} + +platformName("foo1") +fun foo(p: () -> C.Nested){} + +platformName("foo2") +fun foo(p: () -> C.Inner){} + +// EXIST: ::Nested +// ABSENT: ::Inner diff --git a/idea/testData/completion/smart/FunctionReference12.kt b/idea/testData/completion/smart/FunctionReference12.kt new file mode 100644 index 00000000000..ddf4f861be5 --- /dev/null +++ b/idea/testData/completion/smart/FunctionReference12.kt @@ -0,0 +1,13 @@ +class C { + fun foo(p: C.() -> Unit){} + + fun bar() { + foo() + } + + fun f1(){} + fun C.f2(){} +} + +// EXIST: ::f1 +// ABSENT: ::f2 diff --git a/idea/testData/completion/smart/FunctionReference8.kt.todo b/idea/testData/completion/smart/FunctionReference8.kt.todo index e995e62a6bf..77c7ece73d3 100644 --- a/idea/testData/completion/smart/FunctionReference8.kt.todo +++ b/idea/testData/completion/smart/FunctionReference8.kt.todo @@ -7,5 +7,5 @@ fun bar() { fun String.f1(){} fun f2(){} -// EXIST: ::f1 +// EXIST: String::f1 // ABSENT: ::f2 diff --git a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java index 0afd8356d02..7545755fdf9 100644 --- a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java @@ -198,6 +198,24 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest(fileName); } + @TestMetadata("FunctionReference10.kt") + public void testFunctionReference10() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/FunctionReference10.kt"); + doTest(fileName); + } + + @TestMetadata("FunctionReference11.kt") + public void testFunctionReference11() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/FunctionReference11.kt"); + doTest(fileName); + } + + @TestMetadata("FunctionReference12.kt") + public void testFunctionReference12() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/FunctionReference12.kt"); + doTest(fileName); + } + @TestMetadata("FunctionReference3.kt") public void testFunctionReference3() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/smart/FunctionReference3.kt");