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.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");
|
||||
|
||||
Reference in New Issue
Block a user