From 8d48b0d2a0b333cc43c2c127dbf1466c171bfa6b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 7 Oct 2016 20:38:00 +0300 Subject: [PATCH] UNUSED_VARIABLE is now reported only for last entry of destructuring declaration (if applicable) #KT-14221 Fixed --- .../cfg/ControlFlowInformationProvider.kt | 4 ++-- .../org/jetbrains/kotlin/psi/KtPsiUtil.java | 7 ++++--- .../diagnostics/tests/UnusedInDestructuring.kt | 9 +++++++++ .../tests/UnusedInDestructuring.txt | 18 ++++++++++++++++++ .../forParameterAnnotationResolve.kt | 4 ++-- .../controlStructures/valVarLoopParameter.kt | 4 ++-- .../ComponentFunctionReturnTypeMismatch.kt | 2 +- .../DataFlowInfoInMultiDecl.kt | 4 ++-- .../RedeclarationsInMultiDecl.kt | 6 +++--- .../DoubleDeclForLoop.kt | 2 +- .../FolLoopTypeComponentTypeMismatch.kt | 2 +- .../ForLoopComponentFunctionAmbiguity.kt | 2 +- .../ForLoopComponentFunctionMissing.kt | 2 +- .../ForLoopMissingLoopParameter.kt | 2 +- .../ForLoopWithExtensions.kt | 2 +- .../ForWithExplicitTypes.kt | 2 +- .../RedeclarationInForLoop.kt | 2 +- ...structuringDeclarationAssignedUnresolved.kt | 2 +- ...structuringDeclarationMissingInitializer.kt | 2 +- .../kt2643MultiDeclInControlFlow.kt | 4 ++-- .../ShadowMultiDeclarationWithFunParameter.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ idea/testData/checker/Shadowing.kt | 4 ++-- .../DescructuringDeclarationInForLoop.kt | 2 +- 24 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/UnusedInDestructuring.kt create mode 100644 compiler/testData/diagnostics/tests/UnusedInDestructuring.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index ebb5ca63a01..dab4ea65596 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -572,7 +572,7 @@ class ControlFlowInformationProvider private constructor( val element = instruction.variableDeclarationElement as? KtNamedDeclaration ?: return@traverse element.nameIdentifier ?: return@traverse if (!VariableUseState.isUsed(variableUseState)) { - if (KtPsiUtil.isVariableNotParameterDeclaration(element)) { + if (KtPsiUtil.isRemovableVariableDeclaration(element)) { report(Errors.UNUSED_VARIABLE.on(element, variableDescriptor), ctxt) } else if (element is KtParameter) { @@ -607,7 +607,7 @@ class ControlFlowInformationProvider private constructor( } } } - else if (variableUseState === ONLY_WRITTEN_NEVER_READ && KtPsiUtil.isVariableNotParameterDeclaration(element)) { + else if (variableUseState === ONLY_WRITTEN_NEVER_READ && KtPsiUtil.isRemovableVariableDeclaration(element)) { report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on(element, variableDescriptor), ctxt) } else if (variableUseState === WRITTEN_AFTER_READ && element is KtVariableDeclaration) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java index 9e0cf357981..2be7c672125 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiUtil.java @@ -276,12 +276,13 @@ public class KtPsiUtil { } } - public static boolean isVariableNotParameterDeclaration(@NotNull KtDeclaration declaration) { + public static boolean isRemovableVariableDeclaration(@NotNull KtDeclaration declaration) { if (!(declaration instanceof KtVariableDeclaration)) return false; if (declaration instanceof KtProperty) return true; assert declaration instanceof KtDestructuringDeclarationEntry; - KtDestructuringDeclarationEntry multiDeclarationEntry = (KtDestructuringDeclarationEntry) declaration; - return !(multiDeclarationEntry.getParent().getParent().getParent() instanceof KtForExpression); + KtDestructuringDeclaration parentDeclaration = (KtDestructuringDeclaration) declaration.getParent(); + List entries = parentDeclaration.getEntries(); + return entries.size() > 1 && entries.get(entries.size() - 1) == declaration; } @Nullable diff --git a/compiler/testData/diagnostics/tests/UnusedInDestructuring.kt b/compiler/testData/diagnostics/tests/UnusedInDestructuring.kt new file mode 100644 index 00000000000..64e72cd5990 --- /dev/null +++ b/compiler/testData/diagnostics/tests/UnusedInDestructuring.kt @@ -0,0 +1,9 @@ +data class D(val x: Int, val y: Int, val z: Int) +fun foo(): Int { + val (x, y, z) = D(1, 2, 3) + return y + z // x is not used, but we cannot do anything with it +} +fun bar(): Int { + val (x, y, z) = D(1, 2, 3) + return y + x // z is not used +} diff --git a/compiler/testData/diagnostics/tests/UnusedInDestructuring.txt b/compiler/testData/diagnostics/tests/UnusedInDestructuring.txt new file mode 100644 index 00000000000..5ab2e0bac9e --- /dev/null +++ b/compiler/testData/diagnostics/tests/UnusedInDestructuring.txt @@ -0,0 +1,18 @@ +package + +public fun bar(): kotlin.Int +public fun foo(): kotlin.Int + +public final data class D { + public constructor D(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int, /*2*/ z: kotlin.Int) + public final val x: kotlin.Int + public final val y: kotlin.Int + public final val z: kotlin.Int + public final operator /*synthesized*/ fun component1(): kotlin.Int + public final operator /*synthesized*/ fun component2(): kotlin.Int + public final operator /*synthesized*/ fun component3(): kotlin.Int + public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.Int = ..., /*2*/ z: kotlin.Int = ...): D + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/annotations/forParameterAnnotationResolve.kt b/compiler/testData/diagnostics/tests/annotations/forParameterAnnotationResolve.kt index 8878679890e..f5ebfbaf57b 100644 --- a/compiler/testData/diagnostics/tests/annotations/forParameterAnnotationResolve.kt +++ b/compiler/testData/diagnostics/tests/annotations/forParameterAnnotationResolve.kt @@ -8,7 +8,7 @@ fun foo() { for (@Ann(1) i in 1..100) {} for (@Ann(2) i in 1..100) {} - for (@Ann(3) (x, @Ann(4) y) in bar()) {} + for (@Ann(3) (x, @Ann(4) y) in bar()) {} - for (@Err() (x,y) in bar()) {} + for (@Err() (x,y) in bar()) {} } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlStructures/valVarLoopParameter.kt b/compiler/testData/diagnostics/tests/controlStructures/valVarLoopParameter.kt index a1956f7f86d..1a0ab7cdfd2 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/valVarLoopParameter.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/valVarLoopParameter.kt @@ -22,11 +22,11 @@ fun f() { } - for (val (i,j) in Coll()) { + for (val (i,j) in Coll()) { } - for (var (i,j) in Coll()) { + for (var (i,j) in Coll()) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt b/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt index 86b8432b678..ef48870d7e2 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt @@ -4,5 +4,5 @@ class A { } fun a(aa : A) { - val (a: String, b1: String) = aa + val (a: String, b1: String) = aa } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt b/compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt index 3e046284e52..d14057b2485 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt @@ -5,10 +5,10 @@ class A { fun a(aa : A?, b : Any) { if (aa != null) { - val (a1, b1) = aa; + val (a1, b1) = aa; } if (b is A) { - val (a1, b1) = b; + val (a1, b1) = b; } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/RedeclarationsInMultiDecl.kt b/compiler/testData/diagnostics/tests/declarationChecks/RedeclarationsInMultiDecl.kt index a23f77ad672..6344439d5ca 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/RedeclarationsInMultiDecl.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/RedeclarationsInMultiDecl.kt @@ -4,11 +4,11 @@ class A { } fun a() { - val (a, a) = A() - val (x, y) = A(); + val (a, a) = A() + val (x, y) = A(); val b = 1 use(b) - val (b, y) = A(); + val (b, y) = A(); } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/DoubleDeclForLoop.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/DoubleDeclForLoop.kt index 065d6ac7c48..88661f059c8 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/DoubleDeclForLoop.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/DoubleDeclForLoop.kt @@ -8,7 +8,7 @@ class C { } fun test() { - for ((x, y) in C()) { + for ((x, y) in C()) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/FolLoopTypeComponentTypeMismatch.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/FolLoopTypeComponentTypeMismatch.kt index de3155d1fa6..66a9a88a311 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/FolLoopTypeComponentTypeMismatch.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/FolLoopTypeComponentTypeMismatch.kt @@ -8,7 +8,7 @@ class C { } fun test() { - for ((x: Double, y: Int) in C()) { + for ((x: Double, y: Int) in C()) { } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionAmbiguity.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionAmbiguity.kt index 6bc083401c6..27cd5b37bb9 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionAmbiguity.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionAmbiguity.kt @@ -9,7 +9,7 @@ class C { } fun test() { - for ((x, y) in C()) { + for ((x, y) in C()) { } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionMissing.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionMissing.kt index 95924e4c839..275ae1ecd45 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionMissing.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopComponentFunctionMissing.kt @@ -7,7 +7,7 @@ class C { } fun test() { - for ((x, y) in C()) { + for ((x, y) in C()) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.kt index 5246cb5cccb..b754f602776 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopMissingLoopParameter.kt @@ -6,7 +6,7 @@ fun useDeclaredVariables() { } fun checkersShouldRun() { - for ((@A a, _)) { + for ((@A a, _)) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopWithExtensions.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopWithExtensions.kt index 30fca7424e3..493e39d136b 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopWithExtensions.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForLoopWithExtensions.kt @@ -8,7 +8,7 @@ class C { } fun test() { - for ((x, y) in C()) { + for ((x, y) in C()) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForWithExplicitTypes.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForWithExplicitTypes.kt index 3e97d2fc5ff..300010781c0 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForWithExplicitTypes.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/ForWithExplicitTypes.kt @@ -8,7 +8,7 @@ class C { } fun test() { - for ((x: Int, y: Double) in C()) { + for ((x: Int, y: Double) in C()) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/RedeclarationInForLoop.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/RedeclarationInForLoop.kt index 2d273316d4a..dc4f8bc1e86 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/RedeclarationInForLoop.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/RedeclarationInForLoop.kt @@ -8,7 +8,7 @@ class C { } fun test() { - for ((x, x) in C()) { + for ((x, x) in C()) { } } diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.kt index c3b3499591f..e1300ee1105 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationAssignedUnresolved.kt @@ -5,7 +5,7 @@ fun useDeclaredVariables() { } fun checkersShouldRun() { - val (@A a, _) = unresolved + val (@A a, _) = unresolved } annotation class A \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.kt b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.kt index cd0a8756aee..314cd299ee8 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/destructuringDeclarationMissingInitializer.kt @@ -5,7 +5,7 @@ fun useDeclaredVariables() { } fun checkersShouldRun() { - val (@A a, _) + val (@A a, _) } annotation class A \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt b/compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt index 56ffc1ccf38..2fe35daada8 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt @@ -7,7 +7,7 @@ class C { } fun test1(c: C) { - val (a, b) = c + val (a, b) = c } fun test2(c: C) { @@ -16,7 +16,7 @@ fun test2(c: C) { } fun test3(c: C) { - var (a, b) = c + var (a, b) = c a = 3 } diff --git a/compiler/testData/diagnostics/tests/shadowing/ShadowMultiDeclarationWithFunParameter.kt b/compiler/testData/diagnostics/tests/shadowing/ShadowMultiDeclarationWithFunParameter.kt index d0243dbe5e1..d78e76d48a1 100644 --- a/compiler/testData/diagnostics/tests/shadowing/ShadowMultiDeclarationWithFunParameter.kt +++ b/compiler/testData/diagnostics/tests/shadowing/ShadowMultiDeclarationWithFunParameter.kt @@ -6,7 +6,7 @@ class A { fun foo(a: A, c: Int) { val (a, b) = a val arr = Array(2) { A() } - for ((c, d) in arr) { + for ((c, d) in arr) { } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9147709ad8d..43ba6bfca48 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -745,6 +745,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("UnusedInDestructuring.kt") + public void testUnusedInDestructuring() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/UnusedInDestructuring.kt"); + doTest(fileName); + } + @TestMetadata("UnusedParameters.kt") public void testUnusedParameters() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/UnusedParameters.kt"); diff --git a/idea/testData/checker/Shadowing.kt b/idea/testData/checker/Shadowing.kt index 800941d3716..f3e157134ce 100644 --- a/idea/testData/checker/Shadowing.kt +++ b/idea/testData/checker/Shadowing.kt @@ -6,9 +6,9 @@ class A { fun arrayA(): Array = null!! fun foo(a: A, c: Int) { - val (a, b) = a + val (a, b) = a val arr = arrayA() - for ((c, d) in arr) { + for ((c, d) in arr) { } } diff --git a/idea/testData/checker/regression/DescructuringDeclarationInForLoop.kt b/idea/testData/checker/regression/DescructuringDeclarationInForLoop.kt index f54ff5e2887..8e00f614888 100644 --- a/idea/testData/checker/regression/DescructuringDeclarationInForLoop.kt +++ b/idea/testData/checker/regression/DescructuringDeclarationInForLoop.kt @@ -1,3 +1,3 @@ fun main() { - for ((i, j)) {} + for ((i, j)) {} } \ No newline at end of file