diff --git a/idea/resources/inspectionDescriptions/RemoveSetterParameterType.html b/idea/resources/inspectionDescriptions/RemoveSetterParameterType.html new file mode 100644 index 00000000000..3857715ca74 --- /dev/null +++ b/idea/resources/inspectionDescriptions/RemoveSetterParameterType.html @@ -0,0 +1,6 @@ + + +This inspection reports explicitly given parameter types in property setters. +Setter parameter type always matches property type, so it's not needed to be explicit. + + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index be92105d3ef..2d123eeb3f3 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -1627,6 +1627,14 @@ language="kotlin" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt index b1f739659c6..b581f5e2fd0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt @@ -16,26 +16,54 @@ package org.jetbrains.kotlin.idea.intentions +import com.intellij.codeInspection.ProblemHighlightType import com.intellij.openapi.editor.Editor +import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.getStartOffsetIn +import org.jetbrains.kotlin.psi.psiUtil.startOffset -class RemoveExplicitTypeIntention : SelfTargetingIntention(KtCallableDeclaration::class.java, "Remove explicit type specification") { - override fun isApplicableTo(element: KtCallableDeclaration, caretOffset: Int): Boolean { - if (element.containingFile is KtCodeFragment) return false - if (element.typeReference == null) return false +class RemoveSetterParameterTypeInspection( + val intention: RemoveExplicitTypeIntention = RemoveExplicitTypeIntention() +) : IntentionBasedInspection( + intention, + { intention.isSetterParameter(it) } +) { + override val problemHighlightType = ProblemHighlightType.LIKE_UNUSED_SYMBOL - val initializer = (element as? KtWithExpressionInitializer)?.initializer - if (initializer != null && initializer.textRange.containsOffset(caretOffset)) return false + override fun inspectionRange(element: KtCallableDeclaration) = (element as? KtParameter)?.typeReference?.let { + val start = it.getStartOffsetIn(element) + TextRange(start, start + it.endOffset - it.startOffset) + } +} - return when (element) { - is KtProperty -> initializer != null - is KtNamedFunction -> !element.hasBlockBody() && initializer != null - is KtParameter -> element.isLoopParameter - else -> false +class RemoveExplicitTypeIntention : SelfTargetingRangeIntention( + KtCallableDeclaration::class.java, + "Remove explicit type specification" +) { + + private val KtParameter.isSetterParameter: Boolean get() = (parent?.parent as? KtPropertyAccessor)?.isSetter ?: false + + fun isSetterParameter(element: KtCallableDeclaration) = + element is KtParameter && element.isSetterParameter + + override fun applicabilityRange(element: KtCallableDeclaration): TextRange? { + if (element.containingFile is KtCodeFragment) return null + if (element.typeReference == null) return null + + if (element is KtParameter && (element.isLoopParameter || element.isSetterParameter)) { + return element.textRange } + + val initializer = (element as? KtWithExpressionInitializer)?.initializer ?: return null + if (element !is KtProperty && (element !is KtNamedFunction || element.hasBlockBody())) return null + + return TextRange(element.startOffset, initializer.startOffset - 1) } override fun applyTo(element: KtCallableDeclaration, editor: Editor?) { - element.setTypeReference(null) + element.typeReference = null } } \ No newline at end of file diff --git a/idea/testData/inspections/removeSetterParameterType/inspectionData/expected.xml b/idea/testData/inspections/removeSetterParameterType/inspectionData/expected.xml new file mode 100644 index 00000000000..185d5689a49 --- /dev/null +++ b/idea/testData/inspections/removeSetterParameterType/inspectionData/expected.xml @@ -0,0 +1,18 @@ + + + test.kt + 4 + light_idea_test_case + + Redundant setter parameter type + Remove explicit type specification + + + test.kt + 10 + light_idea_test_case + + Redundant setter parameter type + Remove explicit type specification + + \ No newline at end of file diff --git a/idea/testData/inspections/removeSetterParameterType/inspectionData/inspections.test b/idea/testData/inspections/removeSetterParameterType/inspectionData/inspections.test new file mode 100644 index 00000000000..c9fadde5ed8 --- /dev/null +++ b/idea/testData/inspections/removeSetterParameterType/inspectionData/inspections.test @@ -0,0 +1 @@ +// INSPECTION_CLASS: org.jetbrains.kotlin.idea.intentions.RemoveSetterParameterTypeInspection diff --git a/idea/testData/inspections/removeSetterParameterType/test.kt b/idea/testData/inspections/removeSetterParameterType/test.kt new file mode 100644 index 00000000000..af030d02115 --- /dev/null +++ b/idea/testData/inspections/removeSetterParameterType/test.kt @@ -0,0 +1,21 @@ +// YES for first two, NO for last two expected + +var x: String = "" + set(param: String) { + field = "$param " + } + +class My { + var y: Int = 1 + set(param: Int) { + field = param - 1 + } + + var z: Double = 3.14 + private set + + var w: Boolean = true + set(param) { + field = !param + } +} \ No newline at end of file diff --git a/idea/testData/intentions/removeExplicitType/onSetterParameter.kt b/idea/testData/intentions/removeExplicitType/onSetterParameter.kt new file mode 100644 index 00000000000..144949b8fcd --- /dev/null +++ b/idea/testData/intentions/removeExplicitType/onSetterParameter.kt @@ -0,0 +1,4 @@ +var x: String = " " + set(param: String) { + field = "$param " + } diff --git a/idea/testData/intentions/removeExplicitType/onSetterParameter.kt.after b/idea/testData/intentions/removeExplicitType/onSetterParameter.kt.after new file mode 100644 index 00000000000..69c4f369040 --- /dev/null +++ b/idea/testData/intentions/removeExplicitType/onSetterParameter.kt.after @@ -0,0 +1,4 @@ +var x: String = " " + set(param) { + field = "$param " + } diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java index d96bf9f02bc..d13dda5117e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/InspectionTestGenerated.java @@ -220,6 +220,12 @@ public class InspectionTestGenerated extends AbstractInspectionTest { doTest(fileName); } + @TestMetadata("removeSetterParameterType/inspectionData/inspections.test") + public void testRemoveSetterParameterType_inspectionData_Inspections_test() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/removeSetterParameterType/inspectionData/inspections.test"); + doTest(fileName); + } + @TestMetadata("spelling/inspectionData/inspections.test") public void testSpelling_inspectionData_Inspections_test() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/spelling/inspectionData/inspections.test"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 0fe37fe6981..b4ceca375de 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -8184,6 +8184,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("onSetterParameter.kt") + public void testOnSetterParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/removeExplicitType/onSetterParameter.kt"); + doTest(fileName); + } + @TestMetadata("onType.kt") public void testOnType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/removeExplicitType/onType.kt");