KT-2667 Support multi-declarations in for-loops in control flow analysis
#KT-2667 fixed
This commit is contained in:
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator
|
|||||||
import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction;
|
import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
|
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
@@ -529,9 +530,13 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
JetParameter loopParameter = expression.getLoopParameter();
|
JetParameter loopParameter = expression.getLoopParameter();
|
||||||
if (loopParameter != null) {
|
if (loopParameter != null) {
|
||||||
builder.declare(loopParameter);
|
value(loopParameter, inCondition);
|
||||||
builder.write(loopParameter, loopParameter);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
JetMultiDeclaration multiParameter = expression.getMultiParameter();
|
||||||
|
value(multiParameter, inCondition);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO : primitive cases
|
// TODO : primitive cases
|
||||||
Label loopExitPoint = builder.createUnboundLabel();
|
Label loopExitPoint = builder.createUnboundLabel();
|
||||||
Label conditionEntryPoint = builder.createUnboundLabel();
|
Label conditionEntryPoint = builder.createUnboundLabel();
|
||||||
@@ -632,8 +637,8 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitParameter(JetParameter parameter) {
|
public void visitParameter(JetParameter parameter) {
|
||||||
JetExpression defaultValue = parameter.getDefaultValue();
|
|
||||||
builder.declare(parameter);
|
builder.declare(parameter);
|
||||||
|
JetExpression defaultValue = parameter.getDefaultValue();
|
||||||
if (defaultValue != null) {
|
if (defaultValue != null) {
|
||||||
value(defaultValue, inCondition);
|
value(defaultValue, inCondition);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -447,40 +447,39 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
else if (instruction instanceof VariableDeclarationInstruction) {
|
else if (instruction instanceof VariableDeclarationInstruction) {
|
||||||
JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
||||||
if (element instanceof JetNamedDeclaration) {
|
if (!(element instanceof JetNamedDeclaration)) return;
|
||||||
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 JetVariableDeclaration) {
|
if (JetPsiUtil.isVariableNotParameterDeclaration(element)) {
|
||||||
trace.report(Errors.UNUSED_VARIABLE.on((JetVariableDeclaration) element, variableDescriptor));
|
trace.report(Errors.UNUSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
else if (element instanceof JetParameter) {
|
else if (element instanceof JetParameter) {
|
||||||
PsiElement psiElement = element.getParent().getParent();
|
PsiElement psiElement = element.getParent().getParent();
|
||||||
if (psiElement instanceof JetFunction) {
|
if (psiElement instanceof JetFunction) {
|
||||||
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
|
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
|
||||||
if (psiElement instanceof JetFunctionLiteral) return;
|
if (psiElement instanceof JetFunctionLiteral) return;
|
||||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||||
assert descriptor instanceof FunctionDescriptor : psiElement.getText();
|
assert descriptor instanceof FunctionDescriptor : psiElement.getText();
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||||
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
||||||
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor));
|
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (variableUseState == ONLY_WRITTEN_NEVER_READ && element instanceof JetVariableDeclaration) {
|
}
|
||||||
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetVariableDeclaration) element, variableDescriptor));
|
else if (variableUseState == ONLY_WRITTEN_NEVER_READ && JetPsiUtil.isVariableNotParameterDeclaration(element)) {
|
||||||
|
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
|
||||||
|
}
|
||||||
|
else if (variableUseState == LAST_WRITTEN && element instanceof JetVariableDeclaration) {
|
||||||
|
if (element instanceof JetProperty) {
|
||||||
|
JetExpression initializer = ((JetProperty) element).getInitializer();
|
||||||
|
if (initializer != null) {
|
||||||
|
trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (variableUseState == LAST_WRITTEN && element instanceof JetVariableDeclaration) {
|
else if (element instanceof JetMultiDeclarationEntry) {
|
||||||
if (element instanceof JetProperty) {
|
trace.report(VARIABLE_WITH_REDUNDANT_INITIALIZER.on(element, variableDescriptor));
|
||||||
JetExpression initializer = ((JetProperty) element).getInitializer();
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,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<JetVariableDeclaration, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
|
UnusedElementDiagnosticFactory<JetNamedDeclaration, 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);
|
||||||
|
|||||||
@@ -336,4 +336,12 @@ public class JetPsiUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isVariableNotParameterDeclaration(@NotNull JetDeclaration declaration) {
|
||||||
|
if (!(declaration instanceof JetVariableDeclaration)) return false;
|
||||||
|
if (declaration instanceof JetProperty) return true;
|
||||||
|
assert declaration instanceof JetMultiDeclarationEntry;
|
||||||
|
JetMultiDeclarationEntry multiDeclarationEntry = (JetMultiDeclarationEntry) declaration;
|
||||||
|
return !(multiDeclarationEntry.getParent().getParent() instanceof JetForExpression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// KT-2667 Support multi-declarations in for-loops in control flow analysis
|
||||||
|
package d
|
||||||
|
|
||||||
|
import java.util.List
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun component1() = 1
|
||||||
|
fun component2() = 2
|
||||||
|
fun component3() = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(list: List<A>) {
|
||||||
|
for (var (c1, c2, c3) in list) {
|
||||||
|
c1 = <!UNUSED_VALUE!>1<!>
|
||||||
|
c3 + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1058,6 +1058,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt");
|
doTest("compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DataFlowInMultiDeclInFor.kt")
|
||||||
|
public void testDataFlowInMultiDeclInFor() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInMultiDeclInFor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("DataFlowInfoInMultiDecl.kt")
|
@TestMetadata("DataFlowInfoInMultiDecl.kt")
|
||||||
public void testDataFlowInfoInMultiDecl() throws Exception {
|
public void testDataFlowInfoInMultiDecl() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt");
|
doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user