From b72da6c4fcc74e210571146da8a843f3b106b9b0 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Mon, 30 Dec 2019 20:52:54 +0700 Subject: [PATCH] Formatter: support trailing comma in destruction declarations #KT-34744 --- .../idea/formatter/KotlinCommonBlock.kt | 17 +++ .../kotlin/idea/util/FormatterUtil.kt | 49 ++++--- .../TrailingCommaPostFormatProcessor.kt | 7 + .../formatter/Multideclaration.after.kt | 2 +- ...structionDeclarationsInLambda.after.inv.kt | 102 +++++++++++++++ .../DestructionDeclarationsInLambda.after.kt | 114 +++++++++++++++++ .../DestructionDeclarationsInLambda.kt | 66 ++++++++++ .../MultiVariableDeclaration.after.inv.kt | 105 +++++++++++++++ .../MultiVariableDeclaration.after.kt | 120 ++++++++++++++++++ .../MultiVariableDeclaration.kt | 90 +++++++++++++ .../formatter/FormatterTestGenerated.java | 46 +++++++ 11 files changed, 700 insertions(+), 18 deletions(-) create mode 100644 idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.inv.kt create mode 100644 idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.kt create mode 100644 idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.kt create mode 100644 idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.inv.kt create mode 100644 idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.kt create mode 100644 idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.kt diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt index 996836728a3..838a23988ba 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt @@ -642,6 +642,23 @@ abstract class KotlinCommonBlock( } } + elementType === DESTRUCTURING_DECLARATION -> { + nodePsi as KtDestructuringDeclaration + if (nodePsi.valOrVarKeyword == null) return defaultTrailingCommaWrappingStrategy(LPAR, RPAR) + else if (nodePsi.needTrailingComma(settings)) { + val check = thisOrPrevIsMultiLineElement(COMMA, LPAR, RPAR) + return block@{ childElement -> + val childElementType = childElement.elementType + if (childElementType === EQ) return@block null + createWrapAlwaysIf( + childElementType === RPAR || + getSiblingWithoutWhitespaceAndComments(childElement)?.elementType === LPAR || + getSiblingWithoutWhitespaceAndComments(childElement, true) != null && check(childElement) + ) + } + } + } + elementType === INDICES -> return defaultTrailingCommaWrappingStrategy(LBRACKET, RBRACKET) elementType === TYPE_PARAMETER_LIST -> return defaultTrailingCommaWrappingStrategy(LT, GT) diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt index 7f84d111eb8..6d888cf34e6 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt @@ -13,12 +13,11 @@ import com.intellij.psi.PsiElement import com.intellij.psi.codeStyle.CodeStyleSettings import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings +import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtFunctionLiteral import org.jetbrains.kotlin.psi.KtWhenEntry -import org.jetbrains.kotlin.psi.KtWhenExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.utils.addToStdlib.safeAs /* * ASTBlock.node is nullable, this extension was introduced to minimize changes @@ -48,22 +47,38 @@ fun PsiElement.getLineCount(): Int { fun PsiElement.isMultiline() = getLineCount() > 1 -fun KtFunctionLiteral.needTrailingComma(settings: CodeStyleSettings): Boolean = valueParameterList?.trailingComma != null || - settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA && - run(fun(): Boolean { - val startOffset = valueParameterList?.startOffset ?: return false - val endOffset = arrow?.endOffset ?: return false - return containsLineBreakInThis(startOffset, endOffset) - }) +fun KtFunctionLiteral.needTrailingComma(settings: CodeStyleSettings): Boolean = needTrailingComma( + settings = settings, + trailingComma = { valueParameterList?.trailingComma }, + globalStartOffset = { valueParameterList?.startOffset }, + globalEndOffset = { arrow?.endOffset } +) -fun KtWhenEntry.needTrailingComma(settings: CodeStyleSettings): Boolean = trailingComma != null || - !isElse && - settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA && - parent.safeAs()?.leftParenthesis != null && - run(fun(): Boolean { - val endOffset = arrow?.endOffset ?: return false - return containsLineBreakInThis(startOffset, endOffset) - }) +fun KtWhenEntry.needTrailingComma(settings: CodeStyleSettings): Boolean = needTrailingComma( + settings = settings, + trailingComma = { trailingComma }, + additionalCheck = { !isElse }, + globalEndOffset = { arrow?.endOffset } +) + +fun KtDestructuringDeclaration.needTrailingComma(settings: CodeStyleSettings): Boolean = needTrailingComma( + settings = settings, + trailingComma = { trailingComma }, + globalStartOffset = { lPar?.startOffset }, + globalEndOffset = { rPar?.endOffset } +) + +fun T.needTrailingComma( + settings: CodeStyleSettings, + trailingComma: T.() -> PsiElement?, + additionalCheck: () -> Boolean = { true }, + globalStartOffset: T.() -> Int? = PsiElement::startOffset, + globalEndOffset: T.() -> Int? = PsiElement::endOffset +) = trailingComma() != null || settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA && additionalCheck() && run(fun(): Boolean { + val startOffset = globalStartOffset() ?: return false + val endOffset = globalEndOffset() ?: return false + return containsLineBreakInThis(startOffset, endOffset) +}) fun PsiElement.containsLineBreakInThis(globalStartOffset: Int, globalEndOffset: Int): Boolean { val textRange = TextRange.create(globalStartOffset, globalEndOffset).shiftLeft(startOffset) diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt index 86445f5cbda..20dc20f1a20 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt @@ -66,6 +66,11 @@ private class TrailingCommaVisitor(val settings: CodeStyleSettings) : KtTreeVisi super.visitWhenEntry(jetWhenEntry) } + override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) = + processCommaOwnerIfInRange(destructuringDeclaration) { + super.visitDestructuringDeclaration(destructuringDeclaration) + } + private fun processCommaOwnerIfInRange(element: KtElement, preHook: () -> Unit = {}) = processIfInRange(element) { preHook() processCommaOwner(element) @@ -97,6 +102,7 @@ private class TrailingCommaVisitor(val settings: CodeStyleSettings) : KtTreeVisi get() = when { this is KtWhenEntry -> needTrailingComma(settings) parent is KtFunctionLiteral -> parent.cast().needTrailingComma(settings) + this is KtDestructuringDeclaration -> needTrailingComma(settings) else -> settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA && isMultiline() } @@ -191,5 +197,6 @@ private val PsiElement.lastCommaOwnerOrComma: PsiElement? private val PsiElement.lastSignificantChild: PsiElement? get() = when (this) { is KtWhenEntry -> arrow + is KtDestructuringDeclaration -> rPar else -> lastChild } diff --git a/idea/testData/formatter/Multideclaration.after.kt b/idea/testData/formatter/Multideclaration.after.kt index d2bbf5afaff..7d5757ddd3d 100644 --- a/idea/testData/formatter/Multideclaration.after.kt +++ b/idea/testData/formatter/Multideclaration.after.kt @@ -10,6 +10,6 @@ fun test() { items, shippingMethods, addresses, - preferredAddressId + preferredAddressId, ) = argument } \ No newline at end of file diff --git a/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.inv.kt b/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.inv.kt new file mode 100644 index 00000000000..f2d2a81d571 --- /dev/null +++ b/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.inv.kt @@ -0,0 +1,102 @@ +// SET_TRUE: ALLOW_TRAILING_COMMA + +val x: (Pair, Int) -> Unit = { + ( + x, y, + ), /* FIXME: The result should converge in one iteration */ z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y), z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, + y), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, + y), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, // adw + y, + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, /* val x: (Pair, Int) -> Unit = { (x, y), z, -> + println(x) +}*/ + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y), z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y/**/), z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y/* +*/), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (/**/x /**/ /* +*/, // awdawd + y/* +*/), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (/**/x /**/ /* +*/, // awdawd + y/* +*/), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, y, + ), + z, + -> + println(x) +} \ No newline at end of file diff --git a/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.kt b/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.kt new file mode 100644 index 00000000000..71318b3b3bd --- /dev/null +++ b/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.kt @@ -0,0 +1,114 @@ +// SET_TRUE: ALLOW_TRAILING_COMMA + +val x: (Pair, Int) -> Unit = { + ( + x, y, + ), /* FIXME: The result should converge in one iteration */ z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y), z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, + y, + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, + y, + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, // adw + y, + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, /* val x: (Pair, Int) -> Unit = { (x, y), z, -> + println(x) +}*/ + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y), z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (x, y/**/), z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, + y,/* +*/ + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( +/**/ + x, /**/ /* +*/ // awdawd + y,/* +*/ + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( +/**/ + x, /**/ /* +*/ // awdawd + y,/* +*/ + ), + z, + -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + ( + x, y, + ), + z, + -> + println(x) +} \ No newline at end of file diff --git a/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.kt b/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.kt new file mode 100644 index 00000000000..f80aa3aace8 --- /dev/null +++ b/idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.kt @@ -0,0 +1,66 @@ +// SET_TRUE: ALLOW_TRAILING_COMMA + +val x: (Pair, Int) -> Unit = { (x, y,), /* FIXME: The result should converge in one iteration */ z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x, y), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x, + y), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { ( + x, + y), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { ( + x // adw + ,y,), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x /* val x: (Pair, Int) -> Unit = { (x, y), z, -> + println(x) +}*/,), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x, y), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x, y/**/), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x, y/* +*/), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (/**/x /**/ /* +*/, // awdawd + y/* +*/), z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { + (/**/x /**/ /* +*/, // awdawd + y/* +*/), + z, -> + println(x) +} + +val x: (Pair, Int) -> Unit = { (x, y,), + z, -> + println(x) +} \ No newline at end of file diff --git a/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.inv.kt b/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.inv.kt new file mode 100644 index 00000000000..47d172ba926 --- /dev/null +++ b/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.inv.kt @@ -0,0 +1,105 @@ +// SET_TRUE: ALLOW_TRAILING_COMMA + +fun test() { + val (a, b) = 1 to 2 + + val (a, b) = 1 to + 2 + + val (a, b) = 1 + to + 2 + + + val ( + a, b, + ) = 1 to 2 + + val ( + a, + ) = + b + + val ( + a, + ) = b + + val (a, b + ) = 1 to 2 + + val (a, + b) = 1 to 2 + + val ( + a, b + ) = 1 to 2 + + val ( + a, b, + ) = 1 to 2 + + val (a, b, c, + d, f + ) = 1 to 2 + + val ( + a, b, c, + d, f, + ) = 1 to 2 + + val (a, b/**/) = 1 to 2 + + val (a, /**/b/**/) /**/ =/**/ 1 to + 2 + + val (a,/**/ b) = 1 + to + 2 + + val ( + a, b,/**/ + ) = 1 to 2 + + val ( + a,/**/ b,/**//**/ + ) = 1 to 2 + + val ( + a,/**//**/ + ) = + b + + val ( + a, + ) = b + + val (a, b/**/ + ) = 1 to 2 + + val (a, b// awd + ) = 1 to 2 + + val (a,/**/ b /**/ // awd + ) = 1 to 2 + + val (a, // ad + /**/b) = 1 to 2 + + val ( + a, b // fe + /**/)/**/ = 1 to 2 + + val ( + a, b, // awd + ) = 1 to 2 + + val (a, b, c, + d, f // awd + /* + */) = 1 to 2 + + val ( + a, b, c, + d, f, // awd + ) = 1 to 2 +} \ No newline at end of file diff --git a/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.kt b/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.kt new file mode 100644 index 00000000000..cfabfc847da --- /dev/null +++ b/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.kt @@ -0,0 +1,120 @@ +// SET_TRUE: ALLOW_TRAILING_COMMA + +fun test() { + val (a, b) = 1 to 2 + + val (a, b) = 1 to + 2 + + val (a, b) = 1 + to + 2 + + + val ( + a, b, + ) = 1 to 2 + + val ( + a, + ) = + b + + val ( + a, + ) = b + + val ( + a, b, + ) = 1 to 2 + + val ( + a, + b, + ) = 1 to 2 + + val ( + a, b, + ) = 1 to 2 + + val ( + a, b, + ) = 1 to 2 + + val ( + a, b, c, + d, f, + ) = 1 to 2 + + val ( + a, b, c, + d, f, + ) = 1 to 2 + + val (a, b/**/) = 1 to 2 + + val (a, /**/b/**/) /**/ =/**/ 1 to + 2 + + val (a,/**/ b) = 1 + to + 2 + + val ( + a, b,/**/ + ) = 1 to 2 + + val ( + a,/**/ b,/**//**/ + ) = 1 to 2 + + val ( + a,/**//**/ + ) = + b + + val ( + a, + ) = b + + val ( + a, b,/**/ + ) = 1 to 2 + + val ( + a, b,// awd + ) = 1 to 2 + + val ( + a,/**/ b, /**/ // awd + ) = 1 to 2 + + val ( + a, // ad + /**/ + b, + ) = 1 to 2 + + val ( + a, + b, // fe + /**/ + )/**/ = 1 to 2 + + val ( + a, b, // awd + ) = 1 to 2 + + val ( + a, b, c, + d, + f, // awd + /* + */ + ) = 1 to 2 + + val ( + a, b, c, + d, f, // awd + ) = 1 to 2 +} \ No newline at end of file diff --git a/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.kt b/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.kt new file mode 100644 index 00000000000..54fad967e6b --- /dev/null +++ b/idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.kt @@ -0,0 +1,90 @@ +// SET_TRUE: ALLOW_TRAILING_COMMA + +fun test() { + val (a, b) = 1 to 2 + + val (a, b) = 1 to + 2 + + val (a, b) = 1 + to + 2 + + + val (a, b,) = 1 to 2 + + val (a,) = + b + + val (a,) = b + + val (a, b + ) = 1 to 2 + + val (a, + b) = 1 to 2 + + val ( + a, b + ) = 1 to 2 + + val ( + a, b, + ) = 1 to 2 + + val (a, b, c, + d, f + ) = 1 to 2 + + val (a, b, c, + d, f, + ) = 1 to 2 + + val (a, b/**/) = 1 to 2 + + val (a, /**/b/**/) /**/=/**/ 1 to + 2 + + val (a,/**/ b) = 1 + to + 2 + + val (a, b/**/,) = 1 to 2 + + val (a/**/, b/**/,/**/) = 1 to 2 + + val (a/**/,/**/) = + b + + val (a,) = b + + val (a, b/**/ + ) = 1 to 2 + + val (a, b// awd + ) = 1 to 2 + + val (a,/**/ b /**/ // awd + ) = 1 to 2 + + val (a, // ad + /**/b) = 1 to 2 + + val ( + a, b // fe + /**/)/**/ = 1 to 2 + + val ( + a, b, // awd + ) = 1 to 2 + + val (a, b, c, + d, f // awd + /* + */) = 1 to 2 + + val (a, b, c, + d, f // awd + , + ) = 1 to 2 +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 7369b76b295..6b06f0702be 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -1182,6 +1182,29 @@ public class FormatterTestGenerated extends AbstractFormatterTest { } } + @TestMetadata("idea/testData/formatter/trailingComma/destructionDeclaration") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DestructionDeclaration extends AbstractFormatterTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInDestructionDeclaration() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/formatter/trailingComma/destructionDeclaration"), Pattern.compile("^([^\\.]+)\\.after\\.kt.*$"), null, true); + } + + @TestMetadata("DestructionDeclarationsInLambda.after.kt") + public void testDestructionDeclarationsInLambda() throws Exception { + runTest("idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.kt"); + } + + @TestMetadata("MultiVariableDeclaration.after.kt") + public void testMultiVariableDeclaration() throws Exception { + runTest("idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.kt"); + } + } + @TestMetadata("idea/testData/formatter/trailingComma/indices") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -1739,6 +1762,29 @@ public class FormatterTestGenerated extends AbstractFormatterTest { } } + @TestMetadata("idea/testData/formatter/trailingComma/destructionDeclaration") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DestructionDeclaration extends AbstractFormatterTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestInverted, this, testDataFilePath); + } + + public void testAllFilesPresentInDestructionDeclaration() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/formatter/trailingComma/destructionDeclaration"), Pattern.compile("^([^\\.]+)\\.after\\.inv\\.kt.*$"), null, true); + } + + @TestMetadata("DestructionDeclarationsInLambda.after.inv.kt") + public void testDestructionDeclarationsInLambda() throws Exception { + runTest("idea/testData/formatter/trailingComma/destructionDeclaration/DestructionDeclarationsInLambda.after.inv.kt"); + } + + @TestMetadata("MultiVariableDeclaration.after.inv.kt") + public void testMultiVariableDeclaration() throws Exception { + runTest("idea/testData/formatter/trailingComma/destructionDeclaration/MultiVariableDeclaration.after.inv.kt"); + } + } + @TestMetadata("idea/testData/formatter/trailingComma/indices") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)