For each parameter unused: add quick-fix "introduce anonymous parameter"
Related to KT-22068
This commit is contained in:
+20
-2
@@ -5,13 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl.WithDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.intentions.SpecifyExplicitLambdaSignatureIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.getThisLabelName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -41,11 +45,11 @@ class ForEachParameterNotUsedInspection : AbstractKotlinInspection() {
|
||||
if (iterableParameter !is WithDestructuringDeclaration &&
|
||||
lambda.bodyExpression?.usesDescriptor(iterableParameter) != true
|
||||
) {
|
||||
|
||||
holder.registerProblem(
|
||||
calleeExpression,
|
||||
"Loop parameter '${iterableParameter.getThisLabelName()}' is unused",
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
IntroduceAnonymousParameterFix()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -53,6 +57,20 @@ class ForEachParameterNotUsedInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
}
|
||||
|
||||
private class IntroduceAnonymousParameterFix : LocalQuickFix {
|
||||
override fun getFamilyName() = "Introduce anonymous parameter"
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val callExpression = descriptor.psiElement.parent as? KtCallExpression ?: return
|
||||
val literal = callExpression.lambdaArguments.singleOrNull()?.getLambdaExpression()?.functionLiteral ?: return
|
||||
val psiFactory = KtPsiFactory(project)
|
||||
val newParameterList = psiFactory.createLambdaParameterList("_")
|
||||
with (SpecifyExplicitLambdaSignatureIntention) {
|
||||
literal.setParameterListIfAny(psiFactory, newParameterList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtBlockExpression.usesDescriptor(descriptor: VariableDescriptor): Boolean {
|
||||
var used = false
|
||||
acceptChildren(object : KtVisitorVoid() {
|
||||
|
||||
+23
-14
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.KtParameterList
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
@@ -59,24 +61,31 @@ class SpecifyExplicitLambdaSignatureIntention : SelfTargetingOffsetIndependentIn
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun KtFunctionLiteral.setParameterListIfAny(psiFactory: KtPsiFactory, newParameterList: KtParameterList?) {
|
||||
val oldParameterList = valueParameterList
|
||||
if (oldParameterList != null && newParameterList != null) {
|
||||
oldParameterList.replace(newParameterList)
|
||||
} else {
|
||||
val openBraceElement = lBrace
|
||||
val nextSibling = openBraceElement.nextSibling
|
||||
val addNewline = nextSibling is PsiWhiteSpace && nextSibling.text?.contains("\n") ?: false
|
||||
val (whitespace, arrow) = psiFactory.createWhitespaceAndArrow()
|
||||
addRangeAfter(whitespace, arrow, openBraceElement)
|
||||
if (newParameterList != null) {
|
||||
addAfter(newParameterList, openBraceElement)
|
||||
}
|
||||
if (addNewline) {
|
||||
addAfter(psiFactory.createNewLine(), openBraceElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun applyWithParameters(element: KtLambdaExpression, parameterString: String) {
|
||||
val psiFactory = KtPsiFactory(element)
|
||||
val functionLiteral = element.functionLiteral
|
||||
val newParameterList = psiFactory.createLambdaParameterListIfAny(parameterString)
|
||||
val oldParameterList = functionLiteral.valueParameterList
|
||||
if (oldParameterList != null && newParameterList != null) {
|
||||
oldParameterList.replace(newParameterList)
|
||||
} else {
|
||||
val openBraceElement = functionLiteral.lBrace
|
||||
val nextSibling = openBraceElement.nextSibling
|
||||
val addNewline = nextSibling is PsiWhiteSpace && nextSibling.text?.contains("\n") ?: false
|
||||
val (whitespace, arrow) = psiFactory.createWhitespaceAndArrow()
|
||||
functionLiteral.addRangeAfter(whitespace, arrow, openBraceElement)
|
||||
newParameterList?.let { functionLiteral.addAfter(it, openBraceElement) }
|
||||
if (addNewline) {
|
||||
functionLiteral.addAfter(psiFactory.createNewLine(), openBraceElement)
|
||||
}
|
||||
}
|
||||
functionLiteral.setParameterListIfAny(psiFactory, newParameterList)
|
||||
ShortenReferences.DEFAULT.process(element.valueParameters)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test(list: List<String>) {
|
||||
list.for<caret>Each {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test(list: List<String>) {
|
||||
list.forEach { _ -> }
|
||||
}
|
||||
+5
@@ -2177,6 +2177,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
public void testInvoke() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/forEachParameterNotUsed/invoke.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("normal.kt")
|
||||
public void testNormal() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/forEachParameterNotUsed/normal.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/inspectionsLocal/ImplicitNullableNothingType")
|
||||
|
||||
Reference in New Issue
Block a user