KT-2643 Support multi-declarations in Data-Flow analysis
#KT-2643 fixed
This commit is contained in:
@@ -78,7 +78,7 @@ public interface JetControlFlowBuilder {
|
|||||||
void write(@NotNull JetElement assignment, @NotNull JetElement lValue);
|
void write(@NotNull JetElement assignment, @NotNull JetElement lValue);
|
||||||
|
|
||||||
void declare(@NotNull JetParameter parameter);
|
void declare(@NotNull JetParameter parameter);
|
||||||
void declare(@NotNull JetProperty property);
|
void declare(@NotNull JetVariableDeclaration property);
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
void unsupported(JetElement element);
|
void unsupported(JetElement element);
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void declare(@NotNull JetProperty property) {
|
public void declare(@NotNull JetVariableDeclaration property) {
|
||||||
assert builder != null;
|
assert builder != null;
|
||||||
builder.declare(property);
|
builder.declare(property);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -742,6 +742,19 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMultiDeclaration(JetMultiDeclaration declaration) {
|
||||||
|
JetExpression initializer = declaration.getInitializer();
|
||||||
|
if (initializer != null) {
|
||||||
|
builder.read(initializer);
|
||||||
|
}
|
||||||
|
List<JetMultiDeclarationEntry> entries = declaration.getEntries();
|
||||||
|
for (JetMultiDeclarationEntry entry : entries) {
|
||||||
|
builder.declare(entry);
|
||||||
|
builder.write(entry, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitPropertyAccessor(JetPropertyAccessor accessor) {
|
public void visitPropertyAccessor(JetPropertyAccessor accessor) {
|
||||||
processLocalDeclaration(accessor);
|
processLocalDeclaration(accessor);
|
||||||
|
|||||||
@@ -451,8 +451,8 @@ public class JetFlowInformationProvider {
|
|||||||
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
|
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
|
||||||
if (nameIdentifier == null) return;
|
if (nameIdentifier == null) return;
|
||||||
if (!VariableUseState.isUsed(variableUseState)) {
|
if (!VariableUseState.isUsed(variableUseState)) {
|
||||||
if (element instanceof JetProperty) {
|
if (element instanceof JetVariableDeclaration) {
|
||||||
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor));
|
trace.report(Errors.UNUSED_VARIABLE.on((JetVariableDeclaration) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
else if (element instanceof JetParameter) {
|
else if (element instanceof JetParameter) {
|
||||||
PsiElement psiElement = element.getParent().getParent();
|
PsiElement psiElement = element.getParent().getParent();
|
||||||
@@ -468,13 +468,18 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (variableUseState == ONLY_WRITTEN_NEVER_READ && element instanceof JetProperty) {
|
else if (variableUseState == ONLY_WRITTEN_NEVER_READ && element instanceof JetVariableDeclaration) {
|
||||||
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
|
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetVariableDeclaration) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
else if (variableUseState == LAST_WRITTEN && element instanceof JetProperty) {
|
else if (variableUseState == LAST_WRITTEN && element instanceof JetVariableDeclaration) {
|
||||||
JetExpression initializer = ((JetProperty) element).getInitializer();
|
if (element instanceof JetProperty) {
|
||||||
if (initializer != null) {
|
JetExpression initializer = ((JetProperty) element).getInitializer();
|
||||||
trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor));
|
if (initializer != null) {
|
||||||
|
trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (element instanceof JetMultiDeclarationEntry) {
|
||||||
|
trace.report(VARIABLE_WITH_REDUNDANT_INITIALIZER.on(element, variableDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -229,7 +229,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void declare(@NotNull JetProperty property) {
|
public void declare(@NotNull JetVariableDeclaration property) {
|
||||||
add(new VariableDeclarationInstruction(property));
|
add(new VariableDeclarationInstruction(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||||
import org.jetbrains.jet.lang.psi.JetParameter;
|
import org.jetbrains.jet.lang.psi.JetParameter;
|
||||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetVariableDeclaration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
@@ -29,7 +30,7 @@ public class VariableDeclarationInstruction extends InstructionWithNext {
|
|||||||
super(element);
|
super(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected VariableDeclarationInstruction(@NotNull JetProperty element) {
|
protected VariableDeclarationInstruction(@NotNull JetVariableDeclaration element) {
|
||||||
super(element);
|
super(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public interface Errors {
|
|||||||
|
|
||||||
DiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR);
|
||||||
UnusedElementDiagnosticFactory<JetProperty, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
UnusedElementDiagnosticFactory<JetVariableDeclaration, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
||||||
UnusedElementDiagnosticFactory<JetParameter, VariableDescriptor> UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
UnusedElementDiagnosticFactory<JetParameter, VariableDescriptor> UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
||||||
UnusedElementDiagnosticFactory<JetNamedDeclaration, DeclarationDescriptor> ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
UnusedElementDiagnosticFactory<JetNamedDeclaration, DeclarationDescriptor> ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
||||||
DiagnosticFactory1<JetExpression, DeclarationDescriptor> VARIABLE_WITH_REDUNDANT_INITIALIZER = DiagnosticFactory1.create(WARNING);
|
DiagnosticFactory1<JetExpression, DeclarationDescriptor> VARIABLE_WITH_REDUNDANT_INITIALIZER = DiagnosticFactory1.create(WARNING);
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class BindingContextUtils {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable JetElement element, boolean onlyReference) {
|
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable JetElement element, boolean onlyReference) {
|
||||||
DeclarationDescriptor descriptor = null;
|
DeclarationDescriptor descriptor = null;
|
||||||
if (!onlyReference && (element instanceof JetProperty || element instanceof JetParameter)) {
|
if (!onlyReference && (element instanceof JetVariableDeclaration || element instanceof JetParameter)) {
|
||||||
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||||
}
|
}
|
||||||
else if (element instanceof JetSimpleNameExpression) {
|
else if (element instanceof JetSimpleNameExpression) {
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
== C ==
|
||||||
|
class C {
|
||||||
|
fun component1() = 1
|
||||||
|
fun component2() = 2
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[<END>] PREV:[]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[<START>]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== test ==
|
||||||
|
fun test(c: C) {
|
||||||
|
val (a, b) = c
|
||||||
|
val d = 1
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[v(c: C)] PREV:[]
|
||||||
|
v(c: C) NEXT:[w(c)] PREV:[<START>]
|
||||||
|
w(c) NEXT:[r(c)] PREV:[v(c: C)]
|
||||||
|
r(c) NEXT:[v(a)] PREV:[w(c)]
|
||||||
|
v(a) NEXT:[w(a)] PREV:[r(c)]
|
||||||
|
w(a) NEXT:[v(b)] PREV:[v(a)]
|
||||||
|
v(b) NEXT:[w(b)] PREV:[w(a)]
|
||||||
|
w(b) NEXT:[v(val d = 1)] PREV:[v(b)]
|
||||||
|
v(val d = 1) NEXT:[r(1)] PREV:[w(b)]
|
||||||
|
r(1) NEXT:[w(d)] PREV:[v(val d = 1)]
|
||||||
|
w(d) NEXT:[<END>] PREV:[r(1)]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[w(d)]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package n
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun component1() = 1
|
||||||
|
fun component2() = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(c: C) {
|
||||||
|
val (a, b) = c
|
||||||
|
val d = 1
|
||||||
|
}
|
||||||
+2
-2
@@ -3,6 +3,6 @@ class A {
|
|||||||
fun component2() : Int = 2
|
fun component2() : Int = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fun a(<!UNUSED_PARAMETER!>aa<!> : A) {
|
fun a(aa : A) {
|
||||||
val (a: String, b1: String) = <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>aa<!>
|
val (<!UNUSED_VARIABLE!>a<!>: String, <!UNUSED_VARIABLE!>b1<!>: String) = <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>aa<!>
|
||||||
}
|
}
|
||||||
@@ -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 (a1, b1) = aa;
|
val (<!UNUSED_VARIABLE!>a1<!>, <!UNUSED_VARIABLE!>b1<!>) = aa;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b is A) {
|
if (b is A) {
|
||||||
val (a1, b1) = b;
|
val (<!UNUSED_VARIABLE!>a1<!>, <!UNUSED_VARIABLE!>b1<!>) = b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ class MyClass2 {}
|
|||||||
<!CONFLICTING_OVERLOADS!>fun MyClass2.component1()<!> = 1.2
|
<!CONFLICTING_OVERLOADS!>fun MyClass2.component1()<!> = 1.2
|
||||||
<!CONFLICTING_OVERLOADS!>fun MyClass2.component1()<!> = 1.3
|
<!CONFLICTING_OVERLOADS!>fun MyClass2.component1()<!> = 1.3
|
||||||
|
|
||||||
fun test(<!UNUSED_PARAMETER!>mc1<!>: MyClass, <!UNUSED_PARAMETER!>mc2<!>: MyClass2) {
|
fun test(mc1: MyClass, mc2: MyClass2) {
|
||||||
val (a, b) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>mc1<!>
|
val (a, b) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>mc1<!>
|
||||||
val (c) = <!COMPONENT_FUNCTION_AMBIGUITY!>mc2<!>
|
val (c) = <!COMPONENT_FUNCTION_AMBIGUITY!>mc2<!>
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun a() {
|
fun a() {
|
||||||
val (<!REDECLARATION!>a<!>, <!REDECLARATION!>a<!>) = A()
|
val (<!REDECLARATION, UNUSED_VARIABLE!>a<!>, <!REDECLARATION, UNUSED_VARIABLE!>a<!>) = A()
|
||||||
val (x, <!REDECLARATION!>y<!>) = A();
|
val (<!UNUSED_VARIABLE!>x<!>, <!REDECLARATION, UNUSED_VARIABLE!>y<!>) = A();
|
||||||
val <!REDECLARATION!>b<!> = 1
|
val <!REDECLARATION!>b<!> = 1
|
||||||
use(b)
|
use(b)
|
||||||
val (<!REDECLARATION!>b<!>, <!REDECLARATION!>y<!>) = A();
|
val (<!REDECLARATION, UNUSED_VARIABLE!>b<!>, <!REDECLARATION, UNUSED_VARIABLE!>y<!>) = A();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class MyClass2 {}
|
|||||||
|
|
||||||
fun MyClass2.component1() = 1.2
|
fun MyClass2.component1() = 1.2
|
||||||
|
|
||||||
fun test(<!UNUSED_PARAMETER!>mc1<!>: MyClass, <!UNUSED_PARAMETER!>mc2<!>: MyClass2) {
|
fun test(mc1: MyClass, mc2: MyClass2) {
|
||||||
val (a, b) = mc1
|
val (a, b) = mc1
|
||||||
a : Int
|
a : Int
|
||||||
b : String
|
b : String
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//KT-2643 Support multi-declarations in Data-Flow analysis
|
||||||
|
package n
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun component1() = 1
|
||||||
|
fun component2() = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1(c: C) {
|
||||||
|
val (<!UNUSED_VARIABLE!>a<!>, <!UNUSED_VARIABLE!>b<!>) = c
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2(c: C) {
|
||||||
|
val (a, <!UNUSED_VARIABLE!>b<!>) = c
|
||||||
|
a + 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(c: C) {
|
||||||
|
var (<!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>a<!>, <!UNUSED_VARIABLE!>b<!>) = c
|
||||||
|
a = <!UNUSED_VALUE!>3<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test4(c: C) {
|
||||||
|
var (<!VARIABLE_WITH_REDUNDANT_INITIALIZER!>a<!>, <!UNUSED_VARIABLE!>b<!>) = c
|
||||||
|
a = 3
|
||||||
|
a + 1
|
||||||
|
}
|
||||||
@@ -1088,6 +1088,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt");
|
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt2643MultiDeclInControlFlow.kt")
|
||||||
|
public void testKt2643MultiDeclInControlFlow() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt559.kt")
|
@TestMetadata("kt559.kt")
|
||||||
public void testKt559() throws Exception {
|
public void testKt559() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt559.kt");
|
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt559.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user