From 56804055311419a7089c98d1ab09b534e24e9055 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 13 Dec 2017 08:29:29 +0300 Subject: [PATCH] "Redundant spread operator" inspection: support array literal So #KT-21727 Fixed --- ...RemoveRedundantSpreadOperatorInspection.kt | 61 +++++++++++-------- .../emptyLiteral.kt | 4 ++ .../emptyLiteral.kt.after | 4 ++ .../removeRedundantSpreadOperator/literal.kt | 4 ++ .../literal.kt.after | 4 ++ .../LocalInspectionTestGenerated.java | 12 ++++ 6 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt create mode 100644 idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt.after create mode 100644 idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt create mode 100644 idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RemoveRedundantSpreadOperatorInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RemoveRedundantSpreadOperatorInspection.kt index 4a338f093fe..fb100ab0f66 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RemoveRedundantSpreadOperatorInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RemoveRedundantSpreadOperatorInspection.kt @@ -34,22 +34,31 @@ class RemoveRedundantSpreadOperatorInspection : AbstractKotlinInspection() { return object : KtVisitorVoid() { override fun visitArgument(argument: KtValueArgument) { super.visitArgument(argument) + val spreadElement = argument.getSpreadElement() ?: return if (argument.isNamed()) return - val argumentExpression = argument.getArgumentExpression() as? KtCallExpression ?: return - if (argumentExpression.isArrayOfMethod()) { - val argumentOffset = argument.startOffset - val problemDescriptor = holder.manager.createProblemDescriptor( - argument, - TextRange(spreadElement.startOffset - argumentOffset, - argumentExpression.calleeExpression!!.endOffset - argumentOffset), - "Remove redundant spread operator", - ProblemHighlightType.LIKE_UNUSED_SYMBOL, - isOnTheFly, - RemoveRedundantSpreadOperatorQuickfix() - ) - holder.registerProblem(problemDescriptor) - } + val argumentExpression = argument.getArgumentExpression() ?: return + val argumentOffset = argument.startOffset + val startOffset = spreadElement.startOffset - argumentOffset + val endOffset = + when (argumentExpression) { + is KtCallExpression -> { + if (!argumentExpression.isArrayOfMethod()) return + argumentExpression.calleeExpression!!.endOffset - argumentOffset + } + is KtCollectionLiteralExpression -> startOffset + 1 + else -> return + } + + val problemDescriptor = holder.manager.createProblemDescriptor( + argument, + TextRange(startOffset, endOffset), + "Remove redundant spread operator", + ProblemHighlightType.LIKE_UNUSED_SYMBOL, + isOnTheFly, + RemoveRedundantSpreadOperatorQuickfix() + ) + holder.registerProblem(problemDescriptor) } } } @@ -61,16 +70,20 @@ class RemoveRedundantSpreadOperatorQuickfix : LocalQuickFix { override fun getFamilyName() = name override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - val arrayOfValueArgument = descriptor.psiElement as? KtValueArgument ?: return - val arrayOfArgumentExpression = arrayOfValueArgument.getArgumentExpression() as? KtCallExpression ?: return - val arrayOfArgumentList = arrayOfArgumentExpression.valueArgumentList ?: return + // Argument & expression under * + val spreadValueArgument = descriptor.psiElement as? KtValueArgument ?: return + val spreadArgumentExpression = spreadValueArgument.getArgumentExpression() ?: return + val outerArgumentList = spreadValueArgument.getStrictParentOfType() ?: return + // Arguments under arrayOf or [] + val innerArgumentExpressions = + when (spreadArgumentExpression) { + is KtCallExpression -> spreadArgumentExpression.valueArgumentList?.arguments?.map { it.getArgumentExpression() } + is KtCollectionLiteralExpression -> spreadArgumentExpression.getInnerExpressions() + else -> null + } ?: return + val factory = KtPsiFactory(project) - arrayOfValueArgument.getStrictParentOfType()?.let { outerArgumentList -> - arrayOfArgumentList.arguments.reversed().forEach { argument -> - val newValueArgument = factory.createArgument(argument.getArgumentExpression()) - outerArgumentList.addArgumentAfter(newValueArgument, arrayOfValueArgument) - } - outerArgumentList.removeArgument(arrayOfValueArgument) - } + innerArgumentExpressions.reversed().forEach { outerArgumentList.addArgumentAfter(factory.createArgument(it), spreadValueArgument) } + outerArgumentList.removeArgument(spreadValueArgument) } } \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt new file mode 100644 index 00000000000..2f78fec97d8 --- /dev/null +++ b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt @@ -0,0 +1,4 @@ +annotation class Ann(vararg val value: String) + +@Ann(*[]) +class Test \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt.after b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt.after new file mode 100644 index 00000000000..69950d8b5a2 --- /dev/null +++ b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt.after @@ -0,0 +1,4 @@ +annotation class Ann(vararg val value: String) + +@Ann() +class Test \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt new file mode 100644 index 00000000000..05a22b7b52b --- /dev/null +++ b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt @@ -0,0 +1,4 @@ +annotation class Ann(vararg val value: String) + +@Ann(*["a", "b"]) +class Test \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt.after b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt.after new file mode 100644 index 00000000000..9d0516bce0d --- /dev/null +++ b/idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt.after @@ -0,0 +1,4 @@ +annotation class Ann(vararg val value: String) + +@Ann("a", "b") +class Test \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 5cacd231590..fe3300a87c6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -2180,6 +2180,12 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { doTest(fileName); } + @TestMetadata("emptyLiteral.kt") + public void testEmptyLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/removeRedundantSpreadOperator/emptyLiteral.kt"); + doTest(fileName); + } + @TestMetadata("floatArrayOf.kt") public void testFloatArrayOf() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/removeRedundantSpreadOperator/floatArrayOf.kt"); @@ -2192,6 +2198,12 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { doTest(fileName); } + @TestMetadata("literal.kt") + public void testLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/removeRedundantSpreadOperator/literal.kt"); + doTest(fileName); + } + @TestMetadata("longArrayOf.kt") public void testLongArrayOf() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/removeRedundantSpreadOperator/longArrayOf.kt");