A::class and A::class.java supported in smart completion too
This commit is contained in:
@@ -112,6 +112,7 @@ public class ReferenceVariantsHelper(
|
|||||||
is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.UNARY -> receiverExpression = null // can it happen at all?
|
is CallTypeAndReceiver.UNARY -> receiverExpression = null // can it happen at all?
|
||||||
|
is CallTypeAndReceiver.UNKNOWN -> return emptyList()
|
||||||
else -> throw RuntimeException() //TODO: see KT-9394
|
else -> throw RuntimeException() //TODO: see KT-9394
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
|
||||||
public sealed class CallType<TReceiver : JetElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
public sealed class CallType<TReceiver : JetElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
||||||
|
object UNKNOWN : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
||||||
|
|
||||||
object DEFAULT : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
object DEFAULT : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
||||||
|
|
||||||
object DOT : CallType<JetExpression>(DescriptorKindFilter.ALL)
|
object DOT : CallType<JetExpression>(DescriptorKindFilter.ALL)
|
||||||
@@ -78,6 +80,7 @@ public sealed class CallTypeAndReceiver<TReceiver : JetElement?, TCallType : Cal
|
|||||||
val callType: TCallType,
|
val callType: TCallType,
|
||||||
val receiver: TReceiver
|
val receiver: TReceiver
|
||||||
) {
|
) {
|
||||||
|
object UNKNOWN : CallTypeAndReceiver<Nothing?, CallType.UNKNOWN>(CallType.UNKNOWN, null)
|
||||||
object DEFAULT : CallTypeAndReceiver<Nothing?, CallType.DEFAULT>(CallType.DEFAULT, null)
|
object DEFAULT : CallTypeAndReceiver<Nothing?, CallType.DEFAULT>(CallType.DEFAULT, null)
|
||||||
class DOT(receiver: JetExpression) : CallTypeAndReceiver<JetExpression, CallType.DOT>(CallType.DOT, receiver)
|
class DOT(receiver: JetExpression) : CallTypeAndReceiver<JetExpression, CallType.DOT>(CallType.DOT, receiver)
|
||||||
class SAFE(receiver: JetExpression) : CallTypeAndReceiver<JetExpression, CallType.SAFE>(CallType.SAFE, receiver)
|
class SAFE(receiver: JetExpression) : CallTypeAndReceiver<JetExpression, CallType.SAFE>(CallType.SAFE, receiver)
|
||||||
|
|||||||
+30
-18
@@ -20,7 +20,7 @@ import com.intellij.codeInsight.completion.CompletionParameters
|
|||||||
import com.intellij.codeInsight.completion.CompletionResultSet
|
import com.intellij.codeInsight.completion.CompletionResultSet
|
||||||
import com.intellij.codeInsight.completion.CompletionSorter
|
import com.intellij.codeInsight.completion.CompletionSorter
|
||||||
import com.intellij.codeInsight.completion.CompletionType
|
import com.intellij.codeInsight.completion.CompletionType
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.template.TemplateManager
|
import com.intellij.codeInsight.template.TemplateManager
|
||||||
import com.intellij.patterns.PatternCondition
|
import com.intellij.patterns.PatternCondition
|
||||||
import com.intellij.patterns.StandardPatterns
|
import com.intellij.patterns.StandardPatterns
|
||||||
@@ -33,6 +33,7 @@ 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.ExpectedInfoClassification
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.SMART_COMPLETION_ITEM_PRIORITY_KEY
|
import org.jetbrains.kotlin.idea.completion.smart.SMART_COMPLETION_ITEM_PRIORITY_KEY
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
|
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
|
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
|
||||||
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
||||||
parameters: CompletionParameters,
|
parameters: CompletionParameters,
|
||||||
@@ -103,8 +105,9 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
|
|
||||||
private val smartCompletion = expression?.let {
|
private val smartCompletion = expression?.let {
|
||||||
SmartCompletion(
|
SmartCompletion(
|
||||||
it, resolutionFacade, bindingContext, isVisibleFilter, prefixMatcher,
|
it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter, prefixMatcher,
|
||||||
GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver, forBasicCompletion = true
|
GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver,
|
||||||
|
isJvmModule, forBasicCompletion = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,9 +275,31 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun completeKeywords() {
|
private fun completeKeywords() {
|
||||||
|
val keywordsToSkip = HashSet<String>()
|
||||||
|
|
||||||
|
val keywordValueConsumer = object : KeywordValues.Consumer {
|
||||||
|
override fun consume(lookupString: String, expectedInfoClassifier: (ExpectedInfo) -> ExpectedInfoClassification, priority: SmartCompletionItemPriority, factory: () -> LookupElement) {
|
||||||
|
keywordsToSkip.add(lookupString)
|
||||||
|
val lookupElement = factory()
|
||||||
|
val matched = expectedInfos.any {
|
||||||
|
val classification = expectedInfoClassifier(it)
|
||||||
|
assert(!classification.makeNotNullable) { "Nullable keyword values not supported" }
|
||||||
|
classification.isMatch()
|
||||||
|
}
|
||||||
|
if (matched) {
|
||||||
|
lookupElement.putUserData(SmartCompletionInBasicWeigher.KEYWORD_VALUE_MATCHED_KEY, matched)
|
||||||
|
lookupElement.putUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY, priority)
|
||||||
|
}
|
||||||
|
collector.addElement(lookupElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeywordValues.process(keywordValueConsumer, callTypeAndReceiver, bindingContext, resolutionFacade, moduleDescriptor, isJvmModule)
|
||||||
|
|
||||||
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
|
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
|
||||||
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
|
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
|
||||||
val keyword = lookupElement.getLookupString()
|
val keyword = lookupElement.lookupString
|
||||||
|
if (keyword in keywordsToSkip) return@complete
|
||||||
|
|
||||||
when (keyword) {
|
when (keyword) {
|
||||||
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
|
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
|
||||||
"this" -> {
|
"this" -> {
|
||||||
@@ -307,20 +332,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
"class" -> {
|
"class" -> {
|
||||||
if (callTypeAndReceiver is CallTypeAndReceiver.CALLABLE_REFERENCE) {
|
if (callTypeAndReceiver !is CallTypeAndReceiver.CALLABLE_REFERENCE) { // otherwise it should be handled by KeywordValues
|
||||||
if (callTypeAndReceiver.receiver != null) {
|
|
||||||
collector.addElement(lookupElement)
|
|
||||||
|
|
||||||
if (!ProjectStructureUtil.isJsKotlinModule(parameters.originalFile as JetFile)) {
|
|
||||||
val element = LookupElementBuilder.create(KeywordLookupObject(), "class.java")
|
|
||||||
.withPresentableText("class")
|
|
||||||
.withTailText(".java")
|
|
||||||
.bold()
|
|
||||||
collector.addElement(element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
collector.addElement(lookupElement)
|
collector.addElement(lookupElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
|||||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||||
import org.jetbrains.kotlin.idea.core.*
|
import org.jetbrains.kotlin.idea.core.*
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
|
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
import org.jetbrains.kotlin.idea.util.CallType
|
||||||
@@ -74,6 +75,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
protected val resolutionFacade = file.getResolutionFacade()
|
protected val resolutionFacade = file.getResolutionFacade()
|
||||||
protected val moduleDescriptor = resolutionFacade.moduleDescriptor
|
protected val moduleDescriptor = resolutionFacade.moduleDescriptor
|
||||||
protected val project = position.getProject()
|
protected val project = position.getProject()
|
||||||
|
protected val isJvmModule = !ProjectStructureUtil.isJsKotlinModule(parameters.originalFile as JetFile)
|
||||||
|
|
||||||
protected val nameExpression: JetSimpleNameExpression?
|
protected val nameExpression: JetSimpleNameExpression?
|
||||||
protected val expression: JetExpression?
|
protected val expression: JetExpression?
|
||||||
@@ -292,8 +294,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Collection<CallableDescriptor>.filterShadowedNonImported(): Collection<CallableDescriptor> {
|
private fun Collection<CallableDescriptor>.filterShadowedNonImported(): Collection<CallableDescriptor> {
|
||||||
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression!!)
|
return ShadowedDeclarationsFilter(bindingContext, resolutionFacade, nameExpression!!, callTypeAndReceiver)
|
||||||
return ShadowedDeclarationsFilter(bindingContext, resolutionFacade, nameExpression, callTypeAndReceiver)
|
|
||||||
.filterNonImported(this, referenceVariants)
|
.filterNonImported(this, referenceVariants)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +306,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLookupElementFactory(callType: CallType<*>, receiverTypes: Collection<JetType>?): LookupElementFactory {
|
private fun createLookupElementFactory(callType: CallType<*>?, receiverTypes: Collection<JetType>?): LookupElementFactory {
|
||||||
val contextVariablesProvider = {
|
val contextVariablesProvider = {
|
||||||
nameExpression?.let {
|
nameExpression?.let {
|
||||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT)
|
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT)
|
||||||
@@ -321,7 +322,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
|
|
||||||
private fun detectCallTypeAndReceiverTypes(): Pair<CallTypeAndReceiver<*, *>, Collection<JetType>?> {
|
private fun detectCallTypeAndReceiverTypes(): Pair<CallTypeAndReceiver<*, *>, Collection<JetType>?> {
|
||||||
if (nameExpression == null) {
|
if (nameExpression == null) {
|
||||||
return CallTypeAndReceiver.DEFAULT to null
|
return CallTypeAndReceiver.UNKNOWN to null
|
||||||
}
|
}
|
||||||
|
|
||||||
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression)
|
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression)
|
||||||
@@ -346,7 +347,8 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
|
|
||||||
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
|
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
|
||||||
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
||||||
is CallTypeAndReceiver.TYPE ->
|
is CallTypeAndReceiver.TYPE,
|
||||||
|
is CallTypeAndReceiver.UNKNOWN ->
|
||||||
// we don't need to highlight immediate members in these cases
|
// we don't need to highlight immediate members in these cases
|
||||||
return callTypeAndReceiver to null
|
return callTypeAndReceiver to null
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,8 @@ sealed class ArgumentPositionData(val function: FunctionDescriptor) : ExpectedIn
|
|||||||
|
|
||||||
class ReturnValueAdditionalData(val callable: CallableDescriptor) : ExpectedInfo.AdditionalData
|
class ReturnValueAdditionalData(val callable: CallableDescriptor) : ExpectedInfo.AdditionalData
|
||||||
|
|
||||||
|
object WhenEntryAdditionalData : ExpectedInfo.AdditionalData
|
||||||
|
|
||||||
class ExpectedInfos(
|
class ExpectedInfos(
|
||||||
val bindingContext: BindingContext,
|
val bindingContext: BindingContext,
|
||||||
val resolutionFacade: ResolutionFacade,
|
val resolutionFacade: ResolutionFacade,
|
||||||
@@ -489,10 +491,10 @@ class ExpectedInfos(
|
|||||||
val subject = whenExpression.getSubjectExpression()
|
val subject = whenExpression.getSubjectExpression()
|
||||||
if (subject != null) {
|
if (subject != null) {
|
||||||
val subjectType = bindingContext.getType(subject) ?: return null
|
val subjectType = bindingContext.getType(subject) ?: return null
|
||||||
return listOf(ExpectedInfo(subjectType, null, null))
|
return listOf(ExpectedInfo(subjectType, null, null, additionalData = WhenEntryAdditionalData))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return listOf(ExpectedInfo(resolutionFacade.moduleDescriptor.builtIns.booleanType, null, null))
|
return listOf(ExpectedInfo(resolutionFacade.moduleDescriptor.builtIns.booleanType, null, null, additionalData = WhenEntryAdditionalData))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -27,12 +27,16 @@ import org.jetbrains.kotlin.types.JetType
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class InsertHandlerProvider(
|
class InsertHandlerProvider(
|
||||||
private val callType: CallType<*>,
|
private val callType: CallType<*>?,
|
||||||
expectedInfosCalculator: () -> Collection<ExpectedInfo>
|
expectedInfosCalculator: () -> Collection<ExpectedInfo>
|
||||||
) {
|
) {
|
||||||
private val expectedInfos by lazy(LazyThreadSafetyMode.NONE) { expectedInfosCalculator() }
|
private val expectedInfos by lazy(LazyThreadSafetyMode.NONE) { expectedInfosCalculator() }
|
||||||
|
|
||||||
public fun insertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
|
public fun insertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
|
||||||
|
if (callType == null) {
|
||||||
|
error("Cannot create InsertHandler when no CallType known")
|
||||||
|
}
|
||||||
|
|
||||||
return when (descriptor) {
|
return when (descriptor) {
|
||||||
is FunctionDescriptor -> {
|
is FunctionDescriptor -> {
|
||||||
val needTypeArguments = needTypeArguments(descriptor)
|
val needTypeArguments = needTypeArguments(descriptor)
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.completion
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
|
import org.jetbrains.kotlin.idea.completion.smart.ExpectedInfoClassification
|
||||||
|
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
|
||||||
|
import org.jetbrains.kotlin.idea.completion.smart.classifyExpectedInfo
|
||||||
|
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.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.types.JetTypeImpl
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean
|
||||||
|
|
||||||
|
object KeywordValues {
|
||||||
|
interface Consumer {
|
||||||
|
fun consume(
|
||||||
|
lookupString: String,
|
||||||
|
expectedInfoClassifier: (ExpectedInfo) -> ExpectedInfoClassification,
|
||||||
|
priority: SmartCompletionItemPriority,
|
||||||
|
factory: () -> LookupElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun process(
|
||||||
|
consumer: Consumer,
|
||||||
|
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||||
|
bindingContext: BindingContext,
|
||||||
|
resolutionFacade: ResolutionFacade,
|
||||||
|
moduleDescriptor: ModuleDescriptor,
|
||||||
|
isJvmModule: Boolean
|
||||||
|
) {
|
||||||
|
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||||
|
val booleanInfoClassifier = classifier@ { info: ExpectedInfo ->
|
||||||
|
// no sense in true or false as when entry
|
||||||
|
if (info.additionalData is WhenEntryAdditionalData) return@classifier ExpectedInfoClassification.noMatch
|
||||||
|
|
||||||
|
if (info.fuzzyType?.type?.isBooleanOrNullableBoolean() ?: false)
|
||||||
|
ExpectedInfoClassification.match(TypeSubstitutor.EMPTY)
|
||||||
|
else
|
||||||
|
ExpectedInfoClassification.noMatch
|
||||||
|
}
|
||||||
|
consumer.consume("true", booleanInfoClassifier, SmartCompletionItemPriority.TRUE) {
|
||||||
|
LookupElementBuilder.create(KeywordLookupObject(), "true").bold()
|
||||||
|
}
|
||||||
|
consumer.consume("false", booleanInfoClassifier, SmartCompletionItemPriority.FALSE) {
|
||||||
|
LookupElementBuilder.create(KeywordLookupObject(), "false").bold()
|
||||||
|
}
|
||||||
|
|
||||||
|
val nullClassifier = { info: ExpectedInfo ->
|
||||||
|
if (info.fuzzyType != null && info.fuzzyType!!.type.isMarkedNullable())
|
||||||
|
ExpectedInfoClassification.match(TypeSubstitutor.EMPTY)
|
||||||
|
else
|
||||||
|
ExpectedInfoClassification.noMatch
|
||||||
|
}
|
||||||
|
consumer.consume("null", nullClassifier, SmartCompletionItemPriority.NULL) {
|
||||||
|
LookupElementBuilder.create(KeywordLookupObject(), "null").bold()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callTypeAndReceiver is CallTypeAndReceiver.CALLABLE_REFERENCE && callTypeAndReceiver.receiver != null) {
|
||||||
|
val qualifierType = bindingContext[BindingContext.TYPE, callTypeAndReceiver.receiver]
|
||||||
|
if (qualifierType != null) {
|
||||||
|
val kClassDescriptor = resolutionFacade.getFrontendService(ReflectionTypes::class.java).kClass
|
||||||
|
val classLiteralType = JetTypeImpl.create(Annotations.EMPTY, kClassDescriptor, false, listOf(TypeProjectionImpl(qualifierType)))
|
||||||
|
val kClassTypes = listOf(FuzzyType(classLiteralType, emptyList()))
|
||||||
|
val kClassClassifier = { info: ExpectedInfo -> kClassTypes.classifyExpectedInfo(info) }
|
||||||
|
consumer.consume("class", kClassClassifier, SmartCompletionItemPriority.CLASS_LITERAL) {
|
||||||
|
LookupElementBuilder.create(KeywordLookupObject(), "class").bold()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isJvmModule) {
|
||||||
|
val javaLangClassDescriptor = resolutionFacade.resolveImportReference(moduleDescriptor, FqName("java.lang.Class"))
|
||||||
|
.singleOrNull() as? ClassDescriptor
|
||||||
|
|
||||||
|
if (javaLangClassDescriptor != null) {
|
||||||
|
val javaLangClassType = JetTypeImpl.create(Annotations.EMPTY, javaLangClassDescriptor, false, listOf(TypeProjectionImpl(qualifierType)))
|
||||||
|
val javaClassTypes = listOf(FuzzyType(javaLangClassType, emptyList()))
|
||||||
|
val javaClassClassifier = { info: ExpectedInfo -> javaClassTypes.classifyExpectedInfo(info) }
|
||||||
|
consumer.consume("class", javaClassClassifier, SmartCompletionItemPriority.CLASS_LITERAL) {
|
||||||
|
LookupElementBuilder.create(KeywordLookupObject(), "class.java")
|
||||||
|
.withPresentableText("class")
|
||||||
|
.withTailText(".java")
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
|||||||
class LookupElementFactory(
|
class LookupElementFactory(
|
||||||
private val resolutionFacade: ResolutionFacade,
|
private val resolutionFacade: ResolutionFacade,
|
||||||
private val receiverTypes: Collection<JetType>?,
|
private val receiverTypes: Collection<JetType>?,
|
||||||
private val callType: CallType<*>,
|
private val callType: CallType<*>?,
|
||||||
private val isInStringTemplateAfterDollar: Boolean,
|
private val isInStringTemplateAfterDollar: Boolean,
|
||||||
public val insertHandlerProvider: InsertHandlerProvider,
|
public val insertHandlerProvider: InsertHandlerProvider,
|
||||||
contextVariablesProvider: () -> Collection<VariableDescriptor>
|
contextVariablesProvider: () -> Collection<VariableDescriptor>
|
||||||
@@ -132,7 +132,7 @@ class LookupElementFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun handleInsert(context: InsertionContext) {
|
override fun handleInsert(context: InsertionContext) {
|
||||||
KotlinFunctionInsertHandler(callType, inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this)
|
KotlinFunctionInsertHandler(callType!!, inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ class LookupElementFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun handleInsert(context: InsertionContext) {
|
override fun handleInsert(context: InsertionContext) {
|
||||||
KotlinFunctionInsertHandler(callType, inputTypeArguments = needTypeArguments, inputValueArguments = false, argumentText = argumentText).handleInsert(context, this)
|
KotlinFunctionInsertHandler(callType!!, inputTypeArguments = needTypeArguments, inputValueArguments = false, argumentText = argumentText).handleInsert(context, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.completion.CompletionWeigher
|
|||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementWeigher
|
import com.intellij.codeInsight.lookup.LookupElementWeigher
|
||||||
import com.intellij.codeInsight.lookup.WeighingContext
|
import com.intellij.codeInsight.lookup.WeighingContext
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.util.proximity.PsiProximityComparator
|
import com.intellij.psi.util.proximity.PsiProximityComparator
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
@@ -33,9 +34,6 @@ import org.jetbrains.kotlin.idea.core.completion.PackageLookupObject
|
|||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
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.isBooleanOrNullableBoolean
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.nullability
|
|
||||||
|
|
||||||
object PriorityWeigher : LookupElementWeigher("kotlin.priority") {
|
object PriorityWeigher : LookupElementWeigher("kotlin.priority") {
|
||||||
override fun weigh(element: LookupElement, context: WeighingContext)
|
override fun weigh(element: LookupElement, context: WeighingContext)
|
||||||
@@ -184,26 +182,32 @@ class SmartCompletionInBasicWeigher(
|
|||||||
private val callType: CallType<*>,
|
private val callType: CallType<*>,
|
||||||
private val resolutionFacade: ResolutionFacade
|
private val resolutionFacade: ResolutionFacade
|
||||||
) : LookupElementWeigher("kotlin.smartInBasic", true, false) {
|
) : LookupElementWeigher("kotlin.smartInBasic", true, false) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val KEYWORD_VALUE_MATCHED_KEY = Key<Boolean>("SmartCompletionInBasicWeigher.KEYWORD_VALUE_MATCHED_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
private val descriptorsToSkip = smartCompletion.descriptorsToSkip
|
private val descriptorsToSkip = smartCompletion.descriptorsToSkip
|
||||||
private val expectedInfos = smartCompletion.expectedInfos
|
private val expectedInfos = smartCompletion.expectedInfos
|
||||||
|
|
||||||
private fun fullMatchWeight(nameSimilarity: Int) = (3L shl 32) + nameSimilarity * 3 // true and false should be in between zero-nameSimilarity and 1-nameSimilarity
|
private fun fullMatchWeight(nameSimilarity: Int) = (3L shl 32) + nameSimilarity
|
||||||
|
|
||||||
private val MATCHED_TRUE_WEIGHT = (3L shl 32) + 2
|
|
||||||
private val MATCHED_FALSE_WEIGHT = (3L shl 32) + 1
|
|
||||||
|
|
||||||
private fun ifNotNullMatchWeight(nameSimilarity: Int) = (2L shl 32) + nameSimilarity
|
private fun ifNotNullMatchWeight(nameSimilarity: Int) = (2L shl 32) + nameSimilarity
|
||||||
|
|
||||||
private fun smartCompletionItemWeight(nameSimilarity: Int) = (1L shl 32) + nameSimilarity
|
private fun smartCompletionItemWeight(nameSimilarity: Int) = (1L shl 32) + nameSimilarity
|
||||||
|
|
||||||
private val MATCHED_NULL_WEIGHT = 1L
|
|
||||||
|
|
||||||
private val NO_MATCH_WEIGHT = 0L
|
private val NO_MATCH_WEIGHT = 0L
|
||||||
|
|
||||||
private val DESCRIPTOR_TO_SKIP_WEIGHT = -1L // if descriptor is skipped from smart completion then it's probably irrelevant
|
private val DESCRIPTOR_TO_SKIP_WEIGHT = -1L // if descriptor is skipped from smart completion then it's probably irrelevant
|
||||||
|
|
||||||
override fun weigh(element: LookupElement): Long {
|
override fun weigh(element: LookupElement): Long {
|
||||||
|
val keywordValueMatched = element.getUserData(KEYWORD_VALUE_MATCHED_KEY)
|
||||||
val smartCompletionPriority = element.getUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY)
|
val smartCompletionPriority = element.getUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY)
|
||||||
|
|
||||||
|
if (keywordValueMatched != null) {
|
||||||
|
return if (keywordValueMatched) fullMatchWeight(0) else NO_MATCH_WEIGHT
|
||||||
|
}
|
||||||
|
|
||||||
if (smartCompletionPriority != null) { // it's an "additional item" came from smart completion, don't match it against expected type
|
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)
|
return smartCompletionItemWeight(element.getUserData(NAME_SIMILARITY_KEY) ?: 0)
|
||||||
}
|
}
|
||||||
@@ -214,28 +218,6 @@ class SmartCompletionInBasicWeigher(
|
|||||||
|
|
||||||
if (expectedInfos.isEmpty()) return NO_MATCH_WEIGHT
|
if (expectedInfos.isEmpty()) return NO_MATCH_WEIGHT
|
||||||
|
|
||||||
if (o is KeywordLookupObject) {
|
|
||||||
when (element.lookupString) {
|
|
||||||
"true", "false" -> {
|
|
||||||
if (expectedInfos.any { it.fuzzyType?.type?.isBooleanOrNullableBoolean() ?: false }) {
|
|
||||||
return if (element.lookupString == "true") MATCHED_TRUE_WEIGHT else MATCHED_FALSE_WEIGHT
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NO_MATCH_WEIGHT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"null" -> {
|
|
||||||
if (expectedInfos.any { it.fuzzyType?.type?.nullability()?.let { it != TypeNullability.NOT_NULL } ?: false }) {
|
|
||||||
return MATCHED_NULL_WEIGHT
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NO_MATCH_WEIGHT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val smartCastCalculator = smartCompletion.smartCastCalculator
|
val smartCastCalculator = smartCompletion.smartCastCalculator
|
||||||
|
|
||||||
val (fuzzyTypes, name) = when (o) {
|
val (fuzzyTypes, name) = when (o) {
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.completion.smart
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.InsertionContext
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
|
||||||
import org.jetbrains.kotlin.idea.completion.COMPARISON_TOKENS
|
|
||||||
import org.jetbrains.kotlin.idea.completion.ExpectedInfo
|
|
||||||
import org.jetbrains.kotlin.idea.completion.fuzzyType
|
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
|
||||||
|
|
||||||
object KeywordValues {
|
|
||||||
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedInfos: Collection<ExpectedInfo>, expressionWithType: JetExpression) {
|
|
||||||
var skipTrueFalse = false
|
|
||||||
|
|
||||||
val whenCondition = expressionWithType.getParent() as? JetWhenConditionWithExpression
|
|
||||||
if (whenCondition != null) {
|
|
||||||
val entry = whenCondition.getParent() as JetWhenEntry
|
|
||||||
val whenExpression = entry.getParent() as JetWhenExpression
|
|
||||||
val entries = whenExpression.getEntries()
|
|
||||||
if (whenExpression.getElseExpression() == null && entry == entries.last() && entries.size() != 1) {
|
|
||||||
val lookupElement = LookupElementBuilder.create("else").bold().withTailText(" ->")
|
|
||||||
collection.add(object: LookupElementDecorator<LookupElement>(lookupElement) {
|
|
||||||
override fun handleInsert(context: InsertionContext) {
|
|
||||||
WithTailInsertHandler("->", spaceBefore = true, spaceAfter = true).handleInsert(context, getDelegate())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (whenExpression.getSubjectExpression() == null) { // no sense in true or false entries for when with no subject
|
|
||||||
skipTrueFalse = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipTrueFalse) {
|
|
||||||
val booleanInfoClassifier = { info: ExpectedInfo ->
|
|
||||||
if (info.fuzzyType?.type?.isBooleanOrNullableBoolean() ?: false) ExpectedInfoClassification.match(TypeSubstitutor.EMPTY) else ExpectedInfoClassification.noMatch
|
|
||||||
}
|
|
||||||
collection.addLookupElements(null, expectedInfos, booleanInfoClassifier) { LookupElementBuilder.create("true").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.TRUE).singletonList() }
|
|
||||||
collection.addLookupElements(null, expectedInfos, booleanInfoClassifier) { LookupElementBuilder.create("false").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.FALSE).singletonList() }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shouldSkipNull(expressionWithType)) {
|
|
||||||
val classifier = { info: ExpectedInfo ->
|
|
||||||
if (info.fuzzyType != null && info.fuzzyType!!.type.isMarkedNullable())
|
|
||||||
ExpectedInfoClassification.match(TypeSubstitutor.EMPTY)
|
|
||||||
else
|
|
||||||
ExpectedInfoClassification.noMatch
|
|
||||||
}
|
|
||||||
collection.addLookupElements(null, expectedInfos, classifier) {
|
|
||||||
LookupElementBuilder.create("null").bold().assignSmartCompletionPriority(SmartCompletionItemPriority.NULL).singletonList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun shouldSkipNull(expressionWithType: JetExpression): Boolean {
|
|
||||||
val binaryExpression = expressionWithType.parent as? JetBinaryExpression ?: return false
|
|
||||||
return binaryExpression.operationToken in COMPARISON_TOKENS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+48
-17
@@ -19,15 +19,13 @@ package org.jetbrains.kotlin.idea.completion.smart
|
|||||||
import com.intellij.codeInsight.completion.InsertionContext
|
import com.intellij.codeInsight.completion.InsertionContext
|
||||||
import com.intellij.codeInsight.completion.OffsetKey
|
import com.intellij.codeInsight.completion.OffsetKey
|
||||||
import com.intellij.codeInsight.completion.PrefixMatcher
|
import com.intellij.codeInsight.completion.PrefixMatcher
|
||||||
import com.intellij.codeInsight.lookup.Lookup
|
import com.intellij.codeInsight.lookup.*
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
|
||||||
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.descriptors.*
|
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.completion.handlers.WithTailInsertHandler
|
||||||
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.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
@@ -52,12 +50,14 @@ class SmartCompletion(
|
|||||||
private val expression: JetExpression,
|
private val expression: JetExpression,
|
||||||
private val resolutionFacade: ResolutionFacade,
|
private val resolutionFacade: ResolutionFacade,
|
||||||
private val bindingContext: BindingContext,
|
private val bindingContext: BindingContext,
|
||||||
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
private val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
private val visibilityFilter: (DeclarationDescriptor) -> Boolean,
|
||||||
private val prefixMatcher: PrefixMatcher,
|
private val prefixMatcher: PrefixMatcher,
|
||||||
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 callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||||
|
private val isJvmModule: Boolean,
|
||||||
private val forBasicCompletion: Boolean = false
|
private val forBasicCompletion: Boolean = false
|
||||||
) {
|
) {
|
||||||
private val expressionWithType = when (callTypeAndReceiver) {
|
private val expressionWithType = when (callTypeAndReceiver) {
|
||||||
@@ -150,10 +150,11 @@ class SmartCompletion(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun filterDescriptor(descriptor: DeclarationDescriptor): Collection<LookupElement> {
|
private fun filterDescriptor(descriptor: DeclarationDescriptor): Collection<LookupElement> {
|
||||||
|
val callType = callTypeAndReceiver.callType
|
||||||
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, callTypeAndReceiver.callType, resolutionFacade)
|
val types = descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator, callType, resolutionFacade)
|
||||||
val infoClassifier = { expectedInfo: ExpectedInfo -> types.classifyExpectedInfo(expectedInfo) }
|
val infoClassifier = { expectedInfo: ExpectedInfo -> types.classifyExpectedInfo(expectedInfo) }
|
||||||
|
|
||||||
result.addLookupElements(descriptor, expectedInfos, infoClassifier, noNameSimilarityForReturnItself = callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { descriptor ->
|
result.addLookupElements(descriptor, expectedInfos, infoClassifier, noNameSimilarityForReturnItself = callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { descriptor ->
|
||||||
@@ -177,23 +178,53 @@ class SmartCompletion(
|
|||||||
val items = ArrayList<LookupElement>()
|
val items = ArrayList<LookupElement>()
|
||||||
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
|
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
|
||||||
|
|
||||||
if (expectedInfos.isNotEmpty() && callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
if (!forBasicCompletion) { // basic completion adds keyword values on its own
|
||||||
TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion)
|
val keywordValueConsumer = object : KeywordValues.Consumer {
|
||||||
.addTo(items, inheritanceSearchers, expectedInfos)
|
override fun consume(lookupString: String, expectedInfoClassifier: (ExpectedInfo) -> ExpectedInfoClassification, priority: SmartCompletionItemPriority, factory: () -> LookupElement) {
|
||||||
|
items.addLookupElements(null, expectedInfos, expectedInfoClassifier) {
|
||||||
if (expression is JetSimpleNameExpression) {
|
val lookupElement = factory()
|
||||||
StaticMembers(bindingContext, lookupElementFactory).addToCollection(items, expectedInfos, expression, descriptorsToSkip)
|
lookupElement.putUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY, priority)
|
||||||
|
listOf(lookupElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
KeywordValues.process(keywordValueConsumer, callTypeAndReceiver, bindingContext, resolutionFacade, moduleDescriptor, isJvmModule)
|
||||||
|
}
|
||||||
|
|
||||||
if (!forBasicCompletion) {
|
if (expectedInfos.isNotEmpty()) {
|
||||||
|
if (!forBasicCompletion && (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT || callTypeAndReceiver is CallTypeAndReceiver.UNKNOWN /* after this@ */)) {
|
||||||
items.addThisItems(expression, expectedInfos, smartCastCalculator)
|
items.addThisItems(expression, expectedInfos, smartCastCalculator)
|
||||||
|
|
||||||
LambdaItems.addToCollection(items, expectedInfos)
|
|
||||||
|
|
||||||
KeywordValues.addToCollection(items, expectedInfos, expression)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MultipleArgumentsItemProvider(bindingContext, smartCastCalculator).addToCollection(items, expectedInfos, expression)
|
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||||
|
TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion)
|
||||||
|
.addTo(items, inheritanceSearchers, expectedInfos)
|
||||||
|
|
||||||
|
if (expression is JetSimpleNameExpression) {
|
||||||
|
StaticMembers(bindingContext, lookupElementFactory).addToCollection(items, expectedInfos, expression, descriptorsToSkip)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!forBasicCompletion) {
|
||||||
|
LambdaItems.addToCollection(items, expectedInfos)
|
||||||
|
|
||||||
|
val whenCondition = expressionWithType.parent as? JetWhenConditionWithExpression
|
||||||
|
if (whenCondition != null) {
|
||||||
|
val entry = whenCondition.parent as JetWhenEntry
|
||||||
|
val whenExpression = entry.parent as JetWhenExpression
|
||||||
|
val entries = whenExpression.entries
|
||||||
|
if (whenExpression.elseExpression == null && entry == entries.last() && entries.size() != 1) {
|
||||||
|
val lookupElement = LookupElementBuilder.create("else").bold().withTailText(" ->")
|
||||||
|
items.add(object: LookupElementDecorator<LookupElement>(lookupElement) {
|
||||||
|
override fun handleInsert(context: InsertionContext) {
|
||||||
|
WithTailInsertHandler("->", spaceBefore = true, spaceAfter = true).handleInsert(context, delegate)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MultipleArgumentsItemProvider(bindingContext, smartCastCalculator).addToCollection(items, expectedInfos, expression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritanceSearcher = if (inheritanceSearchers.isNotEmpty())
|
val inheritanceSearcher = if (inheritanceSearchers.isNotEmpty())
|
||||||
|
|||||||
+3
-3
@@ -39,9 +39,9 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
|||||||
|
|
||||||
private val smartCompletion by lazy(LazyThreadSafetyMode.NONE) {
|
private val smartCompletion by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
expression?.let {
|
expression?.let {
|
||||||
SmartCompletion(it, resolutionFacade,
|
SmartCompletion(it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter,
|
||||||
bindingContext, isVisibleFilter, prefixMatcher, originalSearchScope,
|
prefixMatcher, originalSearchScope, toFromOriginalFileMapper, lookupElementFactory,
|
||||||
toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver)
|
callTypeAndReceiver, isJvmModule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ enum class SmartCompletionItemPriority {
|
|||||||
IT,
|
IT,
|
||||||
TRUE,
|
TRUE,
|
||||||
FALSE,
|
FALSE,
|
||||||
|
CLASS_LITERAL,
|
||||||
THIS,
|
THIS,
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
NULLABLE,
|
NULLABLE,
|
||||||
|
|||||||
+3
-2
@@ -7,10 +7,11 @@ fun f(e1: E, e2: E?, x: Any) {
|
|||||||
if (e1 == <caret>
|
if (e1 == <caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WITH_ORDER
|
||||||
|
// EXIST: { itemText:"e2" }
|
||||||
// EXIST: { lookupString:"A", itemText:"E.A", typeText:"E" }
|
// EXIST: { lookupString:"A", itemText:"E.A", typeText:"E" }
|
||||||
// EXIST: { lookupString:"B", itemText:"E.B", typeText:"E" }
|
// EXIST: { lookupString:"B", itemText:"E.B", typeText:"E" }
|
||||||
// EXIST: { itemText:"e2" }
|
// EXIST: null
|
||||||
// ABSENT: { itemText:"!! e2" }
|
// ABSENT: { itemText:"!! e2" }
|
||||||
// ABSENT: e1
|
// ABSENT: e1
|
||||||
// ABSENT: x
|
// ABSENT: x
|
||||||
// ABSENT: null
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
fun<T : Any> foo(p: KClass<T>){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(String::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "class", itemText: "class", attributes: "bold" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun<T : Any> foo(p: Class<T>){}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo(String::<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST_JAVA_ONLY: { lookupString: "class.java", itemText: "class", tailText: ".java", attributes: "bold" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+12
@@ -595,6 +595,18 @@ 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("ClassLiteral.kt")
|
||||||
|
public void testClassLiteral() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/ClassLiteral.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassLiteralDotJava.kt")
|
||||||
|
public void testClassLiteralDotJava() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/ClassLiteralDotJava.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("EmptyQualifier1.kt")
|
@TestMetadata("EmptyQualifier1.kt")
|
||||||
public void testEmptyQualifier1() throws Exception {
|
public void testEmptyQualifier1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/EmptyQualifier1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/callableReference/EmptyQualifier1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user