Ordinary completion includes some items from smart completion + changed priority for multi-args item in smart completion
#KT-8580 Fixed
This commit is contained in:
+23
-9
@@ -23,14 +23,15 @@ import com.intellij.codeInsight.completion.CompletionType
|
|||||||
import com.intellij.patterns.PatternCondition
|
import com.intellij.patterns.PatternCondition
|
||||||
import com.intellij.patterns.StandardPatterns
|
import com.intellij.patterns.StandardPatterns
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.JavaPsiFacade
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.toExpressionWithType
|
import org.jetbrains.kotlin.idea.completion.smart.toExpressionWithType
|
||||||
import org.jetbrains.kotlin.idea.completion.SmartCastCalculator
|
|
||||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||||
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -94,6 +95,16 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
|
|
||||||
|
private val expectedInfos = if (expression != null)
|
||||||
|
ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor).calculate(expression.toExpressionWithType())
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
private val smartCastCalculator = if (expression != null)
|
||||||
|
SmartCastCalculator(bindingContext, moduleDescriptor, expression)
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
private fun calcCompletionKind(): CompletionKind {
|
private fun calcCompletionKind(): CompletionKind {
|
||||||
if (NamedArgumentCompletion.isOnlyNamedArgumentExpected(position)) {
|
if (NamedArgumentCompletion.isOnlyNamedArgumentExpected(position)) {
|
||||||
return CompletionKind.NAMED_ARGUMENTS_ONLY
|
return CompletionKind.NAMED_ARGUMENTS_ONLY
|
||||||
@@ -241,6 +252,15 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (completionKind != CompletionKind.KEYWORDS_ONLY) {
|
if (completionKind != CompletionKind.KEYWORDS_ONLY) {
|
||||||
|
if (expectedInfos != null && expectedInfos.isNotEmpty()) {
|
||||||
|
@suppress("UNUSED_VARIABLE") // we don't use InheritanceSearcher
|
||||||
|
val (additionalItems, inheritanceSearcher) = SmartCompletion(
|
||||||
|
expression!!, resolutionFacade, moduleDescriptor, bindingContext, isVisibleFilter, inDescriptor,
|
||||||
|
prefixMatcher, GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory)
|
||||||
|
.additionalItems(expectedInfos, smartCastCalculator!!, itemsToSkip = emptySet(), forOrdinaryCompletion = true)
|
||||||
|
collector.addElements(additionalItems)
|
||||||
|
}
|
||||||
|
|
||||||
flushToResultSet()
|
flushToResultSet()
|
||||||
|
|
||||||
if (!configuration.completeNonImportedDeclarations && isNoQualifierContext()) {
|
if (!configuration.completeNonImportedDeclarations && isNoQualifierContext()) {
|
||||||
@@ -284,14 +304,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
sorter = sorter.weighBefore(DeprecatedWeigher.toString(), ParameterNameAndTypeCompletion.Weigher)
|
sorter = sorter.weighBefore(DeprecatedWeigher.toString(), ParameterNameAndTypeCompletion.Weigher)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression != null) {
|
if (expectedInfos != null && expectedInfos.isNotEmpty()) {
|
||||||
val expressionWithType = expression.toExpressionWithType()
|
sorter = sorter.weighBefore(KindWeigher.toString(), ExpectedInfoMatchWeigher(expectedInfos, smartCastCalculator!!), SmartCompletionPriorityWeigher)
|
||||||
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor).calculate(expressionWithType)
|
|
||||||
|
|
||||||
if (expectedInfos != null && expectedInfos.isNotEmpty()) {
|
|
||||||
val smartCastCalculator = SmartCastCalculator(bindingContext, moduleDescriptor, expression)
|
|
||||||
sorter = sorter.weighBefore(KindWeigher.toString(), ExpectedInfoMatchWeigher(expectedInfos, smartCastCalculator))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sorter
|
return sorter
|
||||||
|
|||||||
@@ -179,6 +179,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
protected val indicesHelper: KotlinIndicesHelper
|
protected val indicesHelper: KotlinIndicesHelper
|
||||||
get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, isVisibleFilter, true)
|
get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, isVisibleFilter, true)
|
||||||
|
|
||||||
|
protected val toFromOriginalFileMapper: ToFromOriginalFileMapper
|
||||||
|
= ToFromOriginalFileMapper(parameters.originalFile as JetFile, position.containingFile as JetFile, parameters.offset)
|
||||||
|
|
||||||
protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean {
|
protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean {
|
||||||
if (descriptor is TypeParameterDescriptor && !isTypeParameterVisible(descriptor)) return false
|
if (descriptor is TypeParameterDescriptor && !isTypeParameterVisible(descriptor)) return false
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import org.jetbrains.kotlin.types.typeUtil.nullability
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
enum class ItemPriority {
|
enum class ItemPriority {
|
||||||
MULTIPLE_ARGUMENTS_ITEM,
|
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
BACKING_FIELD,
|
BACKING_FIELD,
|
||||||
NAMED_PARAMETER
|
NAMED_PARAMETER
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.lookup.WeighingContext
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.*
|
import org.jetbrains.kotlin.idea.completion.smart.*
|
||||||
import org.jetbrains.kotlin.idea.completion.SmartCastCalculator
|
|
||||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
@@ -189,34 +188,43 @@ class ExpectedInfoMatchWeigher(
|
|||||||
private val smartCastCalculator: SmartCastCalculator
|
private val smartCastCalculator: SmartCastCalculator
|
||||||
) : LookupElementWeigher("kotlin.expectedInfoMatch") {
|
) : LookupElementWeigher("kotlin.expectedInfoMatch") {
|
||||||
|
|
||||||
private val NO_MATCH = 0L
|
private fun fullMatchWeight(nameSimilarity: Int): Long {
|
||||||
|
return -((3L shl 32) + nameSimilarity)
|
||||||
|
}
|
||||||
|
|
||||||
private fun fullMatch(nameSimilarity: Int): Long {
|
private fun ifNotNullMatchWeight(nameSimilarity: Int): Long {
|
||||||
return -((2L shl 32) + nameSimilarity)
|
return -((2L shl 32) + nameSimilarity)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ifNotNullMatch(nameSimilarity: Int): Long {
|
private fun smartCompletionItemWeight(nameSimilarity: Int): Long {
|
||||||
return -((1L shl 32) + nameSimilarity)
|
return -((1L shl 32) + nameSimilarity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val NO_MATCH_WEIGHT = 0L
|
||||||
|
|
||||||
override fun weigh(element: LookupElement): Long {
|
override fun weigh(element: LookupElement): Long {
|
||||||
|
val smartCompletionPriority = element.getUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY)
|
||||||
|
if (smartCompletionPriority != null) { // it's an "additional item" came from smart completion, don't match it against expected type
|
||||||
|
return smartCompletionItemWeight(element.getUserData(NAME_SIMILARITY_KEY) ?: 0)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: keywords with type
|
// TODO: keywords with type
|
||||||
val o = element.`object`
|
val o = element.`object`
|
||||||
val (fuzzyTypes, name) = when (o) {
|
val (fuzzyTypes, name) = when (o) {
|
||||||
is DeclarationLookupObject -> {
|
is DeclarationLookupObject -> {
|
||||||
val descriptor = o.descriptor ?: return NO_MATCH
|
val descriptor = o.descriptor ?: return NO_MATCH_WEIGHT
|
||||||
descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator) to descriptor.name
|
descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator) 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
|
||||||
|
|
||||||
else -> return NO_MATCH
|
else -> return NO_MATCH_WEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fuzzyTypes.isEmpty()) return NO_MATCH
|
if (fuzzyTypes.isEmpty()) return NO_MATCH_WEIGHT
|
||||||
|
|
||||||
val classified: Collection<Pair<ExpectedInfo, ExpectedInfoClassification>> = expectedInfos.map { it to fuzzyTypes.classifyExpectedInfo(it) }
|
val classified: Collection<Pair<ExpectedInfo, ExpectedInfoClassification>> = expectedInfos.map { it to fuzzyTypes.classifyExpectedInfo(it) }
|
||||||
if (classified.all { it.second == ExpectedInfoClassification.noMatch }) return NO_MATCH
|
if (classified.all { it.second == ExpectedInfoClassification.noMatch }) return NO_MATCH_WEIGHT
|
||||||
|
|
||||||
val nameSimilarity = if (name != null) {
|
val nameSimilarity = if (name != null) {
|
||||||
val matchingInfos = classified.filter { it.second != ExpectedInfoClassification.noMatch }.map { it.first }
|
val matchingInfos = classified.filter { it.second != ExpectedInfoClassification.noMatch }.map { it.first }
|
||||||
@@ -227,8 +235,8 @@ class ExpectedInfoMatchWeigher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return if (classified.any { it.second.isMatch() })
|
return if (classified.any { it.second.isMatch() })
|
||||||
fullMatch(nameSimilarity)
|
fullMatchWeight(nameSimilarity)
|
||||||
else
|
else
|
||||||
ifNotNullMatch(nameSimilarity)
|
ifNotNullMatchWeight(nameSimilarity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,10 @@ object LambdaItems {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addToCollection(collection: MutableCollection<LookupElement>, functionExpectedInfos: Collection<ExpectedInfo>) {
|
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedInfos: Collection<ExpectedInfo>) {
|
||||||
|
val functionExpectedInfos = expectedInfos.filterFunctionExpected()
|
||||||
|
if (functionExpectedInfos.isEmpty()) return
|
||||||
|
|
||||||
val distinctTypes = functionExpectedInfos
|
val distinctTypes = functionExpectedInfos
|
||||||
.map { it.fuzzyType?.type }
|
.map { it.fuzzyType?.type }
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
|
|||||||
+1
-2
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
|
import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
|
||||||
import org.jetbrains.kotlin.idea.completion.*
|
import org.jetbrains.kotlin.idea.completion.*
|
||||||
import org.jetbrains.kotlin.idea.completion.SmartCastCalculator
|
|
||||||
import org.jetbrains.kotlin.psi.JetExpression
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
import org.jetbrains.kotlin.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -84,7 +83,7 @@ class MultipleArgumentsItemProvider(val bindingContext: BindingContext,
|
|||||||
}
|
}
|
||||||
.withIcon(compoundIcon)
|
.withIcon(compoundIcon)
|
||||||
.addTail(Tail.RPARENTH) //TODO: support square brackets
|
.addTail(Tail.RPARENTH) //TODO: support square brackets
|
||||||
.assignPriority(ItemPriority.MULTIPLE_ARGUMENTS_ITEM)
|
.assignSmartCompletionPriority(SmartCompletionItemPriority.MULTIPLE_ARGUMENTS_ITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun variableInScope(parameter: ValueParameterDescriptor, scope: JetScope): VariableDescriptor? {
|
private fun variableInScope(parameter: ValueParameterDescriptor, scope: JetScope): VariableDescriptor? {
|
||||||
|
|||||||
+24
-13
@@ -25,7 +25,6 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator
|
|||||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
@@ -117,8 +116,6 @@ class SmartCompletion(
|
|||||||
|
|
||||||
val itemsToSkip = calcItemsToSkip(expressionWithType)
|
val itemsToSkip = calcItemsToSkip(expressionWithType)
|
||||||
|
|
||||||
val functionExpectedInfos = expectedInfos.filter { it.fuzzyType != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(it.fuzzyType!!.type) }
|
|
||||||
|
|
||||||
fun filterDeclaration(descriptor: DeclarationDescriptor): Collection<LookupElement> {
|
fun filterDeclaration(descriptor: DeclarationDescriptor): Collection<LookupElement> {
|
||||||
if (descriptor in itemsToSkip) return emptyList()
|
if (descriptor in itemsToSkip) return emptyList()
|
||||||
|
|
||||||
@@ -137,29 +134,42 @@ class SmartCompletion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (receiver == null) {
|
if (receiver == null) {
|
||||||
toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) }
|
toFunctionReferenceLookupElement(descriptor, expectedInfos.filterFunctionExpected())?.let { result.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
val additionalItems = ArrayList<LookupElement>()
|
val (additionalItems, inheritanceSearcher) = additionalItems(expectedInfos, smartCastCalculator, itemsToSkip)
|
||||||
|
|
||||||
|
return Result(::filterDeclaration, additionalItems, inheritanceSearcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun additionalItems(
|
||||||
|
expectedInfos: Collection<ExpectedInfo>,
|
||||||
|
smartCastCalculator: SmartCastCalculator,
|
||||||
|
itemsToSkip: Set<DeclarationDescriptor>,
|
||||||
|
forOrdinaryCompletion: Boolean = false
|
||||||
|
): Pair<Collection<LookupElement>, InheritanceItemsSearcher?> {
|
||||||
|
val items = ArrayList<LookupElement>()
|
||||||
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
|
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
|
||||||
if (receiver == null) {
|
if (receiver == null) {
|
||||||
TypeInstantiationItems(resolutionFacade, moduleDescriptor, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory)
|
TypeInstantiationItems(resolutionFacade, moduleDescriptor, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forOrdinaryCompletion)
|
||||||
.addTo(additionalItems, inheritanceSearchers, expectedInfos)
|
.addTo(items, inheritanceSearchers, expectedInfos)
|
||||||
|
|
||||||
if (expression is JetSimpleNameExpression) {
|
if (expression is JetSimpleNameExpression) {
|
||||||
StaticMembers(bindingContext, lookupElementFactory).addToCollection(additionalItems, expectedInfos, expression, itemsToSkip)
|
StaticMembers(bindingContext, lookupElementFactory).addToCollection(items, expectedInfos, expression, itemsToSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalItems.addThisItems(expression, expectedInfos, smartCastCalculator)
|
if (!forOrdinaryCompletion) {
|
||||||
|
items.addThisItems(expression, expectedInfos, smartCastCalculator)
|
||||||
|
|
||||||
LambdaItems.addToCollection(additionalItems, functionExpectedInfos)
|
LambdaItems.addToCollection(items, expectedInfos)
|
||||||
|
|
||||||
KeywordValues.addToCollection(additionalItems, expectedInfos, expression)
|
KeywordValues.addToCollection(items, expectedInfos, expression) //TODO: in ordinary completion?
|
||||||
|
}
|
||||||
|
|
||||||
MultipleArgumentsItemProvider(bindingContext, smartCastCalculator).addToCollection(additionalItems, expectedInfos, expression)
|
MultipleArgumentsItemProvider(bindingContext, smartCastCalculator).addToCollection(items, expectedInfos, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritanceSearcher = if (inheritanceSearchers.isNotEmpty())
|
val inheritanceSearcher = if (inheritanceSearchers.isNotEmpty())
|
||||||
@@ -170,7 +180,8 @@ class SmartCompletion(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
return Result(::filterDeclaration, additionalItems, inheritanceSearcher)
|
|
||||||
|
return Pair(items, inheritanceSearcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableCollection<LookupElement>.addThisItems(place: JetExpression, expectedInfos: Collection<ExpectedInfo>, smartCastCalculator: SmartCastCalculator) {
|
private fun MutableCollection<LookupElement>.addThisItems(place: JetExpression, expectedInfos: Collection<ExpectedInfo>, smartCastCalculator: SmartCastCalculator) {
|
||||||
|
|||||||
+1
-4
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.idea.util.CallType
|
|||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
||||||
import org.jetbrains.kotlin.psi.FunctionLiteralArgument
|
import org.jetbrains.kotlin.psi.FunctionLiteralArgument
|
||||||
import org.jetbrains.kotlin.psi.JetCodeFragment
|
import org.jetbrains.kotlin.psi.JetCodeFragment
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
|
||||||
import org.jetbrains.kotlin.psi.ValueArgumentName
|
import org.jetbrains.kotlin.psi.ValueArgumentName
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
|
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
|
||||||
@@ -46,13 +45,11 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
val mapper = ToFromOriginalFileMapper(parameters.getOriginalFile() as JetFile, position.getContainingFile() as JetFile, parameters.getOffset())
|
|
||||||
|
|
||||||
addFunctionLiteralArgumentCompletions()
|
addFunctionLiteralArgumentCompletions()
|
||||||
|
|
||||||
val completion = SmartCompletion(expression, resolutionFacade, moduleDescriptor,
|
val completion = SmartCompletion(expression, resolutionFacade, moduleDescriptor,
|
||||||
bindingContext, isVisibleFilter, inDescriptor, prefixMatcher, originalSearchScope,
|
bindingContext, isVisibleFilter, inDescriptor, prefixMatcher, originalSearchScope,
|
||||||
mapper, lookupElementFactory)
|
toFromOriginalFileMapper, lookupElementFactory)
|
||||||
val result = completion.execute()
|
val result = completion.execute()
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
collector.addElements(result.additionalItems)
|
collector.addElements(result.additionalItems)
|
||||||
|
|||||||
+5
-2
@@ -57,7 +57,8 @@ class TypeInstantiationItems(
|
|||||||
val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
||||||
val toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
val toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
||||||
val inheritorSearchScope: GlobalSearchScope,
|
val inheritorSearchScope: GlobalSearchScope,
|
||||||
val lookupElementFactory: LookupElementFactory
|
val lookupElementFactory: LookupElementFactory,
|
||||||
|
val forOrdinaryCompletion: Boolean
|
||||||
) {
|
) {
|
||||||
public fun addTo(
|
public fun addTo(
|
||||||
items: MutableCollection<LookupElement>,
|
items: MutableCollection<LookupElement>,
|
||||||
@@ -88,7 +89,7 @@ class TypeInstantiationItems(
|
|||||||
val typeArgs = type.getArguments()
|
val typeArgs = type.getArguments()
|
||||||
items.addIfNotNull(createTypeInstantiationItem(classifier, typeArgs, tail))
|
items.addIfNotNull(createTypeInstantiationItem(classifier, typeArgs, tail))
|
||||||
|
|
||||||
if (!KotlinBuiltIns.isAny(classifier)) { // do not search inheritors of Any
|
if (!forOrdinaryCompletion && !KotlinBuiltIns.isAny(classifier)) { // do not search inheritors of Any
|
||||||
inheritanceSearchers.addInheritorSearcher(classifier, classifier, typeArgs, tail)
|
inheritanceSearchers.addInheritorSearcher(classifier, classifier, typeArgs, tail)
|
||||||
|
|
||||||
val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(classifier))
|
val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(classifier))
|
||||||
@@ -133,6 +134,8 @@ class TypeInstantiationItems(
|
|||||||
if (classifier.isInner()) return null
|
if (classifier.isInner()) return null
|
||||||
|
|
||||||
val isAbstract = classifier.getModality() == Modality.ABSTRACT
|
val isAbstract = classifier.getModality() == Modality.ABSTRACT
|
||||||
|
if (forOrdinaryCompletion && isAbstract) return null
|
||||||
|
|
||||||
val allConstructors = classifier.getConstructors()
|
val allConstructors = classifier.getConstructors()
|
||||||
val visibleConstructors = allConstructors.filter {
|
val visibleConstructors = allConstructors.filter {
|
||||||
if (isAbstract)
|
if (isAbstract)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.lookup.LookupElement
|
|||||||
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
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.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.*
|
||||||
@@ -297,6 +298,7 @@ fun LookupElementFactory.createLookupElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class SmartCompletionItemPriority {
|
enum class SmartCompletionItemPriority {
|
||||||
|
MULTIPLE_ARGUMENTS_ITEM,
|
||||||
IT,
|
IT,
|
||||||
TRUE,
|
TRUE,
|
||||||
FALSE,
|
FALSE,
|
||||||
@@ -344,3 +346,7 @@ fun DeclarationDescriptor.fuzzyTypesForSmartCompletion(smartCastCalculator: Smar
|
|||||||
fun JetExpression.toExpressionWithType(): JetExpression {
|
fun JetExpression.toExpressionWithType(): JetExpression {
|
||||||
return (this as? JetSimpleNameExpression)?.getReceiverExpression()?.parent as? JetExpression ?: this
|
return (this as? JetSimpleNameExpression)?.getReceiverExpression()?.parent as? JetExpression ?: this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Collection<ExpectedInfo>.filterFunctionExpected()
|
||||||
|
= filter { it.fuzzyType != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(it.fuzzyType!!.type) }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
enum class E {
|
||||||
|
A,
|
||||||
|
B
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): E {
|
||||||
|
return <caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString:"A", itemText:"E.A", tailText:" (<root>)", typeText:"E" }
|
||||||
|
// EXIST: { lookupString:"B", itemText:"E.B", tailText:" (<root>)", typeText:"E" }
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun foo(): java.util.Calendar = get<caret>
|
||||||
|
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"() (java.util)", typeText:"Calendar!" }
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone!) (java.util)", typeText:"Calendar!" }
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone!, Locale!) (java.util)", typeText:"Calendar!" }
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun foo(): java.util.Calendar = Ca<caret>
|
||||||
|
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"() (java.util)", typeText:"Calendar!" }
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone!) (java.util)", typeText:"Calendar!" }
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone!, Locale!) (java.util)", typeText:"Calendar!" }
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun foo(a: Int, b: String, c: String) {}
|
||||||
|
|
||||||
|
fun bar(b: String, a: Int, c: String) {
|
||||||
|
foo(<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: "a, b, c"
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
class CC {
|
||||||
|
companion object {
|
||||||
|
fun getInstance(): CC {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): CC {
|
||||||
|
return C<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ORDER: CC
|
||||||
|
// ORDER: getInstance
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
enum class EE {
|
||||||
|
A,
|
||||||
|
B
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): EE {
|
||||||
|
return E<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ORDER: valueOf
|
||||||
|
// ORDER: A
|
||||||
|
// ORDER: B
|
||||||
|
// ORDER: EE
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
interface I1
|
||||||
|
interface I2
|
||||||
|
|
||||||
|
fun foo(a: I1, b: I2, c: I1) {}
|
||||||
|
|
||||||
|
fun bar(b: I2, a: I1, c: I1) {
|
||||||
|
foo(<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ORDER: a
|
||||||
|
// ORDER: c
|
||||||
|
// ORDER: "a, b, c"
|
||||||
@@ -8,10 +8,10 @@ fun foo(pFoo: Boolean, s: String) {
|
|||||||
foo(<caret>)
|
foo(<caret>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORDER: "pFoo, s"
|
|
||||||
// ORDER: pFoo
|
// ORDER: pFoo
|
||||||
// ORDER: nullableFoo
|
// ORDER: nullableFoo
|
||||||
// ORDER: nullableFoo
|
// ORDER: nullableFoo
|
||||||
|
// ORDER: "pFoo, s"
|
||||||
// ORDER: true
|
// ORDER: true
|
||||||
// ORDER: false
|
// ORDER: false
|
||||||
// ORDER: local
|
// ORDER: local
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
fun foo(a: Int, b: String, c: String) {}
|
fun foo(xa: Int, xb: String, xc: Int) {}
|
||||||
|
|
||||||
fun bar(b: String, a: Int, c: String) {
|
fun bar(xb: String, xa: Int, xc: Int) {
|
||||||
foo(<caret>)
|
foo(<caret>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORDER: "a, b, c"
|
// ORDER: xa
|
||||||
// ORDER: a
|
// ORDER: "xa, xb, xc"
|
||||||
|
// ORDER: xc
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ class C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORDER: "pFoo, s"
|
|
||||||
// ORDER: pFoo
|
// ORDER: pFoo
|
||||||
// ORDER: nullableFoo
|
// ORDER: nullableFoo
|
||||||
// ORDER: nullableFoo
|
// ORDER: nullableFoo
|
||||||
|
// ORDER: "pFoo, s"
|
||||||
// ORDER: this
|
// ORDER: this
|
||||||
// ORDER: local
|
// ORDER: local
|
||||||
// ORDER: apply
|
// ORDER: apply
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ fun foo(pFoo: C, s: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ORDER: "pFoo, s"
|
|
||||||
// ORDER: pFoo
|
// ORDER: pFoo
|
||||||
// ORDER: nullableFoo
|
// ORDER: nullableFoo
|
||||||
// ORDER: nullableFoo
|
// ORDER: nullableFoo
|
||||||
// ORDER: INSTANCE_FOO
|
// ORDER: INSTANCE_FOO
|
||||||
|
// ORDER: "pFoo, s"
|
||||||
// ORDER: local
|
// ORDER: local
|
||||||
// ORDER: nonNullable
|
// ORDER: nonNullable
|
||||||
// ORDER: nullableX
|
// ORDER: nullableX
|
||||||
|
|||||||
+33
@@ -1306,6 +1306,39 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/fromSmart")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class FromSmart extends AbstractJSBasicCompletionTest {
|
||||||
|
public void testAllFilesPresentInFromSmart() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/fromSmart"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumEntries.kt")
|
||||||
|
public void testEnumEntries() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/EnumEntries.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JavaStaticMethods.kt")
|
||||||
|
public void testJavaStaticMethods() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/JavaStaticMethods.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JavaStaticMethods2.kt")
|
||||||
|
public void testJavaStaticMethods2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/JavaStaticMethods2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultipleArgs.kt")
|
||||||
|
public void testMultipleArgs() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/MultipleArgs.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/immediateMembers")
|
@TestMetadata("idea/idea-completion/testData/basic/common/immediateMembers")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+33
@@ -1306,6 +1306,39 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/fromSmart")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class FromSmart extends AbstractJvmBasicCompletionTest {
|
||||||
|
public void testAllFilesPresentInFromSmart() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/fromSmart"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumEntries.kt")
|
||||||
|
public void testEnumEntries() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/EnumEntries.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JavaStaticMethods.kt")
|
||||||
|
public void testJavaStaticMethods() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/JavaStaticMethods.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JavaStaticMethods2.kt")
|
||||||
|
public void testJavaStaticMethods2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/JavaStaticMethods2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultipleArgs.kt")
|
||||||
|
public void testMultipleArgs() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromSmart/MultipleArgs.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/immediateMembers")
|
@TestMetadata("idea/idea-completion/testData/basic/common/immediateMembers")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+18
@@ -151,6 +151,18 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/weighers/basic/expectedInfo"), Pattern.compile("^([^\\.]+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/weighers/basic/expectedInfo"), Pattern.compile("^([^\\.]+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("CompanionObjectMethod.kt")
|
||||||
|
public void testCompanionObjectMethod() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/CompanionObjectMethod.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumEntries.kt")
|
||||||
|
public void testEnumEntries() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/EnumEntries.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ExpectedType.kt")
|
@TestMetadata("ExpectedType.kt")
|
||||||
public void testExpectedType() throws Exception {
|
public void testExpectedType() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/ExpectedType.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/ExpectedType.kt");
|
||||||
@@ -163,6 +175,12 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultiArgsItem.kt")
|
||||||
|
public void testMultiArgsItem() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/MultiArgsItem.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NameSimilarity.kt")
|
@TestMetadata("NameSimilarity.kt")
|
||||||
public void testNameSimilarity() throws Exception {
|
public void testNameSimilarity() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/NameSimilarity.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/NameSimilarity.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user