KT-2667 Support multi-declarations in for-loops in control flow analysis

#KT-2667 fixed
This commit is contained in:
Svetlana Isakova
2012-08-23 14:25:13 +04:00
parent 21774f5288
commit ac39daace6
6 changed files with 68 additions and 34 deletions
@@ -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.Pseudocode;
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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
@@ -529,9 +530,13 @@ public class JetControlFlowProcessor {
}
JetParameter loopParameter = expression.getLoopParameter();
if (loopParameter != null) {
builder.declare(loopParameter);
builder.write(loopParameter, loopParameter);
value(loopParameter, inCondition);
}
else {
JetMultiDeclaration multiParameter = expression.getMultiParameter();
value(multiParameter, inCondition);
}
// TODO : primitive cases
Label loopExitPoint = builder.createUnboundLabel();
Label conditionEntryPoint = builder.createUnboundLabel();
@@ -632,8 +637,8 @@ public class JetControlFlowProcessor {
@Override
public void visitParameter(JetParameter parameter) {
JetExpression defaultValue = parameter.getDefaultValue();
builder.declare(parameter);
JetExpression defaultValue = parameter.getDefaultValue();
if (defaultValue != null) {
value(defaultValue, inCondition);
}
@@ -447,40 +447,39 @@ public class JetFlowInformationProvider {
}
else if (instruction instanceof VariableDeclarationInstruction) {
JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
if (element instanceof JetNamedDeclaration) {
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
if (nameIdentifier == null) return;
if (!VariableUseState.isUsed(variableUseState)) {
if (element instanceof JetVariableDeclaration) {
trace.report(Errors.UNUSED_VARIABLE.on((JetVariableDeclaration) element, variableDescriptor));
}
else if (element instanceof JetParameter) {
PsiElement psiElement = element.getParent().getParent();
if (psiElement instanceof JetFunction) {
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
if (psiElement instanceof JetFunctionLiteral) return;
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
assert descriptor instanceof FunctionDescriptor : psiElement.getText();
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor));
}
if (!(element instanceof JetNamedDeclaration)) return;
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
if (nameIdentifier == null) return;
if (!VariableUseState.isUsed(variableUseState)) {
if (JetPsiUtil.isVariableNotParameterDeclaration(element)) {
trace.report(Errors.UNUSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
}
else if (element instanceof JetParameter) {
PsiElement psiElement = element.getParent().getParent();
if (psiElement instanceof JetFunction) {
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
if (psiElement instanceof JetFunctionLiteral) return;
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
assert descriptor instanceof FunctionDescriptor : psiElement.getText();
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
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) {
if (element instanceof JetProperty) {
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));
}
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, 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<JetNamedDeclaration, DeclarationDescriptor> ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, NAME_IDENTIFIER);
DiagnosticFactory1<JetExpression, DeclarationDescriptor> VARIABLE_WITH_REDUNDANT_INITIALIZER = DiagnosticFactory1.create(WARNING);
@@ -336,4 +336,12 @@ public class JetPsiUtil {
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");
}
@TestMetadata("DataFlowInMultiDeclInFor.kt")
public void testDataFlowInMultiDeclInFor() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInMultiDeclInFor.kt");
}
@TestMetadata("DataFlowInfoInMultiDecl.kt")
public void testDataFlowInfoInMultiDecl() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt");