diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt index 3b5f08b1850..6e8fdccc235 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -30,10 +30,7 @@ import org.jetbrains.kotlin.psi.JetCallableReferenceExpression import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.psi.JetSimpleNameExpression import org.jetbrains.kotlin.psi.ValueArgument -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil -import org.jetbrains.kotlin.resolve.TypeResolver +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext @@ -204,8 +201,8 @@ private fun bindPropertyReference(expression: JetCallableReferenceExpression, re private fun createReflectionTypeForCallableDescriptor( descriptor: CallableDescriptor, - context: ResolutionContext<*>, reflectionTypes: ReflectionTypes, + trace: BindingTrace?, reportOn: JetExpression? ): JetType? { val extensionReceiver = descriptor.getExtensionReceiverParameter() @@ -213,7 +210,7 @@ private fun createReflectionTypeForCallableDescriptor( if (extensionReceiver != null && dispatchReceiver != null && descriptor is CallableMemberDescriptor) { if (reportOn != null) { - context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reportOn, descriptor)) + trace?.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reportOn, descriptor)) } return null } @@ -227,7 +224,7 @@ private fun createReflectionTypeForCallableDescriptor( createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes) is VariableDescriptor -> { if (reportOn != null) { - context.trace.report(UNSUPPORTED.on(reportOn, "References to variables aren't supported yet")) + trace?.report(UNSUPPORTED.on(reportOn, "References to variables aren't supported yet")) } null } @@ -238,10 +235,9 @@ private fun createReflectionTypeForCallableDescriptor( public fun getReflectionTypeForCandidateDescriptor( descriptor: CallableDescriptor, - context: ResolutionContext<*>, reflectionTypes: ReflectionTypes ): JetType? = - createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, null) + createReflectionTypeForCallableDescriptor(descriptor, reflectionTypes, null, null) public fun createReflectionTypeForResolvedCallableReference( reference: JetCallableReferenceExpression, @@ -249,7 +245,7 @@ public fun createReflectionTypeForResolvedCallableReference( context: ResolutionContext<*>, reflectionTypes: ReflectionTypes ): JetType? { - val type = createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, reference.getCallableReference()) + val type = createReflectionTypeForCallableDescriptor(descriptor, reflectionTypes, context.trace, reference.getCallableReference()) ?: return null when (descriptor) { is FunctionDescriptor -> { @@ -276,7 +272,7 @@ public fun getResolvedCallableReferenceShapeType( null overloadResolutionResults.isSingleResult() -> OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call -> - createReflectionTypeForCallableDescriptor(call.getResultingDescriptor(), context, reflectionTypes, reference) + createReflectionTypeForCallableDescriptor(call.getResultingDescriptor(), reflectionTypes, context.trace, reference) } expectedTypeUnknown /* && overload resolution was ambiguous */ -> functionPlaceholders.createFunctionPlaceholderType(emptyList(), false) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 153fd8e5203..094a2e09567 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -164,7 +164,7 @@ public class CandidateResolver( = check { if (!noExpectedType(expectedType)) { val candidate = candidateCall.getCandidateDescriptor() - val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, this, reflectionTypes); + val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, reflectionTypes); if (candidateReflectionType != null) { if (!JetTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) { candidateCall.addStatus(OTHER_ERROR) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index 1941987366b..23ba502cc52 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -102,7 +102,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, private val smartCompletion = expression?.let { SmartCompletion( it, resolutionFacade, bindingContext, isVisibleFilter, prefixMatcher, - GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory, forBasicCompletion = true + GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver, forBasicCompletion = true ) } @@ -353,7 +353,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, } if (smartCompletion != null) { - sorter = sorter.weighBefore(KindWeigher.toString(), SmartCompletionInBasicWeigher(smartCompletion), SmartCompletionPriorityWeigher) + val smartCompletionInBasicWeigher = SmartCompletionInBasicWeigher(smartCompletion, callTypeAndReceiver.callType, resolutionFacade) + sorter = sorter.weighBefore(KindWeigher.toString(), smartCompletionInBasicWeigher, SmartCompletionPriorityWeigher) } return sorter diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index 431c8629e6f..2dfe2cf5218 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -126,7 +126,14 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC protected val referenceVariantsHelper = ReferenceVariantsHelper(bindingContext, resolutionFacade, isVisibleFilter) - protected val lookupElementFactory = createLookupElementFactory() + protected val callTypeAndReceiver: CallTypeAndReceiver<*, *> + protected val lookupElementFactory: LookupElementFactory + + init { + val (callTypeAndReceiver, receiverTypes) = detectCallTypeAndReceiverTypes() + this.callTypeAndReceiver = callTypeAndReceiver + this.lookupElementFactory = createLookupElementFactory(callTypeAndReceiver.callType, receiverTypes) + } // LookupElementsCollector instantiation is deferred because virtual call to createSorter uses data from derived classes protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) { @@ -298,9 +305,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC ) } - private fun createLookupElementFactory(): LookupElementFactory { - val (callType, receiverTypes) = detectCallTypeAndReceiverTypes() - + private fun createLookupElementFactory(callType: CallType<*>, receiverTypes: Collection?): LookupElementFactory { val contextVariablesProvider = { nameExpression?.let { referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT) @@ -314,9 +319,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC insertHandlerProvider, contextVariablesProvider) } - private fun detectCallTypeAndReceiverTypes(): Pair, Collection?> { + private fun detectCallTypeAndReceiverTypes(): Pair, Collection?> { if (nameExpression == null) { - return CallType.DEFAULT to null + return CallTypeAndReceiver.DEFAULT to null } val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression) @@ -326,7 +331,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC is CallTypeAndReceiver.CALLABLE_REFERENCE -> { if (callTypeAndReceiver.receiver != null) { val type = bindingContext[BindingContext.TYPE, callTypeAndReceiver.receiver] - return callTypeAndReceiver.callType to type.singletonOrEmptyList() + return callTypeAndReceiver to type.singletonOrEmptyList() } else { receiverExpression = null @@ -343,7 +348,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC is CallTypeAndReceiver.PACKAGE_DIRECTIVE, is CallTypeAndReceiver.TYPE -> // we don't need to highlight immediate members in these cases - return callTypeAndReceiver.callType to null + return callTypeAndReceiver to null else -> throw RuntimeException() //TODO: see KT-9394 } @@ -374,6 +379,6 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC receiverTypes = receiverTypes.map { it.makeNotNullable() } } - return callTypeAndReceiver.callType to receiverTypes + return callTypeAndReceiver to receiverTypes } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt index 2a25074dc50..c9fe54e7097 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt @@ -30,6 +30,8 @@ import org.jetbrains.kotlin.idea.completion.smart.* import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject import org.jetbrains.kotlin.idea.core.completion.PackageLookupObject +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.FuzzyType import org.jetbrains.kotlin.types.typeUtil.TypeNullability import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean @@ -177,7 +179,11 @@ object PreferMatchingItemWeigher : LookupElementWeigher("kotlin.preferMatching", } } -class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion) : LookupElementWeigher("kotlin.smartInBasic", true, false) { +class SmartCompletionInBasicWeigher( + private val smartCompletion: SmartCompletion, + private val callType: CallType<*>, + private val resolutionFacade: ResolutionFacade +) : LookupElementWeigher("kotlin.smartInBasic", true, false) { private val descriptorsToSkip = smartCompletion.descriptorsToSkip private val expectedInfos = smartCompletion.expectedInfos @@ -235,7 +241,7 @@ class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion val (fuzzyTypes, name) = when (o) { is DeclarationLookupObject -> { val descriptor = o.descriptor ?: return NO_MATCH_WEIGHT - descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator) to descriptor.name + descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator, callType, resolutionFacade) to descriptor.name } is ThisItemLookupObject -> smartCastCalculator.types(o.receiverParameter).map { FuzzyType(it, emptyList()) } to null diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt index 2228bf005a7..b9bb4181f69 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt @@ -29,11 +29,11 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.completion.* import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.idea.util.FuzzyType import org.jetbrains.kotlin.idea.util.isAlmostEverything import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.JetType @@ -57,10 +57,22 @@ class SmartCompletion( private val inheritorSearchScope: GlobalSearchScope, private val toFromOriginalFileMapper: ToFromOriginalFileMapper, private val lookupElementFactory: LookupElementFactory, + private val callTypeAndReceiver: CallTypeAndReceiver<*, *>, private val forBasicCompletion: Boolean = false ) { - private val receiver = (expression as? JetSimpleNameExpression)?.getReceiverExpression() - private val expressionWithType = receiver?.parent as? JetExpression ?: expression + private val expressionWithType = when (callTypeAndReceiver) { + is CallTypeAndReceiver.DEFAULT -> + expression + + is CallTypeAndReceiver.DOT, + is CallTypeAndReceiver.SAFE, + is CallTypeAndReceiver.INFIX, + is CallTypeAndReceiver.CALLABLE_REFERENCE -> + expression.parent as JetExpression + + else -> // actually no smart completion for such places + expression + } public val expectedInfos: Collection = calcExpectedInfos(expressionWithType) @@ -141,14 +153,14 @@ class SmartCompletion( if (descriptor in descriptorsToSkip) return emptyList() val result = SmartList() - val types = descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator) + val types = descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator, callTypeAndReceiver.callType, resolutionFacade) val infoClassifier = { expectedInfo: ExpectedInfo -> types.classifyExpectedInfo(expectedInfo) } - result.addLookupElements(descriptor, expectedInfos, infoClassifier, noNameSimilarityForReturnItself = receiver == null) { descriptor -> + result.addLookupElements(descriptor, expectedInfos, infoClassifier, noNameSimilarityForReturnItself = callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { descriptor -> lookupElementFactory.createLookupElementsInSmartCompletion(descriptor, bindingContext, true) } - if (receiver == null) { + if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { toFunctionReferenceLookupElement(descriptor, expectedInfos.filterFunctionExpected())?.let { result.add(it) } } @@ -165,7 +177,7 @@ class SmartCompletion( val items = ArrayList() val inheritanceSearchers = ArrayList() - if (expectedInfos.isNotEmpty() && receiver == null) { + if (expectedInfos.isNotEmpty() && callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion) .addTo(items, inheritanceSearchers, expectedInfos) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt index 378ea2cc86c..818bfd64475 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt @@ -41,7 +41,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para expression?.let { SmartCompletion(it, resolutionFacade, bindingContext, isVisibleFilter, prefixMatcher, originalSearchScope, - toFromOriginalFileMapper, lookupElementFactory) + toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt index 96313d6d3b9..786bcb53405 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt @@ -23,13 +23,16 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.openapi.util.Key import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.idea.completion.* import org.jetbrains.kotlin.idea.completion.handlers.WithExpressionPrefixInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.TypeSubstitutor @@ -306,7 +309,17 @@ fun LookupElement.assignSmartCompletionPriority(priority: SmartCompletionItemPri return this } -fun DeclarationDescriptor.fuzzyTypesForSmartCompletion(smartCastCalculator: SmartCastCalculator): Collection { +fun DeclarationDescriptor.fuzzyTypesForSmartCompletion( + smartCastCalculator: SmartCastCalculator, + callType: CallType<*>, + resolutionFacade: ResolutionFacade +): Collection { + if (callType == CallType.CALLABLE_REFERENCE) { + if (this !is CallableDescriptor) return emptyList() + val type = getReflectionTypeForCandidateDescriptor(this, resolutionFacade.getFrontendService(ReflectionTypes::class.java)) ?: return emptyList() + return listOf(FuzzyType(type, emptyList()/* references to generic functions not supported yet */)) + } + if (this is CallableDescriptor) { var returnType = fuzzyReturnType() ?: return emptyList() // skip declarations of type Nothing or of generic parameter type which has no real bounds diff --git a/idea/idea-completion/testData/handlers/smart/FunctionReference1.kt b/idea/idea-completion/testData/handlers/smart/CallableReference1.kt similarity index 100% rename from idea/idea-completion/testData/handlers/smart/FunctionReference1.kt rename to idea/idea-completion/testData/handlers/smart/CallableReference1.kt diff --git a/idea/idea-completion/testData/handlers/smart/FunctionReference1.kt.after b/idea/idea-completion/testData/handlers/smart/CallableReference1.kt.after similarity index 100% rename from idea/idea-completion/testData/handlers/smart/FunctionReference1.kt.after rename to idea/idea-completion/testData/handlers/smart/CallableReference1.kt.after diff --git a/idea/idea-completion/testData/handlers/smart/FunctionReference2.kt b/idea/idea-completion/testData/handlers/smart/CallableReference2.kt similarity index 100% rename from idea/idea-completion/testData/handlers/smart/FunctionReference2.kt rename to idea/idea-completion/testData/handlers/smart/CallableReference2.kt diff --git a/idea/idea-completion/testData/handlers/smart/FunctionReference2.kt.after b/idea/idea-completion/testData/handlers/smart/CallableReference2.kt.after similarity index 100% rename from idea/idea-completion/testData/handlers/smart/FunctionReference2.kt.after rename to idea/idea-completion/testData/handlers/smart/CallableReference2.kt.after diff --git a/idea/idea-completion/testData/handlers/smart/CallableReference3.kt b/idea/idea-completion/testData/handlers/smart/CallableReference3.kt new file mode 100644 index 00000000000..3494134837e --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/CallableReference3.kt @@ -0,0 +1,9 @@ +fun foo(p: () -> Unit){} + +fun bar() { + foo(::) +} + +fun f(){} + +// ELEMENT: f \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/smart/CallableReference3.kt.after b/idea/idea-completion/testData/handlers/smart/CallableReference3.kt.after new file mode 100644 index 00000000000..d198ac24a4e --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/CallableReference3.kt.after @@ -0,0 +1,9 @@ +fun foo(p: () -> Unit){} + +fun bar() { + foo(::f) +} + +fun f(){} + +// ELEMENT: f \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/smart/CallableReference4.kt b/idea/idea-completion/testData/handlers/smart/CallableReference4.kt new file mode 100644 index 00000000000..199fb0bdb46 --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/CallableReference4.kt @@ -0,0 +1,12 @@ +class C + +fun C.extFun(s: String){} + +fun foo(p: C.(String) -> Unit, c: Char){} +fun foo(p: (String) -> Unit){} + +fun bar() { + foo(C::) +} + +// ELEMENT: extFun diff --git a/idea/idea-completion/testData/handlers/smart/CallableReference4.kt.after b/idea/idea-completion/testData/handlers/smart/CallableReference4.kt.after new file mode 100644 index 00000000000..f92e7df03ec --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/CallableReference4.kt.after @@ -0,0 +1,12 @@ +class C + +fun C.extFun(s: String){} + +fun foo(p: C.(String) -> Unit, c: Char){} +fun foo(p: (String) -> Unit){} + +fun bar() { + foo(C::extFun, ) +} + +// ELEMENT: extFun diff --git a/idea/idea-completion/testData/smart/callableReference/EmptyQualifier1.kt b/idea/idea-completion/testData/smart/callableReference/EmptyQualifier1.kt new file mode 100644 index 00000000000..f7ee1c34a56 --- /dev/null +++ b/idea/idea-completion/testData/smart/callableReference/EmptyQualifier1.kt @@ -0,0 +1,12 @@ +fun foo(p: () -> Unit){} + +fun bar() { + foo(::xf) +} + +fun xf1(){} +fun xf1(s: String){} +fun xf2(i: Int){} + +// EXIST: { lookupString:"xf1", itemText:"xf1", tailText: "() ()", typeText: "Unit" } +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/callableReference/EmptyQualifier2.kt b/idea/idea-completion/testData/smart/callableReference/EmptyQualifier2.kt new file mode 100644 index 00000000000..93aaf1834a7 --- /dev/null +++ b/idea/idea-completion/testData/smart/callableReference/EmptyQualifier2.kt @@ -0,0 +1,15 @@ +import kotlin.reflect.KProperty0 + +fun foo(p: KProperty0){} + +fun bar() { + foo(::xT) +} + +val xTopLevelIntVal = 1 +var xTopLevelIntVar = 1 +val xTopLevelStringVal = "1" + +// EXIST: { lookupString:"xTopLevelIntVal", itemText:"xTopLevelIntVal", tailText: " ()", typeText: "Int" } +// EXIST: { lookupString:"xTopLevelIntVar", itemText:"xTopLevelIntVar", tailText: " ()", typeText: "Int" } +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/callableReference/EmptyQualifier3.kt b/idea/idea-completion/testData/smart/callableReference/EmptyQualifier3.kt new file mode 100644 index 00000000000..82df9669689 --- /dev/null +++ b/idea/idea-completion/testData/smart/callableReference/EmptyQualifier3.kt @@ -0,0 +1,9 @@ +class C(i: Int){} + +fun foo(p: (Int) -> C){} + +fun bar(){ + foo(::) +} + +// EXIST: C diff --git a/idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier1.kt b/idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier1.kt new file mode 100644 index 00000000000..2ce9ff84540 --- /dev/null +++ b/idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier1.kt @@ -0,0 +1,20 @@ +class C { + fun xf1(){} + fun xf1(s: String){} + fun xf2(i: Int){} +} + +fun C.xfe1(){} +fun C.xfe1(s: String){} +fun C.xfe2(i: Int){} + + +fun foo(p: C.(String) -> Unit){} + +fun bar() { + foo(C::) +} + +// EXIST: { lookupString:"xf1", itemText:"xf1", tailText: "(s: String)", typeText: "Unit" } +// EXIST: { lookupString:"xfe1", itemText:"xfe1", tailText: "(s: String) for C in ", typeText: "Unit" } +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier2.kt b/idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier2.kt new file mode 100644 index 00000000000..8d31a4b8aca --- /dev/null +++ b/idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier2.kt @@ -0,0 +1,15 @@ +import kotlin.reflect.KProperty1 + +fun foo(p: KProperty1){} + +fun bar() { + foo(String::xT) +} + +val String.xTopLevelIntVal: Int get() = 1 +val String.xTopLevelStringVal: String get() = "1" +val Any.xTopLevelValOnAny: Int get() = 1 +val Int.xTopLevelValOnInt: Int get() = 1 + +// EXIST: { lookupString:"xTopLevelIntVal", itemText:"xTopLevelIntVal", tailText: " for String in ", typeText: "Int" } +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/callableReference/SAMConstructor.kt.todo b/idea/idea-completion/testData/smart/callableReference/SAMConstructor.kt.todo new file mode 100644 index 00000000000..ef539498895 --- /dev/null +++ b/idea/idea-completion/testData/smart/callableReference/SAMConstructor.kt.todo @@ -0,0 +1,7 @@ +fun foo(p: (() -> Unit) -> Runnable){} + +fun bar(){ + foo(::) +} + +// EXIST: Runnable diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java index 638644e9efa..7d3f0c4cc5f 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java @@ -595,6 +595,24 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/smart/callableReference"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("EmptyQualifier1.kt") + public void testEmptyQualifier1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/EmptyQualifier1.kt"); + doTest(fileName); + } + + @TestMetadata("EmptyQualifier2.kt") + public void testEmptyQualifier2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/EmptyQualifier2.kt"); + doTest(fileName); + } + + @TestMetadata("EmptyQualifier3.kt") + public void testEmptyQualifier3() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/EmptyQualifier3.kt"); + doTest(fileName); + } + @TestMetadata("NoQualifier1.kt") public void testNoQualifier1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/NoQualifier1.kt"); @@ -642,6 +660,18 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/NoQualifier9.kt"); doTest(fileName); } + + @TestMetadata("NonEmptyQualifier1.kt") + public void testNonEmptyQualifier1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier1.kt"); + doTest(fileName); + } + + @TestMetadata("NonEmptyQualifier2.kt") + public void testNonEmptyQualifier2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/NonEmptyQualifier2.kt"); + doTest(fileName); + } } @TestMetadata("idea/idea-completion/testData/smart/constructor") diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java index 49fd74388c1..bde7a1ba38f 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java @@ -113,6 +113,30 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion doTest(fileName); } + @TestMetadata("CallableReference1.kt") + public void testCallableReference1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/CallableReference1.kt"); + doTest(fileName); + } + + @TestMetadata("CallableReference2.kt") + public void testCallableReference2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/CallableReference2.kt"); + doTest(fileName); + } + + @TestMetadata("CallableReference3.kt") + public void testCallableReference3() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/CallableReference3.kt"); + doTest(fileName); + } + + @TestMetadata("CallableReference4.kt") + public void testCallableReference4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/CallableReference4.kt"); + doTest(fileName); + } + @TestMetadata("ClassInClassObject.kt") public void testClassInClassObject() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/ClassInClassObject.kt"); @@ -359,18 +383,6 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion doTest(fileName); } - @TestMetadata("FunctionReference1.kt") - public void testFunctionReference1() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/FunctionReference1.kt"); - doTest(fileName); - } - - @TestMetadata("FunctionReference2.kt") - public void testFunctionReference2() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/FunctionReference2.kt"); - doTest(fileName); - } - @TestMetadata("GenericFunction.kt") public void testGenericFunction() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/GenericFunction.kt");