diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index f9ce7bd40b2d..bc3d6d795cb8 100644 --- a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -443,7 +443,7 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { boolean isStaticallyTrue = false; if (condition != null) { condition.accept(this); - isStaticallyTrue = PyEvaluator.evaluateBoolean(condition, false); + isStaticallyTrue = PyEvaluator.evaluateAsBoolean(condition, false); } final Instruction head = myBuilder.prevInstruction; final PyElsePart elsePart = node.getElsePart(); @@ -813,7 +813,7 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { super.visitPyAssertStatement(node); final PyExpression[] args = node.getArguments(); // assert False - if (args.length >= 1 && !PyEvaluator.evaluateBoolean(args[0], true)) { + if (args.length >= 1 && !PyEvaluator.evaluateAsBoolean(args[0], true)) { abruptFlow(node); return; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java index b6b0e91cd305..8d7182a8f7f8 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java +++ b/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java @@ -18,6 +18,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.psi.PsiElement; import com.intellij.psi.ResolveResult; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyNames; import com.jetbrains.python.PyTokenTypes; @@ -341,16 +342,40 @@ public class PyEvaluator { return PyUtil.as(new PyEvaluator().evaluate(expression), resultType); } - public static boolean evaluateBoolean(@Nullable PyExpression expr, boolean defaultValue) { - final Object result = new PyEvaluator().evaluate(expr); + /** + * Shortcut that evaluates expression and tries to determine if `bool` will return true for it + * + * @param expression expression to evaluate + * @return true if expression is evaluated to value so `bool` returns true for it + */ + @Nullable + public static Boolean evaluateAsBoolean(@Nullable PyExpression expression) { + final PyEvaluator evaluator = new PyEvaluator(); + evaluator.setEvaluateCollectionItems(false); + evaluator.setEvaluateKeys(false); + + final Object result = evaluator.evaluate(expression); + if (result instanceof Boolean) { return (Boolean)result; } else if (result instanceof Integer) { - return ((Integer)result) != 0; + return (Integer)result != 0; } - else { - return defaultValue; + else if (result instanceof String) { + return !((String)result).isEmpty(); } + else if (result instanceof Collection) { + return !((Collection)result).isEmpty(); + } + else if (result instanceof Map) { + return !((Map)result).isEmpty(); + } + + return null; + } + + public static boolean evaluateAsBoolean(@Nullable PyExpression expression, boolean defaultValue) { + return ObjectUtils.notNull(evaluateAsBoolean(expression), defaultValue); } } diff --git a/python/testSrc/com/jetbrains/python/PyEvaluatorTest.java b/python/testSrc/com/jetbrains/python/PyEvaluatorTest.java index aee80fdb0e07..00726fe32adf 100644 --- a/python/testSrc/com/jetbrains/python/PyEvaluatorTest.java +++ b/python/testSrc/com/jetbrains/python/PyEvaluatorTest.java @@ -264,6 +264,23 @@ public class PyEvaluatorTest extends PyTestCase { assertNull(new PyEvaluator().evaluate(expression)); } + public void testEvaluateAsBoolean() { + assertTrue(PyEvaluator.evaluateAsBoolean(parseExpression("True"))); + assertFalse(PyEvaluator.evaluateAsBoolean(parseExpression("False"))); + + assertTrue(PyEvaluator.evaluateAsBoolean(parseExpression("\'a\'"))); + assertFalse(PyEvaluator.evaluateAsBoolean(parseExpression("\'\'"))); + + assertTrue(PyEvaluator.evaluateAsBoolean(parseExpression("1"))); + assertFalse(PyEvaluator.evaluateAsBoolean(parseExpression("0"))); + + assertTrue(PyEvaluator.evaluateAsBoolean(parseExpression("{1: 0}"))); + assertFalse(PyEvaluator.evaluateAsBoolean(parseExpression("{}"))); + + assertTrue(PyEvaluator.evaluateAsBoolean(parseExpression("[1]"))); + assertFalse(PyEvaluator.evaluateAsBoolean(parseExpression("[]"))); + } + @NotNull private T byExpression(@NotNull String expression, @NotNull Class cls) { final Object value = new PyEvaluator().evaluate(parseExpression(expression));