diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt index e9accef4a2d..bac14c6550f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt @@ -58,17 +58,7 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention initializer.valueParameters - is KtNamedFunction -> initializer.valueParameters - else -> emptyList() - } - if (valueParameters.isEmpty() || valueParameters.any { it.typeReference == null }) return null - } - } + if (!redundantTypeSpecification(element, initializer)) return null return when { initializer != null -> TextRange(element.startOffset, initializer.startOffset - 1) @@ -77,6 +67,19 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention null } } + + fun redundantTypeSpecification(element: KtCallableDeclaration, initializer: KtExpression?): Boolean { + if (initializer == null) return true + if (initializer !is KtLambdaExpression && initializer !is KtNamedFunction) return true + val functionType = element.typeReference?.typeElement as? KtFunctionType ?: return true + if (functionType.parameters.isEmpty()) return true + val valueParameters = when (initializer) { + is KtLambdaExpression -> initializer.valueParameters + is KtNamedFunction -> initializer.valueParameters + else -> emptyList() + } + return valueParameters.isNotEmpty() && valueParameters.none { it.typeReference == null } + } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemovePsiElementSimpleFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemovePsiElementSimpleFix.kt index accacabef09..3e61dc7d6f1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemovePsiElementSimpleFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemovePsiElementSimpleFix.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeIntention import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -60,6 +61,7 @@ open class RemovePsiElementSimpleFix(element: PsiElement, private val text: Stri object RemoveVariableFactory : KotlinSingleIntentionActionFactory() { public override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { val expression = diagnostic.psiElement.getNonStrictParentOfType() ?: return null + if (!RemoveExplicitTypeIntention.redundantTypeSpecification(expression, expression.initializer)) return null return object : RemovePsiElementSimpleFix(expression, "Remove variable '${expression.name}'") { override fun invoke(project: Project, editor: Editor?, file: KtFile) { val initializer = expression.initializer diff --git a/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize1.kt b/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize1.kt new file mode 100644 index 00000000000..319f3432e7c --- /dev/null +++ b/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize1.kt @@ -0,0 +1,5 @@ +// "Remove variable 'a'" "false" +// ACTION: Split property declaration +fun test() { + val a: (String) -> Unit = fun(s) { s + s } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt b/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt new file mode 100644 index 00000000000..eedf4a89b2b --- /dev/null +++ b/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt @@ -0,0 +1,4 @@ +// "Remove variable 'a'" "true" +fun test() { + val a: (String) -> Unit = fun(s: String) { s + s } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt.after b/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt.after new file mode 100644 index 00000000000..6a3f685d37f --- /dev/null +++ b/idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt.after @@ -0,0 +1,4 @@ +// "Remove variable 'a'" "true" +fun test() { + fun(s: String) { s + s } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer1.kt b/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer1.kt new file mode 100644 index 00000000000..90bae781e4f --- /dev/null +++ b/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer1.kt @@ -0,0 +1,5 @@ +// "Remove variable 'a'" "false" +// ACTION: Split property declaration +fun test() { + val a: (String) -> Unit = { s -> s + s } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt b/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt new file mode 100644 index 00000000000..8ff584a32f6 --- /dev/null +++ b/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt @@ -0,0 +1,4 @@ +// "Remove variable 'a'" "true" +fun test() { + val a: (String) -> Unit = { s: String -> s + s } +} \ No newline at end of file diff --git a/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt.after b/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt.after new file mode 100644 index 00000000000..51ded855a2c --- /dev/null +++ b/idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt.after @@ -0,0 +1,4 @@ +// "Remove variable 'a'" "true" +fun test() { + { s: String -> s + s } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index b5922bf1c0b..7fa33de22bd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -11910,6 +11910,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/variables"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("unusedVariableWithAnonymousFunctionInitialize1.kt") + public void testUnusedVariableWithAnonymousFunctionInitialize1() throws Exception { + runTest("idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize1.kt"); + } + + @TestMetadata("unusedVariableWithAnonymousFunctionInitialize2.kt") + public void testUnusedVariableWithAnonymousFunctionInitialize2() throws Exception { + runTest("idea/testData/quickfix/variables/unusedVariableWithAnonymousFunctionInitialize2.kt"); + } + @TestMetadata("unusedVariableWithConstantInitializer.kt") public void testUnusedVariableWithConstantInitializer() throws Exception { runTest("idea/testData/quickfix/variables/unusedVariableWithConstantInitializer.kt"); @@ -11925,6 +11935,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/variables/unusedVariableWithInitializerAndComment.kt"); } + @TestMetadata("unusedVariableWithLambdaInitializer1.kt") + public void testUnusedVariableWithLambdaInitializer1() throws Exception { + runTest("idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer1.kt"); + } + + @TestMetadata("unusedVariableWithLambdaInitializer2.kt") + public void testUnusedVariableWithLambdaInitializer2() throws Exception { + runTest("idea/testData/quickfix/variables/unusedVariableWithLambdaInitializer2.kt"); + } + @TestMetadata("unusedVariableWithNullInitializer.kt") public void testUnusedVariableWithNullInitializer() throws Exception { runTest("idea/testData/quickfix/variables/unusedVariableWithNullInitializer.kt");