Additional item inserting lambda provided by completion when all parameters before the last are optional
This commit is contained in:
@@ -47,34 +47,36 @@ public interface DescriptorRenderer : Renderer<DeclarationDescriptor> {
|
|||||||
|
|
||||||
override fun render(declarationDescriptor: DeclarationDescriptor): String
|
override fun render(declarationDescriptor: DeclarationDescriptor): String
|
||||||
|
|
||||||
|
public fun renderValueParameters(parameters: Collection<ValueParameterDescriptor>, synthesizedParameterNames: Boolean): String
|
||||||
|
|
||||||
public fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String
|
public fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String
|
||||||
|
= renderValueParameters(functionDescriptor.valueParameters, functionDescriptor.hasSynthesizedParameterNames())
|
||||||
|
|
||||||
public fun renderName(name: Name): String
|
public fun renderName(name: Name): String
|
||||||
|
|
||||||
public fun renderFqName(fqName: FqNameBase): String
|
public fun renderFqName(fqName: FqNameBase): String
|
||||||
|
|
||||||
public interface ValueParametersHandler {
|
public interface ValueParametersHandler {
|
||||||
public fun appendBeforeValueParameters(function: FunctionDescriptor, builder: StringBuilder)
|
public fun appendBeforeValueParameters(parameterCount: Int, builder: StringBuilder)
|
||||||
public fun appendAfterValueParameters(function: FunctionDescriptor, builder: StringBuilder)
|
public fun appendAfterValueParameters(parameterCount: Int, builder: StringBuilder)
|
||||||
|
|
||||||
public fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder)
|
public fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder)
|
||||||
public fun appendAfterValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder)
|
public fun appendAfterValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder)
|
||||||
|
|
||||||
public object DEFAULT : ValueParametersHandler {
|
public object DEFAULT : ValueParametersHandler {
|
||||||
override fun appendBeforeValueParameters(function: FunctionDescriptor, builder: StringBuilder) {
|
override fun appendBeforeValueParameters(parameterCount: Int, builder: StringBuilder) {
|
||||||
builder.append("(")
|
builder.append("(")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun appendAfterValueParameters(function: FunctionDescriptor, builder: StringBuilder) {
|
override fun appendAfterValueParameters(parameterCount: Int, builder: StringBuilder) {
|
||||||
builder.append(")")
|
builder.append(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder) {
|
override fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun appendAfterValueParameter(parameter: ValueParameterDescriptor, builder: StringBuilder) {
|
override fun appendAfterValueParameter(parameter: ValueParameterDescriptor, parameterIndex: Int, parameterCount: Int, builder: StringBuilder) {
|
||||||
val function = parameter.getContainingDeclaration() as FunctionDescriptor
|
if (parameterIndex != parameterCount - 1) {
|
||||||
if (parameter.getIndex() != function.getValueParameters().size() - 1) {
|
|
||||||
builder.append(", ")
|
builder.append(", ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ internal class DescriptorRendererImpl(
|
|||||||
|
|
||||||
renderName(function, builder)
|
renderName(function, builder)
|
||||||
|
|
||||||
renderValueParameters(function, builder)
|
renderValueParameters(function.valueParameters, function.hasSynthesizedParameterNames(), builder)
|
||||||
|
|
||||||
renderReceiverAfterName(function, builder)
|
renderReceiverAfterName(function, builder)
|
||||||
|
|
||||||
@@ -594,7 +594,7 @@ internal class DescriptorRendererImpl(
|
|||||||
renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false)
|
renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValueParameters(constructor, builder)
|
renderValueParameters(constructor.valueParameters, constructor.hasSynthesizedParameterNames(), builder)
|
||||||
|
|
||||||
if (secondaryConstructorsAsPrimary) {
|
if (secondaryConstructorsAsPrimary) {
|
||||||
renderWhereSuffix(constructor.getTypeParameters(), builder)
|
renderWhereSuffix(constructor.getTypeParameters(), builder)
|
||||||
@@ -618,25 +618,26 @@ internal class DescriptorRendererImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String {
|
override fun renderValueParameters(parameters: Collection<ValueParameterDescriptor>, synthesizedParameterNames: Boolean): String {
|
||||||
return StringBuilder { renderValueParameters(functionDescriptor, this) }.toString()
|
return StringBuilder { renderValueParameters(parameters, synthesizedParameterNames, this) }.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderValueParameters(function: FunctionDescriptor, builder: StringBuilder) {
|
private fun renderValueParameters(parameters: Collection<ValueParameterDescriptor>, synthesizedParameterNames: Boolean, builder: StringBuilder) {
|
||||||
val includeNames = shouldRenderParameterNames(function)
|
val includeNames = shouldRenderParameterNames(synthesizedParameterNames)
|
||||||
valueParametersHandler.appendBeforeValueParameters(function, builder)
|
val parameterCount = parameters.size()
|
||||||
for (parameter in function.getValueParameters()) {
|
valueParametersHandler.appendBeforeValueParameters(parameterCount, builder)
|
||||||
valueParametersHandler.appendBeforeValueParameter(parameter, builder)
|
for ((index, parameter) in parameters.withIndex()) {
|
||||||
|
valueParametersHandler.appendBeforeValueParameter(parameter, index, parameterCount, builder)
|
||||||
renderValueParameter(parameter, includeNames, builder, false)
|
renderValueParameter(parameter, includeNames, builder, false)
|
||||||
valueParametersHandler.appendAfterValueParameter(parameter, builder)
|
valueParametersHandler.appendAfterValueParameter(parameter, index, parameterCount, builder)
|
||||||
}
|
}
|
||||||
valueParametersHandler.appendAfterValueParameters(function, builder)
|
valueParametersHandler.appendAfterValueParameters(parameterCount, builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldRenderParameterNames(function: FunctionDescriptor): Boolean {
|
private fun shouldRenderParameterNames(synthesizedParameterNames: Boolean): Boolean {
|
||||||
when (parameterNameRenderingPolicy) {
|
when (parameterNameRenderingPolicy) {
|
||||||
ParameterNameRenderingPolicy.ALL -> return true
|
ParameterNameRenderingPolicy.ALL -> return true
|
||||||
ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED -> return !function.hasSynthesizedParameterNames()
|
ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED -> return !synthesizedParameterNames
|
||||||
ParameterNameRenderingPolicy.NONE -> return false
|
ParameterNameRenderingPolicy.NONE -> return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -752,7 +753,7 @@ internal class DescriptorRendererImpl(
|
|||||||
renderAnnotations(primaryConstructor, builder, true)
|
renderAnnotations(primaryConstructor, builder, true)
|
||||||
renderVisibility(primaryConstructor.getVisibility(), builder)
|
renderVisibility(primaryConstructor.getVisibility(), builder)
|
||||||
builder.append("constructor")
|
builder.append("constructor")
|
||||||
renderValueParameters(primaryConstructor, builder)
|
renderValueParameters(primaryConstructor.valueParameters, primaryConstructor.hasSynthesizedParameterNames(), builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -21,7 +21,6 @@ import kotlin.Unit;
|
|||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer;
|
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow;
|
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow;
|
||||||
@@ -167,13 +166,17 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
|||||||
|
|
||||||
private static final DescriptorRenderer.ValueParametersHandler VALUE_PARAMETERS_HANDLER = new DescriptorRenderer.ValueParametersHandler() {
|
private static final DescriptorRenderer.ValueParametersHandler VALUE_PARAMETERS_HANDLER = new DescriptorRenderer.ValueParametersHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void appendBeforeValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder builder) {
|
public void appendBeforeValueParameter(
|
||||||
|
@NotNull ValueParameterDescriptor parameter, int parameterIndex, int parameterCount, @NotNull StringBuilder builder
|
||||||
|
) {
|
||||||
builder.append("<td align=\"right\" style=\"white-space:nowrap;font-weight:bold;\">");
|
builder.append("<td align=\"right\" style=\"white-space:nowrap;font-weight:bold;\">");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendAfterValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder builder) {
|
public void appendAfterValueParameter(
|
||||||
boolean last = parameter.getContainingDeclaration().getValueParameters().size() - 1 == parameter.getIndex();
|
@NotNull ValueParameterDescriptor parameter, int parameterIndex, int parameterCount, @NotNull StringBuilder builder
|
||||||
|
) {
|
||||||
|
boolean last = parameterIndex == parameterCount - 1;
|
||||||
if (!last) {
|
if (!last) {
|
||||||
builder.append(",");
|
builder.append(",");
|
||||||
}
|
}
|
||||||
@@ -181,9 +184,9 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendBeforeValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) {
|
public void appendBeforeValueParameters(int parameterCount, @NotNull StringBuilder builder) {
|
||||||
builder.append("</td>");
|
builder.append("</td>");
|
||||||
if (function.getValueParameters().isEmpty()) {
|
if (parameterCount == 0) {
|
||||||
tdBold(builder, "( )");
|
tdBold(builder, "( )");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -192,8 +195,8 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendAfterValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) {
|
public void appendAfterValueParameters(int parameterCount, @NotNull StringBuilder builder) {
|
||||||
if (!function.getValueParameters().isEmpty()) {
|
if (parameterCount != 0) {
|
||||||
tdBold(builder, ")");
|
tdBold(builder, ")");
|
||||||
}
|
}
|
||||||
builder.append("<td style=\"white-space:nowrap;font-weight:bold;\">");
|
builder.append("<td style=\"white-space:nowrap;font-weight:bold;\">");
|
||||||
|
|||||||
+6
-6
@@ -191,7 +191,7 @@ class BasicLookupElementFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor is CallableDescriptor) {
|
if (descriptor is CallableDescriptor) {
|
||||||
appendContainerAndReceiverInformation(descriptor) { tail, grayed -> element = element.appendTailText(tail, grayed) }
|
appendContainerAndReceiverInformation(descriptor) { element = element.appendTailText(it, true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor is PropertyDescriptor) {
|
if (descriptor is PropertyDescriptor) {
|
||||||
@@ -215,13 +215,13 @@ class BasicLookupElementFactory(
|
|||||||
return element.withIconFromLookupObject()
|
return element.withIconFromLookupObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun appendContainerAndReceiverInformation(descriptor: CallableDescriptor, appendTailText: (String, Boolean) -> Unit) {
|
public fun appendContainerAndReceiverInformation(descriptor: CallableDescriptor, appendTailText: (String) -> Unit) {
|
||||||
val extensionReceiver = descriptor.original.extensionReceiverParameter
|
val extensionReceiver = descriptor.original.extensionReceiverParameter
|
||||||
when {
|
when {
|
||||||
descriptor is SyntheticJavaPropertyDescriptor -> {
|
descriptor is SyntheticJavaPropertyDescriptor -> {
|
||||||
var from = descriptor.getMethod.getName().asString() + "()"
|
var from = descriptor.getMethod.getName().asString() + "()"
|
||||||
descriptor.setMethod?.let { from += "/" + it.getName().asString() + "()" }
|
descriptor.setMethod?.let { from += "/" + it.getName().asString() + "()" }
|
||||||
appendTailText(" (from $from)", true)
|
appendTailText(" (from $from)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to show them as extensions
|
// no need to show them as extensions
|
||||||
@@ -230,7 +230,7 @@ class BasicLookupElementFactory(
|
|||||||
|
|
||||||
extensionReceiver != null -> {
|
extensionReceiver != null -> {
|
||||||
val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(extensionReceiver.type)
|
val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(extensionReceiver.type)
|
||||||
appendTailText(" for $receiverPresentation", true)
|
appendTailText(" for $receiverPresentation")
|
||||||
|
|
||||||
val container = descriptor.getContainingDeclaration()
|
val container = descriptor.getContainingDeclaration()
|
||||||
val containerPresentation = if (container is ClassDescriptor)
|
val containerPresentation = if (container is ClassDescriptor)
|
||||||
@@ -240,7 +240,7 @@ class BasicLookupElementFactory(
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
if (containerPresentation != null) {
|
if (containerPresentation != null) {
|
||||||
appendTailText(" in $containerPresentation", true)
|
appendTailText(" in $containerPresentation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ class BasicLookupElementFactory(
|
|||||||
if (container is PackageFragmentDescriptor) {
|
if (container is PackageFragmentDescriptor) {
|
||||||
// we show container only for global functions and properties
|
// we show container only for global functions and properties
|
||||||
//TODO: it would be probably better to show it also for static declarations which are not from the current class (imported)
|
//TODO: it would be probably better to show it also for static declarations which are not from the current class (imported)
|
||||||
appendTailText(" (${container.fqName})", true)
|
appendTailText(" (${container.fqName})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-21
@@ -28,15 +28,17 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo
|
import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.buildLambdaPresentation
|
import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
|
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
@@ -92,44 +94,55 @@ class LookupElementFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableCollection<LookupElement>.addSpecialFunctionCallElements(descriptor: FunctionDescriptor, useReceiverTypes: Boolean) {
|
private fun MutableCollection<LookupElement>.addSpecialFunctionCallElements(descriptor: FunctionDescriptor, useReceiverTypes: Boolean) {
|
||||||
val singleParameter = descriptor.valueParameters.singleOrNull() ?: return
|
// check that all parameters except for the last one are optional
|
||||||
val parameterType = singleParameter.type
|
val lastParameter = descriptor.valueParameters.lastOrNull() ?: return
|
||||||
|
if (!descriptor.valueParameters.all { it == lastParameter || it.hasDefaultValue() }) return
|
||||||
|
val parameterType = lastParameter.type
|
||||||
if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) {
|
if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) {
|
||||||
|
val isSingleParameter = descriptor.valueParameters.size() == 1
|
||||||
|
|
||||||
val functionParameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
val functionParameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size()
|
||||||
if (functionParameterCount > 1) {
|
// we don't need special item inserting lambda for single functional parameter that does not need multiple arguments because the default item will be special in this case
|
||||||
add(createFunctionCallElementWithExplicitLambdaParameters(descriptor, parameterType, useReceiverTypes))
|
if (!isSingleParameter || functionParameterCount > 1) {
|
||||||
|
add(createFunctionCallElementWithLambda(descriptor, parameterType, functionParameterCount > 1, useReceiverTypes))
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: also ::function? at least for local functions
|
if (isSingleParameter) {
|
||||||
//TODO: order for them
|
//TODO: also ::function? at least for local functions
|
||||||
val fuzzyParameterType = FuzzyType(parameterType, descriptor.typeParameters)
|
//TODO: order for them
|
||||||
for (variable in functionTypeContextVariables) {
|
val fuzzyParameterType = FuzzyType(parameterType, descriptor.typeParameters)
|
||||||
val substitutor = variable.fuzzyReturnType()?.checkIsSubtypeOf(fuzzyParameterType)
|
for (variable in functionTypeContextVariables) {
|
||||||
if (substitutor != null) {
|
val substitutor = variable.fuzzyReturnType()?.checkIsSubtypeOf(fuzzyParameterType)
|
||||||
val substitutedDescriptor = descriptor.substitute(substitutor) ?: continue
|
if (substitutor != null) {
|
||||||
add(createFunctionCallElementWithArgument(substitutedDescriptor, variable.name.asString(), useReceiverTypes))
|
val substitutedDescriptor = descriptor.substitute(substitutor) ?: continue
|
||||||
|
add(createFunctionCallElementWithArgument(substitutedDescriptor, variable.name.asString(), useReceiverTypes))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFunctionCallElementWithExplicitLambdaParameters(descriptor: FunctionDescriptor, parameterType: JetType, useReceiverTypes: Boolean): LookupElement {
|
private fun createFunctionCallElementWithLambda(descriptor: FunctionDescriptor, parameterType: JetType, explicitLambdaParameters: Boolean, useReceiverTypes: Boolean): LookupElement {
|
||||||
var lookupElement = createLookupElement(descriptor, useReceiverTypes)
|
var lookupElement = createLookupElement(descriptor, useReceiverTypes)
|
||||||
val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments
|
val inputTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments
|
||||||
val lambdaInfo = GenerateLambdaInfo(parameterType, true)
|
val lambdaInfo = GenerateLambdaInfo(parameterType, explicitLambdaParameters)
|
||||||
|
val lambdaPresentation = lambdaPresentation(if (explicitLambdaParameters) parameterType else null)
|
||||||
|
|
||||||
|
// render only the last parameter because all other should be optional and will be omitted
|
||||||
|
val parameterPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderValueParameters(listOf(descriptor.valueParameters.last()), descriptor.hasSynthesizedParameterNames())
|
||||||
|
|
||||||
lookupElement = object : LookupElementDecorator<LookupElement>(lookupElement) {
|
lookupElement = object : LookupElementDecorator<LookupElement>(lookupElement) {
|
||||||
override fun renderElement(presentation: LookupElementPresentation) {
|
override fun renderElement(presentation: LookupElementPresentation) {
|
||||||
super.renderElement(presentation)
|
super.renderElement(presentation)
|
||||||
|
|
||||||
val tails = presentation.getTailFragments()
|
|
||||||
presentation.clearTail()
|
presentation.clearTail()
|
||||||
presentation.appendTailText(" " + buildLambdaPresentation(parameterType) + " ", false)
|
presentation.appendTailText(" $lambdaPresentation ", false)
|
||||||
tails.forEach { presentation.appendTailText(it.text, true) }
|
presentation.appendTailText(parameterPresentation, true)
|
||||||
|
basicFactory.appendContainerAndReceiverInformation(descriptor) { presentation.appendTailText(it, true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleInsert(context: InsertionContext) {
|
override fun handleInsert(context: InsertionContext) {
|
||||||
KotlinFunctionInsertHandler(needTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this)
|
KotlinFunctionInsertHandler(inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +181,7 @@ class LookupElementFactory(
|
|||||||
|
|
||||||
presentation.clearTail()
|
presentation.clearTail()
|
||||||
presentation.appendTailText("($argumentText)", false)
|
presentation.appendTailText("($argumentText)", false)
|
||||||
basicFactory.appendContainerAndReceiverInformation(descriptor) { tail, grayed -> presentation.appendTailText(tail, grayed) }
|
basicFactory.appendContainerAndReceiverInformation(descriptor) { presentation.appendTailText(it, true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleInsert(context: InsertionContext) {
|
override fun handleInsert(context: InsertionContext) {
|
||||||
|
|||||||
+2
-1
@@ -64,7 +64,8 @@ fun insertLambdaTemplate(context: InsertionContext, placeholderRange: TextRange,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildLambdaPresentation(lambdaType: JetType): String {
|
fun lambdaPresentation(lambdaType: JetType?): String {
|
||||||
|
if (lambdaType == null) return "{...}"
|
||||||
val parameterTypes = functionParameterTypes(lambdaType)
|
val parameterTypes = functionParameterTypes(lambdaType)
|
||||||
val parametersPresentation = parameterTypes.map { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) }.joinToString(", ")
|
val parametersPresentation = parameterTypes.map { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) }.joinToString(", ")
|
||||||
return "{ $parametersPresentation -> ... }"
|
return "{ $parametersPresentation -> ... }"
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import com.intellij.openapi.util.TextRange
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.idea.completion.ExpectedInfo
|
import org.jetbrains.kotlin.idea.completion.ExpectedInfo
|
||||||
import org.jetbrains.kotlin.idea.completion.fuzzyType
|
import org.jetbrains.kotlin.idea.completion.fuzzyType
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.buildLambdaPresentation
|
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.insertLambdaTemplate
|
import org.jetbrains.kotlin.idea.completion.handlers.insertLambdaTemplate
|
||||||
|
import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation
|
||||||
import org.jetbrains.kotlin.idea.completion.suppressAutoInsertion
|
import org.jetbrains.kotlin.idea.completion.suppressAutoInsertion
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
|
|
||||||
object LambdaItems {
|
object LambdaItems {
|
||||||
public fun collect(functionExpectedInfos: Collection<ExpectedInfo>): Collection<LookupElement> {
|
public fun collect(functionExpectedInfos: Collection<ExpectedInfo>): Collection<LookupElement> {
|
||||||
@@ -47,7 +47,7 @@ object LambdaItems {
|
|||||||
val singleSignatureLength = singleType?.let { KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(it).size() }
|
val singleSignatureLength = singleType?.let { KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(it).size() }
|
||||||
val offerNoParametersLambda = singleSignatureLength == 0 || singleSignatureLength == 1
|
val offerNoParametersLambda = singleSignatureLength == 0 || singleSignatureLength == 1
|
||||||
if (offerNoParametersLambda) {
|
if (offerNoParametersLambda) {
|
||||||
val lookupElement = LookupElementBuilder.create("{...}")
|
val lookupElement = LookupElementBuilder.create(lambdaPresentation(null))
|
||||||
.withInsertHandler(ArtificialElementInsertHandler("{ ", " }", false))
|
.withInsertHandler(ArtificialElementInsertHandler("{ ", " }", false))
|
||||||
.suppressAutoInsertion()
|
.suppressAutoInsertion()
|
||||||
.assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA_NO_PARAMS)
|
.assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA_NO_PARAMS)
|
||||||
@@ -57,7 +57,7 @@ object LambdaItems {
|
|||||||
|
|
||||||
if (singleSignatureLength != 0) {
|
if (singleSignatureLength != 0) {
|
||||||
for (functionType in distinctTypes) {
|
for (functionType in distinctTypes) {
|
||||||
val lookupString = buildLambdaPresentation(functionType)
|
val lookupString = lambdaPresentation(functionType)
|
||||||
val lookupElement = LookupElementBuilder.create(lookupString)
|
val lookupElement = LookupElementBuilder.create(lookupString)
|
||||||
.withInsertHandler({ context, lookupElement ->
|
.withInsertHandler({ context, lookupElement ->
|
||||||
val offset = context.getStartOffset()
|
val offset = context.getStartOffset()
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
fun xfoo1(option1: String = "", option2: Int = 1, p: () -> Unit){}
|
||||||
|
fun xfoo2(option1: String = "", option2: Int = 1, p: (Int) -> Boolean){}
|
||||||
|
fun xfoo3(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit){}
|
||||||
|
|
||||||
|
fun xfooBad1(option: String = "", notOption: Int, p: (String, Char) -> Unit){}
|
||||||
|
fun xfooBad2(option1: String = "", option2: Int = 1, p: (String, Char) -> Unit, option3: Int = 0){}
|
||||||
|
|
||||||
|
fun test(param: () -> Unit) {
|
||||||
|
xfoo<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { itemText: "xfoo1", tailText: "(option1: String = ..., option2: Int = ..., p: () -> Unit) (<root>)", typeText:"Unit" }
|
||||||
|
// EXIST: { itemText: "xfoo1", tailText: " {...} (p: () -> Unit) (<root>)", typeText:"Unit" }
|
||||||
|
|
||||||
|
// EXIST: { itemText: "xfoo2", tailText: "(option1: String = ..., option2: Int = ..., p: (Int) -> Boolean) (<root>)", typeText:"Unit" }
|
||||||
|
// EXIST: { itemText: "xfoo2", tailText: " {...} (p: (Int) -> Boolean) (<root>)", typeText:"Unit" }
|
||||||
|
|
||||||
|
// EXIST: { itemText: "xfoo3", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
|
||||||
|
// EXIST: { itemText: "xfoo3", tailText: " { String, Char -> ... } (p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
|
||||||
|
|
||||||
|
// EXIST: { itemText: "xfooBad1", tailText: "(option: String = ..., notOption: Int, p: (String, Char) -> Unit) (<root>)", typeText:"Unit" }
|
||||||
|
|
||||||
|
// EXIST: { itemText: "xfooBad2", tailText: "(option1: String = ..., option2: Int = ..., p: (String, Char) -> Unit, option3: Int = ...) (<root>)", typeText:"Unit" }
|
||||||
|
|
||||||
|
// NOTHING_ELSE
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
fun xfoo(option1: String = "", option2: Int = 1, p: () -> Unit){}
|
||||||
|
|
||||||
|
fun test(param: () -> Unit) {
|
||||||
|
xfoo<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: xfoo
|
||||||
|
// TAIL_TEXT: " {...} (p: () -> Unit) (<root>)"
|
||||||
|
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
fun xfoo(option1: String = "", option2: Int = 1, p: () -> Unit){}
|
||||||
|
|
||||||
|
fun test(param: () -> Unit) {
|
||||||
|
xfoo { <caret> }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: xfoo
|
||||||
|
// TAIL_TEXT: " {...} (p: () -> Unit) (<root>)"
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
fun xfoo(option1: String = "", option2: Int = 1, p: (String, Int) -> Unit){}
|
||||||
|
|
||||||
|
fun test(param: () -> Unit) {
|
||||||
|
xfoo<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: xfoo
|
||||||
|
// TAIL_TEXT: " { String, Int -> ... } (p: (String, Int) -> Unit) (<root>)"
|
||||||
|
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
fun xfoo(option1: String = "", option2: Int = 1, p: (String, Int) -> Unit){}
|
||||||
|
|
||||||
|
fun test(param: () -> Unit) {
|
||||||
|
xfoo { s, i -> <caret> }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: xfoo
|
||||||
|
// TAIL_TEXT: " { String, Int -> ... } (p: (String, Int) -> Unit) (<root>)"
|
||||||
|
|
||||||
+6
@@ -1364,6 +1364,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/HigherOrderFunction2.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/HigherOrderFunction2.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OptionalParameters.kt")
|
||||||
|
public void testOptionalParameters() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
||||||
|
|||||||
+6
@@ -1364,6 +1364,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/HigherOrderFunction2.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/HigherOrderFunction2.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OptionalParameters.kt")
|
||||||
|
public void testOptionalParameters() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions/OptionalParameters.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
||||||
|
|||||||
+12
@@ -274,6 +274,18 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OptionalParameters1.kt")
|
||||||
|
public void testOptionalParameters1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OptionalParameters2.kt")
|
||||||
|
public void testOptionalParameters2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/OptionalParameters2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ParameterTypeIsDerivedFromFunction.kt")
|
@TestMetadata("ParameterTypeIsDerivedFromFunction.kt")
|
||||||
public void testParameterTypeIsDerivedFromFunction() throws Exception {
|
public void testParameterTypeIsDerivedFromFunction() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ParameterTypeIsDerivedFromFunction.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/highOrderFunctions/ParameterTypeIsDerivedFromFunction.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user