KotlinHighLevelFunctionParameterInfoHandler: Properly handle vararg parameter arguments.

The computation for which parameter to highlight did not account for
multiple arguments for vararg parameters.

GitOrigin-RevId: dce019225af47749425c80c628332a895a549a57
This commit is contained in:
Mark Punzalan
2022-02-08 08:47:58 +00:00
committed by intellij-monorepo-bot
parent 0ce5fa8955
commit b8eee9d001
9 changed files with 141 additions and 5 deletions
@@ -191,6 +191,23 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
}
}
// Determine the parameter to be highlighted.
val afterTrailingComma = arguments.isNotEmpty() && currentArgumentIndex == arguments.size
val highlightParameterIndex = when {
currentArgumentIndex < arguments.size -> argumentToParameterIndex[arguments[currentArgumentIndex]]
afterTrailingComma -> {
// If last argument is for a vararg parameter, then the argument about to be entered at the cursor should also be
// for that same vararg parameter.
val parameterForLastArgument = argumentMapping[arguments.last()]
if (parameterForLastArgument?.isVararg == true) {
parameterToIndex[parameterForLastArgument]
} else {
null
}
}
else -> null
}
var hasTypeMismatchBeforeCurrent = false
for ((index, argument) in arguments.withIndex()) {
if (index >= currentArgumentIndex) break
@@ -216,7 +233,8 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
valueParameters.size,
parameterIndexToText,
isCallResolvedToCandidate,
hasTypeMismatchBeforeCurrent
hasTypeMismatchBeforeCurrent,
highlightParameterIndex,
)
}
}
@@ -315,7 +333,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
val callInfo = itemToShow.callInfo ?: return false
val (callElement, valueArguments, arguments, argumentToParameterIndex, valueParameterCount, parameterIndexToText,
isCallResolvedToCandidate, hasTypeMismatchBeforeCurrent) = callInfo
isCallResolvedToCandidate, hasTypeMismatchBeforeCurrent, highlightParameterIndex) = callInfo
val supportsMixedNamedArgumentsInTheirOwnPosition =
callElement.languageVersionSettings.supportsFeature(LanguageFeature.MixedNamedArgumentsInTheirOwnPosition)
@@ -333,6 +351,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
var highlightStartOffset = -1
var highlightEndOffset = -1
var isDisabledBeforeHighlight = false
var hasUnmappedArgument = false
var hasUnmappedArgumentBeforeCurrent = false
val usedParameterIndices = HashSet<Int>()
val text = buildString {
@@ -383,6 +402,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
for (valueArgument in valueArguments) {
val parameterIndex = argumentToParameterIndex[valueArgument.getArgumentExpression()]
if (parameterIndex == null) {
hasUnmappedArgument = true
if (argumentIndex < currentArgumentIndex) {
hasUnmappedArgumentBeforeCurrent = true
}
@@ -399,7 +419,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
namedMode = true
}
val shouldHighlight = argumentIndex == currentArgumentIndex
val shouldHighlight = parameterIndex == highlightParameterIndex
appendParameter(parameterIndex, shouldHighlight, valueArgument.isNamed())
}
} else {
@@ -407,6 +427,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
for (argument in arguments) {
val parameterIndex = argumentToParameterIndex[argument]
if (parameterIndex == null) {
hasUnmappedArgument = true
if (argumentIndex <= currentArgumentIndex) {
hasUnmappedArgumentBeforeCurrent = true
}
@@ -415,7 +436,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
}
if (!usedParameterIndices.add(parameterIndex)) continue
val shouldHighlight = argumentIndex == currentArgumentIndex
val shouldHighlight = parameterIndex == highlightParameterIndex
appendParameter(parameterIndex, shouldHighlight)
}
}
@@ -447,7 +468,8 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
val allParametersUsed = usedParameterIndices.size == valueParameterCount
val supportsTrailingCommas = callElement.languageVersionSettings.supportsFeature(LanguageFeature.TrailingCommas)
val afterTrailingComma = arguments.isNotEmpty() && currentArgumentIndex == arguments.size
val tooManyArgs = allParametersUsed && ((!supportsTrailingCommas && afterTrailingComma) || arguments.size > valueParameterCount)
val isInPositionToEnterArgument = !supportsTrailingCommas && afterTrailingComma
val tooManyArgs = allParametersUsed && (isInPositionToEnterArgument || hasUnmappedArgument)
val isDisabled = tooManyArgs || hasTypeMismatchBeforeCurrent || hasUnmappedArgumentBeforeCurrent
@@ -473,6 +495,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
val parameterIndexToText: Map<Int, String>,
val isCallResolvedToCandidate: Boolean,
val hasTypeMismatchBeforeCurrent: Boolean,
val highlightParameterIndex: Int?,
)
data class CandidateInfo(
@@ -436,6 +436,36 @@ public abstract class FirParameterInfoTestGenerated extends AbstractFirParameter
public void testUpdateOnTyping() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/UpdateOnTyping.kt");
}
@TestMetadata("Vararg.kt")
public void testVararg() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/Vararg.kt");
}
@TestMetadata("VarargFirstArgTrailingComma.kt")
public void testVarargFirstArgTrailingComma() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/VarargFirstArgTrailingComma.kt");
}
@TestMetadata("VarargMultipleArgsTrailingComma.kt")
public void testVarargMultipleArgsTrailingComma() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/VarargMultipleArgsTrailingComma.kt");
}
@TestMetadata("VarargNamedArg.kt")
public void testVarargNamedArg() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/VarargNamedArg.kt");
}
@TestMetadata("VarargSpreadArg.kt")
public void testVarargSpreadArg() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/VarargSpreadArg.kt");
}
@TestMetadata("VarargUpdateOnTyping.kt")
public void testVarargUpdateOnTyping() throws Exception {
runTest("../idea/tests/testData/parameterInfo/functionCall/VarargUpdateOnTyping.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@@ -436,6 +436,36 @@ public abstract class ParameterInfoTestGenerated extends AbstractParameterInfoTe
public void testUpdateOnTyping() throws Exception {
runTest("testData/parameterInfo/functionCall/UpdateOnTyping.kt");
}
@TestMetadata("Vararg.kt")
public void testVararg() throws Exception {
runTest("testData/parameterInfo/functionCall/Vararg.kt");
}
@TestMetadata("VarargFirstArgTrailingComma.kt")
public void testVarargFirstArgTrailingComma() throws Exception {
runTest("testData/parameterInfo/functionCall/VarargFirstArgTrailingComma.kt");
}
@TestMetadata("VarargMultipleArgsTrailingComma.kt")
public void testVarargMultipleArgsTrailingComma() throws Exception {
runTest("testData/parameterInfo/functionCall/VarargMultipleArgsTrailingComma.kt");
}
@TestMetadata("VarargNamedArg.kt")
public void testVarargNamedArg() throws Exception {
runTest("testData/parameterInfo/functionCall/VarargNamedArg.kt");
}
@TestMetadata("VarargSpreadArg.kt")
public void testVarargSpreadArg() throws Exception {
runTest("testData/parameterInfo/functionCall/VarargSpreadArg.kt");
}
@TestMetadata("VarargUpdateOnTyping.kt")
public void testVarargUpdateOnTyping() throws Exception {
runTest("testData/parameterInfo/functionCall/VarargUpdateOnTyping.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@@ -0,0 +1,8 @@
fun m(x: Boolean, vararg y: Int) = 2
fun d() {
m(true, 1, <caret>2)
}
/*
Text: (x: Boolean, <highlight>vararg y: Int</highlight>), Disabled: false, Strikeout: false, Green: true
*/
@@ -0,0 +1,8 @@
fun m(x: Boolean, vararg y: Int) = 2
fun d() {
m(true,<caret>)
}
/*
Text: (x: Boolean, <highlight>vararg y: Int</highlight>), Disabled: false, Strikeout: false, Green: true
*/
@@ -0,0 +1,8 @@
fun m(x: Boolean, vararg y: Int) = 2
fun d() {
m(true, 1, 2,<caret>)
}
/*
Text: (x: Boolean, <highlight>vararg y: Int</highlight>), Disabled: false, Strikeout: false, Green: true
*/
@@ -0,0 +1,9 @@
fun m(x: Boolean, vararg y: Int) = 2
fun d() {
val a = intArrayOf(1, 2, 3)
m(y = <caret>a, x = true)
}
/*
Text: (<highlight>[vararg y: Int]</highlight>, [x: Boolean]), Disabled: false, Strikeout: false, Green: true
*/
@@ -0,0 +1,9 @@
fun m(x: Boolean, vararg y: Int) = 2
fun d() {
val a = intArrayOf(1, 2, 3)
m(true, 1, *a<caret>, 4)
}
/*
Text: (x: Boolean, <highlight>vararg y: Int</highlight>), Disabled: false, Strikeout: false, Green: true
*/
@@ -0,0 +1,11 @@
fun m(x: Boolean, vararg y: Int) = 2
fun d() {
m(true, <caret>)
}
// TYPE: "true, "
/*
Text: (x: Boolean, <highlight>vararg y: Int</highlight>), Disabled: true, Strikeout: false, Green: true
*/