From b143a1c8f7c364e7216c20bb88c79e7ab93c38af Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 11 Dec 2018 16:40:53 +0300 Subject: [PATCH] For each parameter not used: handle char sequences correctly An enhancement for KT-27209 --- .../idea/inspections/ForEachParameterNotUsedInspection.kt | 7 +++++-- .../inspectionsLocal/forEachParameterNotUsed/repeat.kt | 2 +- .../forEachParameterNotUsed/repeat.kt.after | 2 +- .../inspectionsLocal/forEachParameterNotUsed/sequence.kt | 2 +- .../forEachParameterNotUsed/sequence.kt.after | 2 +- .../inspectionsLocal/forEachParameterNotUsed/string.kt | 6 ++++++ .../forEachParameterNotUsed/string.kt.after | 6 ++++++ .../idea/inspections/LocalInspectionTestGenerated.java | 5 +++++ 8 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt create mode 100644 idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ForEachParameterNotUsedInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ForEachParameterNotUsedInspection.kt index d42fa265bf6..dcda25e8ff1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ForEachParameterNotUsedInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ForEachParameterNotUsedInspection.kt @@ -34,6 +34,7 @@ class ForEachParameterNotUsedInspection : AbstractKotlinInspection() { private const val FOREACH_NAME = "forEach" private val COLLECTIONS_FOREACH_FQNAME = FqName("kotlin.collections.$FOREACH_NAME") private val SEQUENCES_FOREACH_FQNAME = FqName("kotlin.sequences.$FOREACH_NAME") + private val TEXT_FOREACH_FQNAME = FqName("kotlin.text.$FOREACH_NAME") } override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { @@ -44,7 +45,7 @@ class ForEachParameterNotUsedInspection : AbstractKotlinInspection() { if (lambda == null || lambda.functionLiteral.arrow != null) return val context = it.analyze() when (it.getResolvedCall(context)?.resultingDescriptor?.fqNameOrNull()) { - COLLECTIONS_FOREACH_FQNAME, SEQUENCES_FOREACH_FQNAME -> { + COLLECTIONS_FOREACH_FQNAME, SEQUENCES_FOREACH_FQNAME, TEXT_FOREACH_FQNAME -> { val descriptor = context[BindingContext.FUNCTION, lambda.functionLiteral] ?: return val iterableParameter = descriptor.valueParameters.singleOrNull() ?: return @@ -83,7 +84,7 @@ class ForEachParameterNotUsedInspection : AbstractKotlinInspection() { } private class ReplaceWithRepeatFix : LocalQuickFix { - override fun getFamilyName() = "Replace with 'repeat(size)'" + override fun getFamilyName() = "Replace with 'repeat()'" override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val callExpression = descriptor.psiElement.parent as? KtCallExpression ?: return @@ -92,8 +93,10 @@ class ForEachParameterNotUsedInspection : AbstractKotlinInspection() { val receiverClass = receiverExpression.resolveToCall()?.resultingDescriptor?.returnType?.constructor?.declarationDescriptor as? ClassDescriptor val collection = callExpression.builtIns.collection + val charSequence = callExpression.builtIns.charSequence val sizeText = when { receiverClass != null && DescriptorUtils.isSubclass(receiverClass, collection) -> "size" + receiverClass != null && DescriptorUtils.isSubclass(receiverClass, charSequence) -> "length" else -> "count()" } val lambdaExpression = callExpression.lambdaArguments.singleOrNull()?.getArgumentExpression() ?: return diff --git a/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt b/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt index 12d9cd1d434..1832b399bd1 100644 --- a/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt +++ b/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt @@ -1,5 +1,5 @@ // WITH_RUNTIME -// FIX: Replace with 'repeat(size)' +// FIX: Replace with 'repeat()' fun test(list: List) { list.forEach {} diff --git a/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt.after b/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt.after index c46460b8cc2..c62be2b1606 100644 --- a/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt.after +++ b/idea/testData/inspectionsLocal/forEachParameterNotUsed/repeat.kt.after @@ -1,5 +1,5 @@ // WITH_RUNTIME -// FIX: Replace with 'repeat(size)' +// FIX: Replace with 'repeat()' fun test(list: List) { repeat(list.size) {} diff --git a/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt b/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt index 135dda859a5..d8fe7ab2cc6 100644 --- a/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt +++ b/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt @@ -1,5 +1,5 @@ // WITH_RUNTIME -// FIX: Replace with 'repeat(size)' +// FIX: Replace with 'repeat()' fun test(sequence: Sequence) { sequence.forEach {} diff --git a/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt.after b/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt.after index 87f0580075f..1f2a89f7992 100644 --- a/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt.after +++ b/idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt.after @@ -1,5 +1,5 @@ // WITH_RUNTIME -// FIX: Replace with 'repeat(size)' +// FIX: Replace with 'repeat()' fun test(sequence: Sequence) { repeat(sequence.count()) {} diff --git a/idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt b/idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt new file mode 100644 index 00000000000..08c22e27720 --- /dev/null +++ b/idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +// FIX: Replace with 'repeat()' + +fun test(s: String) { + s.forEach {} +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt.after b/idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt.after new file mode 100644 index 00000000000..6245b50a480 --- /dev/null +++ b/idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +// FIX: Replace with 'repeat()' + +fun test(s: String) { + repeat(s.length) {} +} \ 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 62ab1dd17a4..00f94bff841 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -2557,6 +2557,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { public void testSequence() throws Exception { runTest("idea/testData/inspectionsLocal/forEachParameterNotUsed/sequence.kt"); } + + @TestMetadata("string.kt") + public void testString() throws Exception { + runTest("idea/testData/inspectionsLocal/forEachParameterNotUsed/string.kt"); + } } @TestMetadata("idea/testData/inspectionsLocal/ImplicitNullableNothingType")