Reformat parameterInfo

This commit is contained in:
Nikolay Krasko
2018-11-15 13:10:53 +03:00
parent b1cf98d82a
commit c568ea043f
4 changed files with 71 additions and 55 deletions
@@ -53,7 +53,8 @@ private fun getArgumentNameHintsForCallCandidate(
return resolvedCall.valueArguments.mapNotNull { (valueParam: ValueParameterDescriptor, resolvedArg) -> return resolvedCall.valueArguments.mapNotNull { (valueParam: ValueParameterDescriptor, resolvedArg) ->
if (resultingDescriptor is FunctionInvokeDescriptor && if (resultingDescriptor is FunctionInvokeDescriptor &&
valueParam.type.extractParameterNameFromFunctionTypeArgument() == null) { valueParam.type.extractParameterNameFromFunctionTypeArgument() == null
) {
return@mapNotNull null return@mapNotNull null
} }
@@ -73,7 +74,7 @@ private fun getArgumentNameHintsForCallCandidate(
} }
} }
private fun KtExpression.isUnclearExpression() = when(this) { private fun KtExpression.isUnclearExpression() = when (this) {
is KtConstantExpression, is KtThisExpression, is KtBinaryExpression, is KtStringTemplateExpression -> true is KtConstantExpression, is KtThisExpression, is KtBinaryExpression, is KtStringTemplateExpression -> true
is KtPrefixExpression -> baseExpression is KtConstantExpression && (operationToken == KtTokens.PLUS || operationToken == KtTokens.MINUS) is KtPrefixExpression -> baseExpression is KtConstantExpression && (operationToken == KtTokens.PLUS || operationToken == KtTokens.MINUS)
else -> false else -> false
@@ -57,7 +57,9 @@ import java.awt.Color
import java.util.* import java.util.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
class KotlinFunctionParameterInfoHandler : KotlinParameterInfoWithCallHandlerBase<KtValueArgumentList, KtValueArgument>(KtValueArgumentList::class, KtValueArgument::class) { class KotlinFunctionParameterInfoHandler :
KotlinParameterInfoWithCallHandlerBase<KtValueArgumentList, KtValueArgument>(KtValueArgumentList::class, KtValueArgument::class) {
override fun getActualParameters(arguments: KtValueArgumentList) = arguments.arguments.toTypedArray() override fun getActualParameters(arguments: KtValueArgumentList) = arguments.arguments.toTypedArray()
override fun getActualParametersRBraceType() = KtTokens.RPAR override fun getActualParametersRBraceType() = KtTokens.RPAR
@@ -67,6 +69,7 @@ class KotlinFunctionParameterInfoHandler : KotlinParameterInfoWithCallHandlerBas
class KotlinLambdaParameterInfoHandler : class KotlinLambdaParameterInfoHandler :
KotlinParameterInfoWithCallHandlerBase<KtLambdaArgument, KtLambdaArgument>(KtLambdaArgument::class, KtLambdaArgument::class) { KotlinParameterInfoWithCallHandlerBase<KtLambdaArgument, KtLambdaArgument>(KtLambdaArgument::class, KtLambdaArgument::class) {
override fun getActualParameters(lambdaArgument: KtLambdaArgument) = arrayOf(lambdaArgument) override fun getActualParameters(lambdaArgument: KtLambdaArgument) = arrayOf(lambdaArgument)
override fun getActualParametersRBraceType() = KtTokens.RBRACE override fun getActualParametersRBraceType() = KtTokens.RBRACE
@@ -79,17 +82,20 @@ class KotlinLambdaParameterInfoHandler :
} }
} }
class KotlinArrayAccessParameterInfoHandler : KotlinParameterInfoWithCallHandlerBase<KtContainerNode, KtExpression>(KtContainerNode::class, KtExpression::class) { class KotlinArrayAccessParameterInfoHandler :
KotlinParameterInfoWithCallHandlerBase<KtContainerNode, KtExpression>(KtContainerNode::class, KtExpression::class) {
override fun getArgumentListAllowedParentClasses() = setOf(KtArrayAccessExpression::class.java) override fun getArgumentListAllowedParentClasses() = setOf(KtArrayAccessExpression::class.java)
override fun getActualParameters(containerNode: KtContainerNode): Array<out KtExpression> = containerNode.allChildren.filterIsInstance<KtExpression>().toList().toTypedArray() override fun getActualParameters(containerNode: KtContainerNode): Array<out KtExpression> =
containerNode.allChildren.filterIsInstance<KtExpression>().toList().toTypedArray()
override fun getActualParametersRBraceType() = KtTokens.RBRACKET override fun getActualParametersRBraceType() = KtTokens.RBRACKET
} }
abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement, TArgument : KtElement>( abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement, TArgument : KtElement>(
private val argumentListClass: KClass<TArgumentList>, private val argumentListClass: KClass<TArgumentList>,
private val argumentClass: KClass<TArgument> private val argumentClass: KClass<TArgument>
) : ParameterInfoHandlerWithTabActionSupport<TArgumentList, FunctionDescriptor, TArgument> { ) : ParameterInfoHandlerWithTabActionSupport<TArgumentList, FunctionDescriptor, TArgument> {
companion object { companion object {
@@ -136,14 +142,16 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
val resolutionFacade = file.getResolutionFacade() val resolutionFacade = file.getResolutionFacade()
val candidates = val candidates =
call.resolveCandidates(bindingContext, resolutionFacade) call.resolveCandidates(bindingContext, resolutionFacade)
.map { it.resultingDescriptor } .map { it.resultingDescriptor }
.distinctBy { it.original } .distinctBy { it.original }
val shadowedDeclarationsFilter = ShadowedDeclarationsFilter(bindingContext, val shadowedDeclarationsFilter = ShadowedDeclarationsFilter(
resolutionFacade, bindingContext,
call.callElement, resolutionFacade,
call.explicitReceiver as? ReceiverValue) call.callElement,
call.explicitReceiver as? ReceiverValue
)
context.itemsToShow = shadowedDeclarationsFilter.filter(candidates).toTypedArray() context.itemsToShow = shadowedDeclarationsFilter.filter(candidates).toTypedArray()
return argumentList return argumentList
@@ -186,7 +194,7 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
val project = argumentList.project val project = argumentList.project
val (substitutedDescriptor, argumentToParameter, highlightParameterIndex, isGrey) = matchCallWithSignature( val (substitutedDescriptor, argumentToParameter, highlightParameterIndex, isGrey) = matchCallWithSignature(
call, itemToShow, currentArgumentIndex, bindingContext, argumentList.getResolutionFacade() call, itemToShow, currentArgumentIndex, bindingContext, argumentList.getResolutionFacade()
) ?: return false ) ?: return false
var boldStartOffset = -1 var boldStartOffset = -1
@@ -261,6 +269,7 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
//TODO //TODO
override fun couldShowInLookup() = false override fun couldShowInLookup() = false
override fun getParametersForLookup(item: LookupElement, context: ParameterInfoContext) = emptyArray<Any>() override fun getParametersForLookup(item: LookupElement, context: ParameterInfoContext) = emptyArray<Any>()
override fun getParametersForDocumentation(item: FunctionDescriptor, context: ParameterInfoContext) = emptyArray<Any>() override fun getParametersForDocumentation(item: FunctionDescriptor, context: ParameterInfoContext) = emptyArray<Any>()
@@ -311,8 +320,7 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
if (expression is KtConstantExpression || expression is KtStringTemplateExpression) { if (expression is KtConstantExpression || expression is KtStringTemplateExpression) {
if (text.startsWith("\"")) { if (text.startsWith("\"")) {
return "\"...\"" return "\"...\""
} } else if (text.startsWith("\'")) {
else if (text.startsWith("\'")) {
return "\'...\'" return "\'...\'"
} }
} }
@@ -330,27 +338,27 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
} }
private fun isResolvedToDescriptor( private fun isResolvedToDescriptor(
call: Call, call: Call,
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
bindingContext: BindingContext bindingContext: BindingContext
): Boolean { ): Boolean {
val target = call.getResolvedCall(bindingContext)?.resultingDescriptor as? FunctionDescriptor val target = call.getResolvedCall(bindingContext)?.resultingDescriptor as? FunctionDescriptor
return target != null && descriptorsEqual(target, functionDescriptor) return target != null && descriptorsEqual(target, functionDescriptor)
} }
private data class SignatureInfo( private data class SignatureInfo(
val substitutedDescriptor: FunctionDescriptor, val substitutedDescriptor: FunctionDescriptor,
val argumentToParameter: (ValueArgument) -> ValueParameterDescriptor?, val argumentToParameter: (ValueArgument) -> ValueParameterDescriptor?,
val highlightParameterIndex: Int?, val highlightParameterIndex: Int?,
val isGrey: Boolean val isGrey: Boolean
) )
private fun matchCallWithSignature( private fun matchCallWithSignature(
call: Call, call: Call,
overload: FunctionDescriptor, overload: FunctionDescriptor,
currentArgumentIndex: Int, currentArgumentIndex: Int,
bindingContext: BindingContext, bindingContext: BindingContext,
resolutionFacade: ResolutionFacade resolutionFacade: ResolutionFacade
): SignatureInfo? { ): SignatureInfo? {
if (currentArgumentIndex == 0 && call.valueArguments.isEmpty() && overload.valueParameters.isEmpty()) { if (currentArgumentIndex == 0 && call.valueArguments.isEmpty() && overload.valueParameters.isEmpty()) {
return SignatureInfo(overload, { null }, null, isGrey = false) return SignatureInfo(overload, { null }, null, isGrey = false)
@@ -370,8 +378,7 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
if (arguments.size > currentArgumentIndex) { if (arguments.size > currentArgumentIndex) {
currentArgument = arguments[currentArgumentIndex] currentArgument = arguments[currentArgumentIndex]
callToUse = call callToUse = call
} } else {
else {
// add dummy current argument if we don't have one // add dummy current argument if we don't have one
currentArgument = object : ValueArgument { currentArgument = object : ValueArgument {
override fun getArgumentExpression(): KtExpression? = null override fun getArgumentExpression(): KtExpression? = null
@@ -383,9 +390,9 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
} }
callToUse = object : DelegatingCall(call) { callToUse = object : DelegatingCall(call) {
val argumentsWithCurrent = val argumentsWithCurrent =
arguments + currentArgument + arguments + currentArgument +
// For array set method call, also add the argument in the right-hand side // For array set method call, also add the argument in the right-hand side
(if (isArraySetMethod) listOf(call.valueArguments.last()) else listOf()) (if (isArraySetMethod) listOf(call.valueArguments.last()) else listOf())
override fun getValueArguments() = argumentsWithCurrent override fun getValueArguments() = argumentsWithCurrent
override fun getFunctionLiteralArguments() = emptyList<LambdaArgument>() override fun getFunctionLiteralArguments() = emptyList<LambdaArgument>()
@@ -398,8 +405,8 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
// The second way is needed for the case when the descriptor was invalidated and new one has been built. // The second way is needed for the case when the descriptor was invalidated and new one has been built.
// See testLocalFunctionBug(). // See testLocalFunctionBug().
val resolvedCall = candidates.firstOrNull { it.resultingDescriptor.original == overload.original } val resolvedCall = candidates.firstOrNull { it.resultingDescriptor.original == overload.original }
?: candidates.firstOrNull { descriptorsEqual(it.resultingDescriptor, overload) } ?: candidates.firstOrNull { descriptorsEqual(it.resultingDescriptor, overload) }
?: return null ?: return null
val resultingDescriptor = resolvedCall.resultingDescriptor val resultingDescriptor = resolvedCall.resultingDescriptor
fun argumentToParameter(argument: ValueArgument): ValueParameterDescriptor? { fun argumentToParameter(argument: ValueArgument): ValueParameterDescriptor? {
@@ -417,13 +424,13 @@ abstract class KotlinParameterInfoWithCallHandlerBase<TArgumentList : KtElement,
// grey out if not all arguments before the current are matched // grey out if not all arguments before the current are matched
val isGrey = argumentsBeforeCurrent.any { argument -> val isGrey = argumentsBeforeCurrent.any { argument ->
resolvedCall.getArgumentMapping(argument).isError() && resolvedCall.getArgumentMapping(argument).isError() &&
!argument.hasError(bindingContext) /* ignore arguments that have error type */ !argument.hasError(bindingContext) /* ignore arguments that have error type */
} }
return SignatureInfo(resultingDescriptor, ::argumentToParameter, highlightParameterIndex, isGrey) return SignatureInfo(resultingDescriptor, ::argumentToParameter, highlightParameterIndex, isGrey)
} }
private fun ValueArgument.hasError(bindingContext: BindingContext) private fun ValueArgument.hasError(bindingContext: BindingContext) =
= getArgumentExpression()?.let { bindingContext.getType(it) }?.isError ?: true getArgumentExpression()?.let { bindingContext.getType(it) }?.isError ?: true
// we should not compare descriptors directly because partial resolve is involved // we should not compare descriptors directly because partial resolve is involved
private fun descriptorsEqual(descriptor1: FunctionDescriptor, descriptor2: FunctionDescriptor): Boolean { private fun descriptorsEqual(descriptor1: FunctionDescriptor, descriptor2: FunctionDescriptor): Boolean {
@@ -60,14 +60,16 @@ class KotlinFunctionTypeArgumentInfoHandler : KotlinTypeArgumentInfoHandlerBase<
val call = callElement.getCall(bindingContext) ?: return null val call = callElement.getCall(bindingContext) ?: return null
val candidates = call.resolveCandidates(bindingContext, callElement.getResolutionFacade()) val candidates = call.resolveCandidates(bindingContext, callElement.getResolutionFacade())
return candidates return candidates
.map { it.resultingDescriptor } .map { it.resultingDescriptor }
.distinctBy { buildPresentation(it.typeParameters, -1).first } .distinctBy { buildPresentation(it.typeParameters, -1).first }
} }
override fun getArgumentListAllowedParentClasses() = setOf(KtCallElement::class.java) override fun getArgumentListAllowedParentClasses() = setOf(KtCallElement::class.java)
} }
abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDescriptor> : ParameterInfoHandlerWithTabActionSupport<KtTypeArgumentList, TParameterOwner, KtTypeProjection> { abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDescriptor> :
ParameterInfoHandlerWithTabActionSupport<KtTypeArgumentList, TParameterOwner, KtTypeProjection> {
protected abstract fun fetchTypeParameters(descriptor: TParameterOwner): List<TypeParameterDescriptor> protected abstract fun fetchTypeParameters(descriptor: TParameterOwner): List<TypeParameterDescriptor>
protected abstract fun findParameterOwners(argumentList: KtTypeArgumentList): Collection<TParameterOwner>? protected abstract fun findParameterOwners(argumentList: KtTypeArgumentList): Collection<TParameterOwner>?
@@ -78,7 +80,8 @@ abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDe
override fun getActualParameters(o: KtTypeArgumentList) = o.arguments.toTypedArray() override fun getActualParameters(o: KtTypeArgumentList) = o.arguments.toTypedArray()
override fun getArgListStopSearchClasses() = setOf(KtNamedFunction::class.java, KtVariableDeclaration::class.java, KtClassOrObject::class.java) override fun getArgListStopSearchClasses() =
setOf(KtNamedFunction::class.java, KtVariableDeclaration::class.java, KtClassOrObject::class.java)
override fun getParameterCloseChars() = ParameterInfoUtils.DEFAULT_PARAMETER_CLOSE_CHARS override fun getParameterCloseChars() = ParameterInfoUtils.DEFAULT_PARAMETER_CLOSE_CHARS
@@ -124,8 +127,8 @@ abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDe
val offset = context.offset val offset = context.offset
val parameterIndex = argumentList.allChildren val parameterIndex = argumentList.allChildren
.takeWhile { it.startOffset < offset } .takeWhile { it.startOffset < offset }
.count { it.node.elementType == KtTokens.COMMA } .count { it.node.elementType == KtTokens.COMMA }
context.setCurrentParameter(parameterIndex) context.setCurrentParameter(parameterIndex)
} }
@@ -144,16 +147,18 @@ abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDe
val (text, currentParameterStart, currentParameterEnd) = buildPresentation(parameters, currentIndex) val (text, currentParameterStart, currentParameterEnd) = buildPresentation(parameters, currentIndex)
context.setupUIComponentPresentation(text, currentParameterStart, currentParameterEnd, context.setupUIComponentPresentation(
false/*isDisabled*/, false/*strikeout*/, false/*isDisabledBeforeHighlight*/, text, currentParameterStart, currentParameterEnd,
context.defaultParameterColor) false/*isDisabled*/, false/*strikeout*/, false/*isDisabledBeforeHighlight*/,
context.defaultParameterColor
)
return true return true
} }
protected fun buildPresentation( protected fun buildPresentation(
parameters: List<TypeParameterDescriptor>, parameters: List<TypeParameterDescriptor>,
currentIndex: Int currentIndex: Int
): Triple<String, Int, Int> { ): Triple<String, Int, Int> {
var currentParameterStart = -1 var currentParameterStart = -1
var currentParameterEnd = -1 var currentParameterEnd = -1
@@ -172,7 +177,8 @@ abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDe
} }
when (parameter.variance) { when (parameter.variance) {
Variance.INVARIANT -> {} Variance.INVARIANT -> {
}
Variance.IN_VARIANCE -> append("in ") Variance.IN_VARIANCE -> append("in ")
Variance.OUT_VARIANCE -> append("out ") Variance.OUT_VARIANCE -> append("out ")
} }
@@ -185,8 +191,7 @@ abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDe
if (!upperBound.isAnyOrNullableAny() || upperBound.nullability() == TypeNullability.NOT_NULL) { // skip Any? or Any! if (!upperBound.isAnyOrNullableAny() || upperBound.nullability() == TypeNullability.NOT_NULL) { // skip Any? or Any!
append(" : ").append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(upperBound)) append(" : ").append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(upperBound))
} }
} } else if (upperBounds.size > 1) {
else if (upperBounds.size > 1) {
needWhere = true needWhere = true
} }
@@ -205,7 +210,9 @@ abstract class KotlinTypeArgumentInfoHandlerBase<TParameterOwner : DeclarationDe
for (upperBound in upperBounds) { for (upperBound in upperBounds) {
if (needComma) append(", ") if (needComma) append(", ")
needComma = true needComma = true
append(parameter.name.asString()).append(" : ").append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(upperBound)) append(parameter.name.asString())
append(" : ")
append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(upperBound))
} }
} }
} }
@@ -134,7 +134,8 @@ private fun isUnclearType(type: KotlinType, element: KtCallableDeclaration): Boo
return false return false
} }
if (resolvedDescriptor is ConstructorDescriptor && if (resolvedDescriptor is ConstructorDescriptor &&
(resolvedDescriptor.constructedClass.declaredTypeParameters.isEmpty() || initializer.typeArgumentList != null)) { (resolvedDescriptor.constructedClass.declaredTypeParameters.isEmpty() || initializer.typeArgumentList != null)
) {
return false return false
} }
} }