UNUSED_VARIABLE is now reported only for last entry of destructuring declaration (if applicable) #KT-14221 Fixed
This commit is contained in:
@@ -572,7 +572,7 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
val element = instruction.variableDeclarationElement as? KtNamedDeclaration ?: return@traverse
|
val element = instruction.variableDeclarationElement as? KtNamedDeclaration ?: return@traverse
|
||||||
element.nameIdentifier ?: return@traverse
|
element.nameIdentifier ?: return@traverse
|
||||||
if (!VariableUseState.isUsed(variableUseState)) {
|
if (!VariableUseState.isUsed(variableUseState)) {
|
||||||
if (KtPsiUtil.isVariableNotParameterDeclaration(element)) {
|
if (KtPsiUtil.isRemovableVariableDeclaration(element)) {
|
||||||
report(Errors.UNUSED_VARIABLE.on(element, variableDescriptor), ctxt)
|
report(Errors.UNUSED_VARIABLE.on(element, variableDescriptor), ctxt)
|
||||||
}
|
}
|
||||||
else if (element is KtParameter) {
|
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)
|
report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on(element, variableDescriptor), ctxt)
|
||||||
}
|
}
|
||||||
else if (variableUseState === WRITTEN_AFTER_READ && element is KtVariableDeclaration) {
|
else if (variableUseState === WRITTEN_AFTER_READ && element is KtVariableDeclaration) {
|
||||||
|
|||||||
@@ -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 KtVariableDeclaration)) return false;
|
||||||
if (declaration instanceof KtProperty) return true;
|
if (declaration instanceof KtProperty) return true;
|
||||||
assert declaration instanceof KtDestructuringDeclarationEntry;
|
assert declaration instanceof KtDestructuringDeclarationEntry;
|
||||||
KtDestructuringDeclarationEntry multiDeclarationEntry = (KtDestructuringDeclarationEntry) declaration;
|
KtDestructuringDeclaration parentDeclaration = (KtDestructuringDeclaration) declaration.getParent();
|
||||||
return !(multiDeclarationEntry.getParent().getParent().getParent() instanceof KtForExpression);
|
List<KtDestructuringDeclarationEntry> entries = parentDeclaration.getEntries();
|
||||||
|
return entries.size() > 1 && entries.get(entries.size() - 1) == declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -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, <!UNUSED_VARIABLE!>z<!>) = D(1, 2, 3)
|
||||||
|
return y + x // z is not used
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
+2
-2
@@ -8,7 +8,7 @@ fun foo() {
|
|||||||
for (@Ann(1) i in 1..100) {}
|
for (@Ann(1) i in 1..100) {}
|
||||||
for (@Ann(2) i in 1..100) {}
|
for (@Ann(2) i in 1..100) {}
|
||||||
|
|
||||||
for (<!WRONG_ANNOTATION_TARGET!>@Ann(3)<!> (x, @Ann(4) y) in bar()) {}
|
for (<!WRONG_ANNOTATION_TARGET!>@Ann(3)<!> (x, @Ann(4) <!UNUSED_VARIABLE!>y<!>) in bar()) {}
|
||||||
|
|
||||||
for (@<!UNRESOLVED_REFERENCE!>Err<!>() (x,y) in bar()) {}
|
for (@<!UNRESOLVED_REFERENCE!>Err<!>() (x,<!UNUSED_VARIABLE!>y<!>) in bar()) {}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -22,11 +22,11 @@ fun f() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>val<!> (i,j) in Coll()) {
|
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>val<!> (i,<!UNUSED_VARIABLE!>j<!>) in Coll()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>var<!> (i,j) in Coll()) {
|
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>var<!> (i,<!UNUSED_VARIABLE!>j<!>) in Coll()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -4,5 +4,5 @@ class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun a(aa : A) {
|
fun a(aa : A) {
|
||||||
val (<!UNUSED_VARIABLE!>a<!>: String, <!UNUSED_VARIABLE!>b1<!>: String) = <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>aa<!>
|
val (a: String, <!UNUSED_VARIABLE!>b1<!>: String) = <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>aa<!>
|
||||||
}
|
}
|
||||||
+2
-2
@@ -5,10 +5,10 @@ class A {
|
|||||||
|
|
||||||
fun a(aa : A?, b : Any) {
|
fun a(aa : A?, b : Any) {
|
||||||
if (aa != null) {
|
if (aa != null) {
|
||||||
val (<!UNUSED_VARIABLE!>a1<!>, <!UNUSED_VARIABLE!>b1<!>) = <!DEBUG_INFO_SMARTCAST!>aa<!>;
|
val (a1, <!UNUSED_VARIABLE!>b1<!>) = <!DEBUG_INFO_SMARTCAST!>aa<!>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b is A) {
|
if (b is A) {
|
||||||
val (<!UNUSED_VARIABLE!>a1<!>, <!UNUSED_VARIABLE!>b1<!>) = <!DEBUG_INFO_SMARTCAST!>b<!>;
|
val (a1, <!UNUSED_VARIABLE!>b1<!>) = <!DEBUG_INFO_SMARTCAST!>b<!>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -4,11 +4,11 @@ class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun a() {
|
fun a() {
|
||||||
val (<!REDECLARATION, UNUSED_VARIABLE!>a<!>, <!NAME_SHADOWING, REDECLARATION, UNUSED_VARIABLE!>a<!>) = A()
|
val (<!REDECLARATION!>a<!>, <!NAME_SHADOWING, REDECLARATION, UNUSED_VARIABLE!>a<!>) = A()
|
||||||
val (<!UNUSED_VARIABLE!>x<!>, <!REDECLARATION, UNUSED_VARIABLE!>y<!>) = A();
|
val (x, <!REDECLARATION, UNUSED_VARIABLE!>y<!>) = A();
|
||||||
val <!REDECLARATION!>b<!> = 1
|
val <!REDECLARATION!>b<!> = 1
|
||||||
use(b)
|
use(b)
|
||||||
val (<!NAME_SHADOWING, REDECLARATION, UNUSED_VARIABLE!>b<!>, <!NAME_SHADOWING, REDECLARATION, UNUSED_VARIABLE!>y<!>) = A();
|
val (<!NAME_SHADOWING, REDECLARATION!>b<!>, <!NAME_SHADOWING, REDECLARATION, UNUSED_VARIABLE!>y<!>) = A();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
compiler/testData/diagnostics/tests/declarationChecks/destructuringDeclarations/DoubleDeclForLoop.kt
Vendored
+1
-1
@@ -8,7 +8,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((x, y) in C()) {
|
for ((x, <!UNUSED_VARIABLE!>y<!>) in C()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((x: Double, y: Int) in <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>C()<!>) {
|
for ((x: Double, <!UNUSED_VARIABLE!>y<!>: Int) in <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>C()<!>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -9,7 +9,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((x, y) in <!COMPONENT_FUNCTION_AMBIGUITY!>C()<!>) {
|
for ((x, <!UNUSED_VARIABLE!>y<!>) in <!COMPONENT_FUNCTION_AMBIGUITY!>C()<!>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -7,7 +7,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((x, y) in <!COMPONENT_FUNCTION_MISSING!>C()<!>) {
|
for ((x, <!UNUSED_VARIABLE!>y<!>) in <!COMPONENT_FUNCTION_MISSING!>C()<!>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ fun useDeclaredVariables() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun checkersShouldRun() {
|
fun checkersShouldRun() {
|
||||||
for ((@A a, <!UNDERSCORE_IS_RESERVED!>_<!>)<!SYNTAX!><!>) {
|
for ((@A a, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>)<!SYNTAX!><!>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((x, y) in C()) {
|
for ((x, <!UNUSED_VARIABLE!>y<!>) in C()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((x: Int, y: Double) in C()) {
|
for ((x: Int, <!UNUSED_VARIABLE!>y<!>: Double) in C()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((<!REDECLARATION!>x<!>, <!NAME_SHADOWING, REDECLARATION!>x<!>) in C()) {
|
for ((<!REDECLARATION!>x<!>, <!NAME_SHADOWING, REDECLARATION, UNUSED_VARIABLE!>x<!>) in C()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ fun useDeclaredVariables() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun checkersShouldRun() {
|
fun checkersShouldRun() {
|
||||||
val (@A <!UNUSED_VARIABLE!>a<!>, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>) = <!UNRESOLVED_REFERENCE!>unresolved<!>
|
val (@A a, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>) = <!UNRESOLVED_REFERENCE!>unresolved<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation class A
|
annotation class A
|
||||||
+1
-1
@@ -5,7 +5,7 @@ fun useDeclaredVariables() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun checkersShouldRun() {
|
fun checkersShouldRun() {
|
||||||
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (@A <!UNUSED_VARIABLE!>a<!>, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>)<!>
|
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (@A a, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>)<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation class A
|
annotation class A
|
||||||
+2
-2
@@ -7,7 +7,7 @@ class C {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test1(c: C) {
|
fun test1(c: C) {
|
||||||
val (<!UNUSED_VARIABLE!>a<!>, <!UNUSED_VARIABLE!>b<!>) = c
|
val (a, <!UNUSED_VARIABLE!>b<!>) = c
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2(c: C) {
|
fun test2(c: C) {
|
||||||
@@ -16,7 +16,7 @@ fun test2(c: C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test3(c: C) {
|
fun test3(c: C) {
|
||||||
var (<!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>a<!>, <!UNUSED_VARIABLE!>b<!>) = c
|
var (a, <!UNUSED_VARIABLE!>b<!>) = c
|
||||||
<!UNUSED_VALUE!>a =<!> 3
|
<!UNUSED_VALUE!>a =<!> 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ class A {
|
|||||||
fun foo(a: A, c: Int) {
|
fun foo(a: A, c: Int) {
|
||||||
val (<!NAME_SHADOWING!>a<!>, b) = a
|
val (<!NAME_SHADOWING!>a<!>, b) = a
|
||||||
val arr = Array(2) { A() }
|
val arr = Array(2) { A() }
|
||||||
for ((<!NAME_SHADOWING!>c<!>, d) in arr) {
|
for ((<!NAME_SHADOWING!>c<!>, <!UNUSED_VARIABLE!>d<!>) in arr) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -745,6 +745,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("UnusedParameters.kt")
|
||||||
public void testUnusedParameters() throws Exception {
|
public void testUnusedParameters() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/UnusedParameters.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/UnusedParameters.kt");
|
||||||
|
|||||||
Vendored
+2
-2
@@ -6,9 +6,9 @@ class A {
|
|||||||
fun arrayA(): Array<A> = null!!
|
fun arrayA(): Array<A> = null!!
|
||||||
|
|
||||||
fun foo(a: A, <warning>c</warning>: Int) {
|
fun foo(a: A, <warning>c</warning>: Int) {
|
||||||
val (<warning descr="[NAME_SHADOWING] Name shadowed: a"><warning descr="[UNUSED_VARIABLE] Variable 'a' is never used">a</warning></warning>, <warning>b</warning>) = a
|
val (<warning descr="[NAME_SHADOWING] Name shadowed: a">a</warning>, <warning>b</warning>) = a
|
||||||
val arr = arrayA()
|
val arr = arrayA()
|
||||||
for ((<warning descr="[NAME_SHADOWING] Name shadowed: c">c</warning>, d) in arr) {
|
for ((<warning descr="[NAME_SHADOWING] Name shadowed: c">c</warning>, <warning>d</warning>) in arr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
fun main() {
|
fun main() {
|
||||||
for ((i, j)<error>)</error> {}
|
for ((i, <warning>j</warning>)<error>)</error> {}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user