Initial support for KT-7090 Completion for callable references
#KT-7090 Fixed
This commit is contained in:
+65
-40
@@ -37,19 +37,21 @@ import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.idea.util.ShadowedDeclarationsFilter
|
||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
class CompletionSessionConfiguration(
|
||||
val completeNonImportedDeclarations: Boolean,
|
||||
@@ -123,45 +125,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
|
||||
protected val referenceVariantsHelper = ReferenceVariantsHelper(bindingContext, resolutionFacade, isVisibleFilter)
|
||||
|
||||
protected val receiversData: ReferenceVariantsHelper.ReceiversData? = nameExpression?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it) }
|
||||
|
||||
protected val lookupElementFactory = run {
|
||||
val contextType = if (expression?.getParent() is JetSimpleNameStringTemplateEntry)
|
||||
LookupElementFactory.ContextType.STRING_TEMPLATE_AFTER_DOLLAR
|
||||
else if (receiversData?.callType == CallType.INFIX)
|
||||
LookupElementFactory.ContextType.INFIX_CALL
|
||||
else
|
||||
LookupElementFactory.ContextType.NORMAL
|
||||
|
||||
var receiverTypes = emptyList<JetType>()
|
||||
if (receiversData != null) {
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
|
||||
|
||||
receiverTypes = receiversData.receivers.flatMap { receiverValue ->
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
if (dataFlowValue.isPredictable) { // we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed
|
||||
resolutionFacade.frontendService<SmartCastManager>()
|
||||
.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo)
|
||||
}
|
||||
else {
|
||||
listOf(receiverValue.type)
|
||||
}
|
||||
}
|
||||
|
||||
if (receiversData.callType == CallType.SAFE) {
|
||||
receiverTypes = receiverTypes.map { it.makeNotNullable() }
|
||||
}
|
||||
}
|
||||
|
||||
val contextVariablesProvider = {
|
||||
nameExpression?.let {
|
||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, explicitReceiverData = null)
|
||||
.map { it as VariableDescriptor }
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
LookupElementFactory(resolutionFacade, receiverTypes, contextType, InsertHandlerProvider { expectedInfos }, contextVariablesProvider)
|
||||
}
|
||||
protected val lookupElementFactory = createLookupElementFactory()
|
||||
|
||||
// LookupElementsCollector instantiation is deferred because virtual call to createSorter uses data from derived classes
|
||||
protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) {
|
||||
@@ -331,4 +295,65 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
{ javaClass -> collector.addElement(lookupElementFactory.createLookupElementForJavaClass(javaClass), notImported = true) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun createLookupElementFactory(): LookupElementFactory {
|
||||
val (callType, receiverTypes) = detectCallTypeAndReceiverTypes()
|
||||
|
||||
val contextVariablesProvider = {
|
||||
nameExpression?.let {
|
||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, explicitReceiverData = null)
|
||||
.map { it as VariableDescriptor }
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
val insertHandlerProvider = InsertHandlerProvider(callType) { expectedInfos }
|
||||
return LookupElementFactory(resolutionFacade, receiverTypes,
|
||||
callType, expression?.parent is JetSimpleNameStringTemplateEntry,
|
||||
insertHandlerProvider, contextVariablesProvider)
|
||||
}
|
||||
|
||||
private fun detectCallTypeAndReceiverTypes(): Pair<CallType, Collection<JetType>> {
|
||||
if (nameExpression == null) {
|
||||
return CallType.NORMAL to emptyList()
|
||||
}
|
||||
|
||||
val explicitReceiverData = ReferenceVariantsHelper.getExplicitReceiverData(nameExpression)
|
||||
val receiverElement = explicitReceiverData?.element
|
||||
val callType = explicitReceiverData?.callType ?: CallType.NORMAL
|
||||
|
||||
if (explicitReceiverData != null && callType == CallType.CALLABLE_REFERENCE && receiverElement != null) {
|
||||
val type = bindingContext[BindingContext.TYPE, receiverElement as JetTypeReference]
|
||||
return callType to type.singletonOrEmptyList()
|
||||
}
|
||||
|
||||
receiverElement as JetExpression?
|
||||
|
||||
val receiverValues = if (receiverElement != null) {
|
||||
val expressionType = bindingContext.getType(receiverElement)
|
||||
expressionType?.let { listOf(ExpressionReceiver(receiverElement, expressionType)) } ?: emptyList()
|
||||
}
|
||||
else {
|
||||
val resolutionScope = referenceVariantsHelper.resolutionScope(nameExpression)
|
||||
resolutionScope?.getImplicitReceiversWithInstance()?.map { it.value } ?: emptyList()
|
||||
}
|
||||
|
||||
val dataFlowInfo = referenceVariantsHelper.dataFlowInfo(nameExpression)
|
||||
|
||||
var receiverTypes = receiverValues.flatMap { receiverValue ->
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
if (dataFlowValue.isPredictable) { // we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed
|
||||
resolutionFacade.frontendService<SmartCastManager>()
|
||||
.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo)
|
||||
}
|
||||
else {
|
||||
listOf(receiverValue.type)
|
||||
}
|
||||
}
|
||||
|
||||
if (callType == CallType.SAFE) {
|
||||
receiverTypes = receiverTypes.map { it.makeNotNullable() }
|
||||
}
|
||||
|
||||
return callType to receiverTypes
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -21,11 +21,15 @@ import com.intellij.codeInsight.lookup.LookupElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.*
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import java.util.*
|
||||
|
||||
class InsertHandlerProvider(expectedInfosCalculator: () -> Collection<ExpectedInfo>) {
|
||||
class InsertHandlerProvider(
|
||||
private val callType: CallType,
|
||||
expectedInfosCalculator: () -> Collection<ExpectedInfo>
|
||||
) {
|
||||
private val expectedInfos by lazy(LazyThreadSafetyMode.NONE) { expectedInfosCalculator() }
|
||||
|
||||
public fun insertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement> {
|
||||
@@ -34,7 +38,7 @@ class InsertHandlerProvider(expectedInfosCalculator: () -> Collection<ExpectedIn
|
||||
val needTypeArguments = needTypeArguments(descriptor)
|
||||
val parameters = descriptor.valueParameters
|
||||
when (parameters.size()) {
|
||||
0 -> KotlinFunctionInsertHandler(needTypeArguments, inputValueArguments = false)
|
||||
0 -> KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = false)
|
||||
|
||||
1 -> {
|
||||
val parameterType = parameters.single().getType()
|
||||
@@ -42,13 +46,13 @@ class InsertHandlerProvider(expectedInfosCalculator: () -> Collection<ExpectedIn
|
||||
val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
||||
if (parameterCount <= 1) {
|
||||
// otherwise additional item with lambda template is to be added
|
||||
return KotlinFunctionInsertHandler(needTypeArguments, inputValueArguments = false, lambdaInfo = GenerateLambdaInfo(parameterType, false))
|
||||
return KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = false, lambdaInfo = GenerateLambdaInfo(parameterType, false))
|
||||
}
|
||||
}
|
||||
KotlinFunctionInsertHandler(needTypeArguments, inputValueArguments = true)
|
||||
KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = true)
|
||||
}
|
||||
|
||||
else -> KotlinFunctionInsertHandler(needTypeArguments, inputValueArguments = true)
|
||||
else -> KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.psi.filters.position.PositionElementFilter
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.KotlinKeywordInsertHandler
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.lexer.JetKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.JetTokens.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -76,7 +77,7 @@ object KeywordCompletion {
|
||||
.withInsertHandler(if (keywordToken !in FUNCTION_KEYWORDS)
|
||||
KotlinKeywordInsertHandler
|
||||
else
|
||||
KotlinFunctionInsertHandler(inputTypeArguments = false, inputValueArguments = false))
|
||||
KotlinFunctionInsertHandler(CallType.NORMAL, inputTypeArguments = false, inputValueArguments = false))
|
||||
consumer(element)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-13
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation
|
||||
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.fuzzyReturnType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -44,7 +45,8 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
class LookupElementFactory(
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val receiverTypes: Collection<JetType>,
|
||||
private val contextType: LookupElementFactory.ContextType,
|
||||
private val callType: CallType,
|
||||
private val isInStringTemplateAfterDollar: Boolean,
|
||||
public val insertHandlerProvider: InsertHandlerProvider,
|
||||
contextVariablesProvider: () -> Collection<VariableDescriptor>
|
||||
) {
|
||||
@@ -54,23 +56,17 @@ class LookupElementFactory(
|
||||
contextVariablesProvider().filter { KotlinBuiltIns.isFunctionOrExtensionFunctionType(it.type) }
|
||||
}
|
||||
|
||||
public enum class ContextType {
|
||||
NORMAL,
|
||||
STRING_TEMPLATE_AFTER_DOLLAR,
|
||||
INFIX_CALL
|
||||
}
|
||||
|
||||
public fun createStandardLookupElementsForDescriptor(descriptor: DeclarationDescriptor, useReceiverTypes: Boolean): Collection<LookupElement> {
|
||||
val result = SmartList<LookupElement>()
|
||||
|
||||
var lookupElement = createLookupElement(descriptor, useReceiverTypes)
|
||||
if (contextType == ContextType.STRING_TEMPLATE_AFTER_DOLLAR && (descriptor is FunctionDescriptor || descriptor is ClassifierDescriptor)) {
|
||||
if (isInStringTemplateAfterDollar && (descriptor is FunctionDescriptor || descriptor is ClassifierDescriptor)) {
|
||||
lookupElement = lookupElement.withBracesSurrounding()
|
||||
}
|
||||
result.add(lookupElement)
|
||||
|
||||
// add special item for function with one argument of function type with more than one parameter
|
||||
if (contextType != ContextType.INFIX_CALL && descriptor is FunctionDescriptor) {
|
||||
if (descriptor is FunctionDescriptor && (callType == CallType.NORMAL || callType == CallType.SAFE)) {
|
||||
result.addSpecialFunctionCallElements(descriptor, useReceiverTypes)
|
||||
}
|
||||
|
||||
@@ -136,11 +132,11 @@ class LookupElementFactory(
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext) {
|
||||
KotlinFunctionInsertHandler(inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this)
|
||||
KotlinFunctionInsertHandler(callType, inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this)
|
||||
}
|
||||
}
|
||||
|
||||
if (contextType == ContextType.STRING_TEMPLATE_AFTER_DOLLAR) {
|
||||
if (isInStringTemplateAfterDollar) {
|
||||
lookupElement = lookupElement.withBracesSurrounding()
|
||||
}
|
||||
|
||||
@@ -153,7 +149,7 @@ class LookupElementFactory(
|
||||
val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments
|
||||
lookupElement = FunctionCallWithArgumentLookupElement(lookupElement, descriptor, argumentText, needTypeArguments)
|
||||
|
||||
if (contextType == ContextType.STRING_TEMPLATE_AFTER_DOLLAR) {
|
||||
if (isInStringTemplateAfterDollar) {
|
||||
lookupElement = lookupElement.withBracesSurrounding()
|
||||
}
|
||||
|
||||
@@ -179,7 +175,7 @@ class LookupElementFactory(
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext) {
|
||||
KotlinFunctionInsertHandler(inputTypeArguments = needTypeArguments, inputValueArguments = false, argumentText = argumentText).handleInsert(context, this)
|
||||
KotlinFunctionInsertHandler(callType, inputTypeArguments = needTypeArguments, inputValueArguments = false, argumentText = argumentText).handleInsert(context, this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.patterns.PlatformPatterns
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.JetPackageDirective
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
@@ -53,7 +54,7 @@ object PackageDirectiveCompletion {
|
||||
val bindingContext = resolutionFacade.analyze(expression)
|
||||
|
||||
val variants = ReferenceVariantsHelper(bindingContext, resolutionFacade, { true }).getPackageReferenceVariants(expression, prefixMatcher.asNameFilter())
|
||||
val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(expectedInfosCalculator = { emptyList() }))
|
||||
val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.NORMAL/*TODO*/, expectedInfosCalculator = { emptyList() }))
|
||||
for (variant in variants) {
|
||||
val lookupElement = lookupElementFactory.createLookupElement(variant)
|
||||
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
||||
|
||||
+5
-10
@@ -26,10 +26,9 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.JetBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.JetTypeArgumentList
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
@@ -38,6 +37,7 @@ import org.jetbrains.kotlin.types.JetType
|
||||
class GenerateLambdaInfo(val lambdaType: JetType, val explicitParameters: Boolean)
|
||||
|
||||
class KotlinFunctionInsertHandler(
|
||||
val callType: CallType,
|
||||
val inputTypeArguments: Boolean,
|
||||
val inputValueArguments: Boolean,
|
||||
val argumentText: String = "",
|
||||
@@ -61,9 +61,10 @@ class KotlinFunctionInsertHandler(
|
||||
val element = context.getFile().findElementAt(startOffset) ?: return
|
||||
|
||||
when {
|
||||
element.getStrictParentOfType<JetImportDirective>() != null -> return
|
||||
//TODO: replace with CallType
|
||||
element.getStrictParentOfType<JetImportDirective>() != null || callType == CallType.CALLABLE_REFERENCE -> return
|
||||
|
||||
isInfixCall(element) -> {
|
||||
callType == CallType.INFIX -> {
|
||||
if (context.getCompletionChar() == ' ') {
|
||||
context.setAddCompletionChar(false)
|
||||
}
|
||||
@@ -77,12 +78,6 @@ class KotlinFunctionInsertHandler(
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInfixCall(context: PsiElement): Boolean {
|
||||
val parent = context.getParent()
|
||||
val grandParent = parent?.getParent()
|
||||
return parent is JetSimpleNameExpression && grandParent is JetBinaryExpression && parent == grandParent.getOperationReference()
|
||||
}
|
||||
|
||||
private fun addArguments(context : InsertionContext, offsetElement : PsiElement) {
|
||||
val completionChar = context.getCompletionChar()
|
||||
if (completionChar == '(') { //TODO: more correct behavior related to braces type
|
||||
|
||||
+3
-2
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
||||
import org.jetbrains.kotlin.psi.FunctionLiteralArgument
|
||||
import org.jetbrains.kotlin.psi.JetCodeFragment
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.psi.ValueArgumentName
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
|
||||
@@ -90,9 +91,9 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
||||
// special completion for outside parenthesis lambda argument
|
||||
private fun addFunctionLiteralArgumentCompletions() {
|
||||
if (nameExpression != null) {
|
||||
val (receiverExpression, callType) = ReferenceVariantsHelper.getExplicitReceiverData(nameExpression) ?: return
|
||||
val (receiverElement, callType) = ReferenceVariantsHelper.getExplicitReceiverData(nameExpression) ?: return
|
||||
if (callType == CallType.INFIX) {
|
||||
val call = receiverExpression.getCall(bindingContext)
|
||||
val call = (receiverElement as JetExpression).getCall(bindingContext)
|
||||
if (call != null && call.getFunctionLiteralArguments().isEmpty()) {
|
||||
val dummyArgument = object : FunctionLiteralArgument {
|
||||
override fun getFunctionLiteral() = throw UnsupportedOperationException()
|
||||
|
||||
+3
-2
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.psiClassToDescriptor
|
||||
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.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
||||
@@ -203,9 +204,9 @@ class TypeInstantiationItems(
|
||||
}
|
||||
|
||||
val baseInsertHandler = when (visibleConstructors.size()) {
|
||||
0 -> KotlinFunctionInsertHandler(inputTypeArguments = false, inputValueArguments = false)
|
||||
0 -> KotlinFunctionInsertHandler(CallType.NORMAL, inputTypeArguments = false, inputValueArguments = false)
|
||||
1 -> lookupElementFactory.insertHandlerProvider.insertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler
|
||||
else -> KotlinFunctionInsertHandler(inputTypeArguments = false, inputValueArguments = true)
|
||||
else -> KotlinFunctionInsertHandler(CallType.NORMAL, inputTypeArguments = false, inputValueArguments = true)
|
||||
}
|
||||
|
||||
insertHandler = object : InsertHandler<LookupElement> {
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
fun globalFun(p: Int) {}
|
||||
|
||||
fun String.extensionFun(){}
|
||||
val String.extensionVal: Int
|
||||
get() = 1
|
||||
|
||||
val globalVal = 1
|
||||
var globalVar = 1
|
||||
|
||||
class C {
|
||||
fun memberFun(){}
|
||||
|
||||
val memberVal = 1
|
||||
|
||||
class NestedClass
|
||||
inner class InnerClass
|
||||
|
||||
fun foo() {
|
||||
fun localFun(){}
|
||||
|
||||
val local = 1
|
||||
|
||||
val v = ::<caret>
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun companionObjectFun(){}
|
||||
}
|
||||
}
|
||||
|
||||
class WithPrivateConstructor private constructor()
|
||||
abstract class AbstractClass
|
||||
|
||||
// EXIST: { itemText: "globalFun", attributes: "" }
|
||||
// EXIST: { itemText: "globalVal", attributes: "" }
|
||||
// EXIST: { itemText: "globalVar", attributes: "" }
|
||||
// ABSENT: extensionFun
|
||||
// ABSENT: extensionVal
|
||||
// EXIST: { itemText: "memberFun", attributes: "bold" }
|
||||
// EXIST: { itemText: "memberVal", attributes: "bold" }
|
||||
// EXIST: { itemText: "localFun", attributes: "" }
|
||||
// ABSENT: { itemText: "local", attributes: "" }
|
||||
// EXIST: { itemText: "companionObjectFun", attributes: "bold" }
|
||||
// EXIST: { itemText: "C", attributes: "" }
|
||||
// EXIST: { itemText: "NestedClass", attributes: "" }
|
||||
// EXIST: { itemText: "InnerClass", attributes: "bold" }
|
||||
// ABSENT: WithPrivateConstructor
|
||||
// ABSENT: AbstractClass
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
class C {
|
||||
fun memberFun(){}
|
||||
|
||||
val memberVal = 1
|
||||
|
||||
class NestedClass
|
||||
inner class InnerClass
|
||||
|
||||
companion object {
|
||||
fun companionObjectFun(){}
|
||||
}
|
||||
}
|
||||
|
||||
fun C.foo() {
|
||||
val v = ::<caret>
|
||||
}
|
||||
|
||||
// EXIST: { itemText: "memberFun", attributes: "bold" }
|
||||
// EXIST: { itemText: "memberVal", attributes: "bold" }
|
||||
// EXIST: { itemText: "hashCode", attributes: "" }
|
||||
// ABSENT: companionObjectFun
|
||||
// ABSENT: NestedClass
|
||||
// EXIST: { itemText: "InnerClass", attributes: "bold" }
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun xfoo(p: (String, Char) -> Unit){}
|
||||
|
||||
fun test() {
|
||||
::xfo<caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"xfoo", itemText: "xfoo", tailText: "(p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
|
||||
// NOTHING_ELSE
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
abstract class A {
|
||||
abstract fun memberFunInA()
|
||||
abstract val memberValInA: Int
|
||||
|
||||
inner class InnerInA
|
||||
class NestedInA
|
||||
}
|
||||
|
||||
fun A.extensionFun(){}
|
||||
|
||||
val A.extensionVal: Int
|
||||
get() = 1
|
||||
|
||||
fun Any.anyExtensionFun(){}
|
||||
fun String.wrongExtensionFun(){}
|
||||
|
||||
fun globalFun(p: Int) {}
|
||||
val globalVal = 1
|
||||
|
||||
class C {
|
||||
fun memberFun(){}
|
||||
|
||||
val memberVal = 1
|
||||
|
||||
fun A.memberExtensionFun(){}
|
||||
|
||||
fun foo() {
|
||||
fun localFun(){}
|
||||
|
||||
val v = A::<caret>
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun companionObjectFun(){}
|
||||
|
||||
fun A.companionExtension(){}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO // EXIST: class */
|
||||
/* TODO // EXIST: class.java */
|
||||
// EXIST: { itemText: "memberFunInA", attributes: "bold" }
|
||||
// EXIST: { itemText: "memberValInA", attributes: "bold" }
|
||||
// EXIST: { itemText: "InnerInA", attributes: "bold" }
|
||||
// EXIST: { itemText: "NestedInA", attributes: "" }
|
||||
// EXIST: { itemText: "extensionFun", attributes: "bold" }
|
||||
// EXIST: { itemText: "extensionVal", attributes: "bold" }
|
||||
// EXIST: { itemText: "anyExtensionFun", attributes: "" }
|
||||
// ABSENT: wrongExtensionFun
|
||||
// ABSENT: globalFun
|
||||
// ABSENT: globalVal
|
||||
// ABSENT: memberFun
|
||||
// ABSENT: memberVal
|
||||
// ABSENT: memberExtensionFun
|
||||
// ABSENT: localFun
|
||||
// ABSENT: companionObjectFun
|
||||
// ABSENT: companionExtension
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
interface I1 {
|
||||
fun i1Member()
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
fun i2Member()
|
||||
}
|
||||
|
||||
fun I1.i1Extension(){}
|
||||
fun I2.i2Extension(){}
|
||||
fun Any.anyExtension(){}
|
||||
fun String.stringExtension(){}
|
||||
|
||||
open class C {
|
||||
fun cMember(){}
|
||||
|
||||
fun foo() {
|
||||
if (this is I1 && this is I2) {
|
||||
val v = ::<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: { itemText: "i1Extension", attributes: "bold" }
|
||||
// EXIST: { itemText: "i2Extension", attributes: "bold" }
|
||||
// EXIST: { itemText: "i1Member", attributes: "bold" }
|
||||
// EXIST: { itemText: "i2Member", attributes: "bold" }
|
||||
// EXIST: { itemText: "anyExtension", attributes: "" }
|
||||
// EXIST: { itemText: "hashCode", attributes: "" }
|
||||
// ABSENT: stringExtension
|
||||
// EXIST: { itemText: "cMember", attributes: "bold" }
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import java.io.File
|
||||
|
||||
val v = File::<caret>
|
||||
|
||||
// EXIST_JAVA_ONLY: { itemText: "freeSpace", tailText: " (from getFreeSpace())", attributes: "bold" }
|
||||
// EXIST_JAVA_ONLY: { itemText: "isFile", tailText: " (from isFile())", attributes: "bold" }
|
||||
// ABSENT: { itemText: "isFile", tailText: "()" }
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.io.File
|
||||
|
||||
class MyFile : File("") {
|
||||
val v = ::<caret>
|
||||
}
|
||||
|
||||
// EXIST_JAVA_ONLY: { itemText: "freeSpace", tailText: " (from getFreeSpace())", attributes: "" }
|
||||
// EXIST_JAVA_ONLY: { itemText: "isFile", tailText: " (from isFile())", attributes: "" }
|
||||
// ABSENT: { itemText: "isFile", tailText: "()" }
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package ppp
|
||||
|
||||
class X(p: Int)
|
||||
|
||||
class C {
|
||||
fun foo() {
|
||||
val v = ::<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: X
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package ppp
|
||||
|
||||
class X(p: Int)
|
||||
|
||||
class C {
|
||||
fun foo() {
|
||||
val v = ::X<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: X
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fun globalFun(p: Int) {}
|
||||
|
||||
class C {
|
||||
fun foo() {
|
||||
val v = ::<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: globalFun
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fun globalFun(p: Int) {}
|
||||
|
||||
class C {
|
||||
fun foo() {
|
||||
val v = ::globalFun<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: globalFun
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
fun foo() {
|
||||
val v = D::<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
fun memberFun(s: String){}
|
||||
}
|
||||
|
||||
// ELEMENT: memberFun
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
fun foo() {
|
||||
val v = D::memberFun<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
fun memberFun(s: String){}
|
||||
}
|
||||
|
||||
// ELEMENT: memberFun
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
val prop: Int = 0
|
||||
|
||||
fun foo() {
|
||||
val v = ::<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: prop
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
val prop: Int = 0
|
||||
|
||||
fun foo() {
|
||||
val v = ::prop<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: prop
|
||||
+51
@@ -1066,6 +1066,57 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/callableReference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CallableReference extends AbstractJSBasicCompletionTest {
|
||||
public void testAllFilesPresentInCallableReference() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("EmptyQualifier.kt")
|
||||
public void testEmptyQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/EmptyQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("EmptyQualifierInExtensionFun.kt")
|
||||
public void testEmptyQualifierInExtensionFun() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/EmptyQualifierInExtensionFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("HigherOrderFunction.kt")
|
||||
public void testHigherOrderFunction() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/HigherOrderFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NonEmptyQualifier.kt")
|
||||
public void testNonEmptyQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/NonEmptyQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SmartCastThis.kt")
|
||||
public void testSmartCastThis() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/SmartCastThis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SyntheticExtensions.kt")
|
||||
public void testSyntheticExtensions() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/SyntheticExtensions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SyntheticExtensions2.kt")
|
||||
public void testSyntheticExtensions2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/SyntheticExtensions2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/extensions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+51
@@ -1066,6 +1066,57 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/callableReference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CallableReference extends AbstractJvmBasicCompletionTest {
|
||||
public void testAllFilesPresentInCallableReference() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("EmptyQualifier.kt")
|
||||
public void testEmptyQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/EmptyQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("EmptyQualifierInExtensionFun.kt")
|
||||
public void testEmptyQualifierInExtensionFun() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/EmptyQualifierInExtensionFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("HigherOrderFunction.kt")
|
||||
public void testHigherOrderFunction() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/HigherOrderFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NonEmptyQualifier.kt")
|
||||
public void testNonEmptyQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/NonEmptyQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SmartCastThis.kt")
|
||||
public void testSmartCastThis() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/SmartCastThis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SyntheticExtensions.kt")
|
||||
public void testSyntheticExtensions() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/SyntheticExtensions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SyntheticExtensions2.kt")
|
||||
public void testSyntheticExtensions2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/callableReference/SyntheticExtensions2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/extensions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+33
@@ -155,6 +155,39 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/handlers/basic/callableReference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CallableReference extends AbstractBasicCompletionHandlerTest {
|
||||
public void testAllFilesPresentInCallableReference() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/basic/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("ClassConstructor.kt")
|
||||
public void testClassConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/callableReference/ClassConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("EmptyQualifier.kt")
|
||||
public void testEmptyQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/callableReference/EmptyQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NonEmptyQualifier.kt")
|
||||
public void testNonEmptyQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/callableReference/NonEmptyQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/callableReference/Property.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/handlers/basic/exclChar")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user