From 027fe9bb55f26dfdb6b609a5485c207051b7e739 Mon Sep 17 00:00:00 2001 From: fitermay Date: Mon, 3 Oct 2016 14:19:59 +0300 Subject: [PATCH] PY-1177 Fixed: Control flow analysis doesn't detect while/break Handle control flow for statically true condition in while statement --- .../controlflow/PyControlFlowBuilder.java | 22 +++++++++---------- .../WhileTrueBreak.py | 4 ++++ .../PyUnboundLocalVariableInspectionTest.java | 7 +++++- 3 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 python/testData/inspections/PyUnboundLocalVariableInspection/WhileTrueBreak.py diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index fbff5c2d8a00..0dd30074a902 100644 --- a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -404,26 +404,26 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { final Instruction instruction = myBuilder.startNode(node); final PyWhilePart whilePart = node.getWhilePart(); final PyExpression condition = whilePart.getCondition(); + boolean isStaticallyTrue = false; if (condition != null) { condition.accept(this); + isStaticallyTrue = (PyConstantExpressionEvaluator.evaluate(condition) == Boolean.TRUE); } final Instruction head = myBuilder.prevInstruction; final PyElsePart elsePart = node.getElsePart(); - if (elsePart == null) { + if (elsePart == null && !isStaticallyTrue) { myBuilder.addPendingEdge(node, myBuilder.prevInstruction); } final PyStatementList list = whilePart.getStatementList(); - if (list != null) { - myBuilder.startConditionalNode(list, condition, true); - list.accept(this); - // Loop edges - if (myBuilder.prevInstruction != null) { - myBuilder.addEdge(myBuilder.prevInstruction, instruction); - } - myBuilder.checkPending(instruction); + myBuilder.startConditionalNode(list, condition, true); + list.accept(this); + // Loop edges + if (myBuilder.prevInstruction != null) { + myBuilder.addEdge(myBuilder.prevInstruction, instruction); } + myBuilder.checkPending(instruction); myBuilder.prevInstruction = head; - if (elsePart != null) { + if (elsePart != null && !isStaticallyTrue) { elsePart.accept(this); myBuilder.addPendingEdge(node, myBuilder.prevInstruction); } diff --git a/python/testData/inspections/PyUnboundLocalVariableInspection/WhileTrueBreak.py b/python/testData/inspections/PyUnboundLocalVariableInspection/WhileTrueBreak.py new file mode 100644 index 000000000000..0308cd3758db --- /dev/null +++ b/python/testData/inspections/PyUnboundLocalVariableInspection/WhileTrueBreak.py @@ -0,0 +1,4 @@ +while True: + a = 1 + break +print(a) # pass diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnboundLocalVariableInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnboundLocalVariableInspectionTest.java index feb634b6faad..5b4f9f8c0abe 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnboundLocalVariableInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnboundLocalVariableInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -183,6 +183,11 @@ public class PyUnboundLocalVariableInspectionTest extends PyTestCase { doTest(); } + // PY-1177 + public void testWhileTrueBreak() { + doTest(); + } + private void doTest() { myFixture.configureByFile(TEST_DIRECTORY + getTestName(false) + ".py"); myFixture.enableInspections(PyUnboundLocalVariableInspection.class);