Support for callable references in smart completion
This commit is contained in:
+7
-11
@@ -30,10 +30,7 @@ import org.jetbrains.kotlin.psi.JetCallableReferenceExpression
|
|||||||
import org.jetbrains.kotlin.psi.JetExpression
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.psi.ValueArgument
|
import org.jetbrains.kotlin.psi.ValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
|
|
||||||
import org.jetbrains.kotlin.resolve.TypeResolver
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
@@ -204,8 +201,8 @@ private fun bindPropertyReference(expression: JetCallableReferenceExpression, re
|
|||||||
|
|
||||||
private fun createReflectionTypeForCallableDescriptor(
|
private fun createReflectionTypeForCallableDescriptor(
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
context: ResolutionContext<*>,
|
|
||||||
reflectionTypes: ReflectionTypes,
|
reflectionTypes: ReflectionTypes,
|
||||||
|
trace: BindingTrace?,
|
||||||
reportOn: JetExpression?
|
reportOn: JetExpression?
|
||||||
): JetType? {
|
): JetType? {
|
||||||
val extensionReceiver = descriptor.getExtensionReceiverParameter()
|
val extensionReceiver = descriptor.getExtensionReceiverParameter()
|
||||||
@@ -213,7 +210,7 @@ private fun createReflectionTypeForCallableDescriptor(
|
|||||||
|
|
||||||
if (extensionReceiver != null && dispatchReceiver != null && descriptor is CallableMemberDescriptor) {
|
if (extensionReceiver != null && dispatchReceiver != null && descriptor is CallableMemberDescriptor) {
|
||||||
if (reportOn != null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
@@ -227,7 +224,7 @@ private fun createReflectionTypeForCallableDescriptor(
|
|||||||
createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes)
|
createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes)
|
||||||
is VariableDescriptor -> {
|
is VariableDescriptor -> {
|
||||||
if (reportOn != null) {
|
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
|
null
|
||||||
}
|
}
|
||||||
@@ -238,10 +235,9 @@ private fun createReflectionTypeForCallableDescriptor(
|
|||||||
|
|
||||||
public fun getReflectionTypeForCandidateDescriptor(
|
public fun getReflectionTypeForCandidateDescriptor(
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
context: ResolutionContext<*>,
|
|
||||||
reflectionTypes: ReflectionTypes
|
reflectionTypes: ReflectionTypes
|
||||||
): JetType? =
|
): JetType? =
|
||||||
createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, null)
|
createReflectionTypeForCallableDescriptor(descriptor, reflectionTypes, null, null)
|
||||||
|
|
||||||
public fun createReflectionTypeForResolvedCallableReference(
|
public fun createReflectionTypeForResolvedCallableReference(
|
||||||
reference: JetCallableReferenceExpression,
|
reference: JetCallableReferenceExpression,
|
||||||
@@ -249,7 +245,7 @@ public fun createReflectionTypeForResolvedCallableReference(
|
|||||||
context: ResolutionContext<*>,
|
context: ResolutionContext<*>,
|
||||||
reflectionTypes: ReflectionTypes
|
reflectionTypes: ReflectionTypes
|
||||||
): JetType? {
|
): JetType? {
|
||||||
val type = createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, reference.getCallableReference())
|
val type = createReflectionTypeForCallableDescriptor(descriptor, reflectionTypes, context.trace, reference.getCallableReference())
|
||||||
?: return null
|
?: return null
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is FunctionDescriptor -> {
|
is FunctionDescriptor -> {
|
||||||
@@ -276,7 +272,7 @@ public fun getResolvedCallableReferenceShapeType(
|
|||||||
null
|
null
|
||||||
overloadResolutionResults.isSingleResult() ->
|
overloadResolutionResults.isSingleResult() ->
|
||||||
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call ->
|
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 */ ->
|
expectedTypeUnknown /* && overload resolution was ambiguous */ ->
|
||||||
functionPlaceholders.createFunctionPlaceholderType(emptyList(), false)
|
functionPlaceholders.createFunctionPlaceholderType(emptyList(), false)
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class CandidateResolver(
|
|||||||
= check {
|
= check {
|
||||||
if (!noExpectedType(expectedType)) {
|
if (!noExpectedType(expectedType)) {
|
||||||
val candidate = candidateCall.getCandidateDescriptor()
|
val candidate = candidateCall.getCandidateDescriptor()
|
||||||
val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, this, reflectionTypes);
|
val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, reflectionTypes);
|
||||||
if (candidateReflectionType != null) {
|
if (candidateReflectionType != null) {
|
||||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) {
|
if (!JetTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) {
|
||||||
candidateCall.addStatus(OTHER_ERROR)
|
candidateCall.addStatus(OTHER_ERROR)
|
||||||
|
|||||||
+3
-2
@@ -102,7 +102,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
private val smartCompletion = expression?.let {
|
private val smartCompletion = expression?.let {
|
||||||
SmartCompletion(
|
SmartCompletion(
|
||||||
it, resolutionFacade, bindingContext, isVisibleFilter, prefixMatcher,
|
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) {
|
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
|
return sorter
|
||||||
|
|||||||
@@ -126,7 +126,14 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
|
|
||||||
protected val referenceVariantsHelper = ReferenceVariantsHelper(bindingContext, resolutionFacade, isVisibleFilter)
|
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
|
// LookupElementsCollector instantiation is deferred because virtual call to createSorter uses data from derived classes
|
||||||
protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) {
|
protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
@@ -298,9 +305,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLookupElementFactory(): LookupElementFactory {
|
private fun createLookupElementFactory(callType: CallType<*>, receiverTypes: Collection<JetType>?): LookupElementFactory {
|
||||||
val (callType, receiverTypes) = detectCallTypeAndReceiverTypes()
|
|
||||||
|
|
||||||
val contextVariablesProvider = {
|
val contextVariablesProvider = {
|
||||||
nameExpression?.let {
|
nameExpression?.let {
|
||||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT)
|
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT)
|
||||||
@@ -314,9 +319,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
insertHandlerProvider, contextVariablesProvider)
|
insertHandlerProvider, contextVariablesProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun detectCallTypeAndReceiverTypes(): Pair<CallType<*>, Collection<JetType>?> {
|
private fun detectCallTypeAndReceiverTypes(): Pair<CallTypeAndReceiver<*, *>, Collection<JetType>?> {
|
||||||
if (nameExpression == null) {
|
if (nameExpression == null) {
|
||||||
return CallType.DEFAULT to null
|
return CallTypeAndReceiver.DEFAULT to null
|
||||||
}
|
}
|
||||||
|
|
||||||
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression)
|
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression)
|
||||||
@@ -326,7 +331,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
|
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
|
||||||
if (callTypeAndReceiver.receiver != null) {
|
if (callTypeAndReceiver.receiver != null) {
|
||||||
val type = bindingContext[BindingContext.TYPE, callTypeAndReceiver.receiver]
|
val type = bindingContext[BindingContext.TYPE, callTypeAndReceiver.receiver]
|
||||||
return callTypeAndReceiver.callType to type.singletonOrEmptyList()
|
return callTypeAndReceiver to type.singletonOrEmptyList()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
receiverExpression = null
|
receiverExpression = null
|
||||||
@@ -343,7 +348,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
||||||
is CallTypeAndReceiver.TYPE ->
|
is CallTypeAndReceiver.TYPE ->
|
||||||
// we don't need to highlight immediate members in these cases
|
// 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
|
else -> throw RuntimeException() //TODO: see KT-9394
|
||||||
}
|
}
|
||||||
@@ -374,6 +379,6 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
receiverTypes = receiverTypes.map { it.makeNotNullable() }
|
receiverTypes = receiverTypes.map { it.makeNotNullable() }
|
||||||
}
|
}
|
||||||
|
|
||||||
return callTypeAndReceiver.callType to receiverTypes
|
return callTypeAndReceiver to receiverTypes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import org.jetbrains.kotlin.idea.completion.smart.*
|
|||||||
import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier
|
import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier
|
||||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||||
import org.jetbrains.kotlin.idea.core.completion.PackageLookupObject
|
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.idea.util.FuzzyType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean
|
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 descriptorsToSkip = smartCompletion.descriptorsToSkip
|
||||||
private val expectedInfos = smartCompletion.expectedInfos
|
private val expectedInfos = smartCompletion.expectedInfos
|
||||||
|
|
||||||
@@ -235,7 +241,7 @@ class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion
|
|||||||
val (fuzzyTypes, name) = when (o) {
|
val (fuzzyTypes, name) = when (o) {
|
||||||
is DeclarationLookupObject -> {
|
is DeclarationLookupObject -> {
|
||||||
val descriptor = o.descriptor ?: return NO_MATCH_WEIGHT
|
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
|
is ThisItemLookupObject -> smartCastCalculator.types(o.receiverParameter).map { FuzzyType(it, emptyList()) } to null
|
||||||
|
|||||||
+19
-7
@@ -29,11 +29,11 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.completion.*
|
import org.jetbrains.kotlin.idea.completion.*
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
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.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.isAlmostEverything
|
import org.jetbrains.kotlin.idea.util.isAlmostEverything
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
@@ -57,10 +57,22 @@ class SmartCompletion(
|
|||||||
private val inheritorSearchScope: GlobalSearchScope,
|
private val inheritorSearchScope: GlobalSearchScope,
|
||||||
private val toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
private val toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
||||||
private val lookupElementFactory: LookupElementFactory,
|
private val lookupElementFactory: LookupElementFactory,
|
||||||
|
private val callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||||
private val forBasicCompletion: Boolean = false
|
private val forBasicCompletion: Boolean = false
|
||||||
) {
|
) {
|
||||||
private val receiver = (expression as? JetSimpleNameExpression)?.getReceiverExpression()
|
private val expressionWithType = when (callTypeAndReceiver) {
|
||||||
private val expressionWithType = receiver?.parent as? JetExpression ?: expression
|
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<ExpectedInfo> = calcExpectedInfos(expressionWithType)
|
public val expectedInfos: Collection<ExpectedInfo> = calcExpectedInfos(expressionWithType)
|
||||||
|
|
||||||
@@ -141,14 +153,14 @@ class SmartCompletion(
|
|||||||
if (descriptor in descriptorsToSkip) return emptyList()
|
if (descriptor in descriptorsToSkip) return emptyList()
|
||||||
|
|
||||||
val result = SmartList<LookupElement>()
|
val result = SmartList<LookupElement>()
|
||||||
val types = descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator)
|
val types = descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator, callTypeAndReceiver.callType, resolutionFacade)
|
||||||
val infoClassifier = { expectedInfo: ExpectedInfo -> types.classifyExpectedInfo(expectedInfo) }
|
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)
|
lookupElementFactory.createLookupElementsInSmartCompletion(descriptor, bindingContext, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (receiver == null) {
|
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||||
toFunctionReferenceLookupElement(descriptor, expectedInfos.filterFunctionExpected())?.let { result.add(it) }
|
toFunctionReferenceLookupElement(descriptor, expectedInfos.filterFunctionExpected())?.let { result.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +177,7 @@ class SmartCompletion(
|
|||||||
val items = ArrayList<LookupElement>()
|
val items = ArrayList<LookupElement>()
|
||||||
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
|
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
|
||||||
|
|
||||||
if (expectedInfos.isNotEmpty() && receiver == null) {
|
if (expectedInfos.isNotEmpty() && callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||||
TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion)
|
TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion)
|
||||||
.addTo(items, inheritanceSearchers, expectedInfos)
|
.addTo(items, inheritanceSearchers, expectedInfos)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
|||||||
expression?.let {
|
expression?.let {
|
||||||
SmartCompletion(it, resolutionFacade,
|
SmartCompletion(it, resolutionFacade,
|
||||||
bindingContext, isVisibleFilter, prefixMatcher, originalSearchScope,
|
bindingContext, isVisibleFilter, prefixMatcher, originalSearchScope,
|
||||||
toFromOriginalFileMapper, lookupElementFactory)
|
toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,16 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator
|
|||||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.completion.*
|
import org.jetbrains.kotlin.idea.completion.*
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.WithExpressionPrefixInsertHandler
|
import org.jetbrains.kotlin.idea.completion.handlers.WithExpressionPrefixInsertHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler
|
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.idea.util.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
@@ -306,7 +309,17 @@ fun LookupElement.assignSmartCompletionPriority(priority: SmartCompletionItemPri
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DeclarationDescriptor.fuzzyTypesForSmartCompletion(smartCastCalculator: SmartCastCalculator): Collection<FuzzyType> {
|
fun DeclarationDescriptor.fuzzyTypesForSmartCompletion(
|
||||||
|
smartCastCalculator: SmartCastCalculator,
|
||||||
|
callType: CallType<*>,
|
||||||
|
resolutionFacade: ResolutionFacade
|
||||||
|
): Collection<FuzzyType> {
|
||||||
|
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) {
|
if (this is CallableDescriptor) {
|
||||||
var returnType = fuzzyReturnType() ?: return emptyList()
|
var returnType = fuzzyReturnType() ?: return emptyList()
|
||||||
// skip declarations of type Nothing or of generic parameter type which has no real bounds
|
// skip declarations of type Nothing or of generic parameter type which has no real bounds
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun foo(p: () -> Unit){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f(){}
|
||||||
|
|
||||||
|
// ELEMENT: f
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun foo(p: () -> Unit){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(::f)<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f(){}
|
||||||
|
|
||||||
|
// ELEMENT: f
|
||||||
@@ -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::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: extFun
|
||||||
@@ -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, <caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: extFun
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
fun foo(p: () -> Unit){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(::xf<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun xf1(){}
|
||||||
|
fun xf1(s: String){}
|
||||||
|
fun xf2(i: Int){}
|
||||||
|
|
||||||
|
// EXIST: { lookupString:"xf1", itemText:"xf1", tailText: "() (<root>)", typeText: "Unit" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import kotlin.reflect.KProperty0
|
||||||
|
|
||||||
|
fun foo(p: KProperty0<Int>){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(::xT<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
val xTopLevelIntVal = 1
|
||||||
|
var xTopLevelIntVar = 1
|
||||||
|
val xTopLevelStringVal = "1"
|
||||||
|
|
||||||
|
// EXIST: { lookupString:"xTopLevelIntVal", itemText:"xTopLevelIntVal", tailText: " (<root>)", typeText: "Int" }
|
||||||
|
// EXIST: { lookupString:"xTopLevelIntVar", itemText:"xTopLevelIntVar", tailText: " (<root>)", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class C(i: Int){}
|
||||||
|
|
||||||
|
fun foo(p: (Int) -> C){}
|
||||||
|
|
||||||
|
fun bar(){
|
||||||
|
foo(::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: C
|
||||||
@@ -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::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString:"xf1", itemText:"xf1", tailText: "(s: String)", typeText: "Unit" }
|
||||||
|
// EXIST: { lookupString:"xfe1", itemText:"xfe1", tailText: "(s: String) for C in <root>", typeText: "Unit" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
|
fun foo(p: KProperty1<String, Int>){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(String::xT<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <root>", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun foo(p: (() -> Unit) -> Runnable){}
|
||||||
|
|
||||||
|
fun bar(){
|
||||||
|
foo(::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: Runnable
|
||||||
+30
@@ -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);
|
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")
|
@TestMetadata("NoQualifier1.kt")
|
||||||
public void testNoQualifier1() throws Exception {
|
public void testNoQualifier1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/NoQualifier1.kt");
|
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");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/NoQualifier9.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("idea/idea-completion/testData/smart/constructor")
|
||||||
|
|||||||
+24
-12
@@ -113,6 +113,30 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("ClassInClassObject.kt")
|
||||||
public void testClassInClassObject() throws Exception {
|
public void testClassInClassObject() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/ClassInClassObject.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/ClassInClassObject.kt");
|
||||||
@@ -359,18 +383,6 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("GenericFunction.kt")
|
||||||
public void testGenericFunction() throws Exception {
|
public void testGenericFunction() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/GenericFunction.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/smart/GenericFunction.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user