"Redundant spread operator" inspection: support array literal

So #KT-21727 Fixed
This commit is contained in:
Toshiaki Kameyama
2017-12-13 08:29:29 +03:00
committed by Mikhail Glukhikh
parent df4bf73033
commit 5680405531
6 changed files with 65 additions and 24 deletions
@@ -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<KtValueArgumentList>() ?: 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<KtValueArgumentList>()?.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)
}
}
@@ -0,0 +1,4 @@
annotation class Ann(vararg val value: String)
@Ann(<caret>*[])
class Test
@@ -0,0 +1,4 @@
annotation class Ann(vararg val value: String)
@Ann()
class Test
@@ -0,0 +1,4 @@
annotation class Ann(vararg val value: String)
@Ann(<caret>*["a", "b"])
class Test
@@ -0,0 +1,4 @@
annotation class Ann(vararg val value: String)
@Ann("a", "b")
class Test
@@ -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");