diff --git a/jedi/evaluate/flow_analysis.py b/jedi/evaluate/flow_analysis.py index 3740b937..79699c78 100644 --- a/jedi/evaluate/flow_analysis.py +++ b/jedi/evaluate/flow_analysis.py @@ -35,26 +35,33 @@ UNSURE = Status(None, 'unsure') def break_check(evaluator, base_scope, element_scope): reachable = REACHABLE if isinstance(element_scope, Flow): - check_scope = element_scope - invert = False - if check_scope.command == 'else': - check_scope = check_scope.previous - invert = True + if element_scope.command == 'else': + check_scope = element_scope + while check_scope.previous is not None: + check_scope = check_scope.previous + reachable = _check_flow(evaluator, check_scope) + if reachable in (REACHABLE, UNSURE): + break + reachable = reachable.invert() + else: + reachable = _check_flow(evaluator, element_scope) - if check_scope.command == 'if' and check_scope.inputs: - types = evaluator.eval_statement(check_scope.inputs[0]) - values = set(x.py__bool__() for x in types) - if len(values) == 1: - reachable = Status.lookup_table[values.pop()] - if invert: - reachable = reachable.invert() - if reachable is UNREACHABLE: - return UNREACHABLE - else: - return UNSURE - elif check_scope.command in ('try', 'except', 'finally'): - reachable = UNSURE + # Only reachable branches need to be examined further. + if reachable in (UNREACHABLE, UNSURE): + return reachable - if base_scope != element_scope and base_scope != check_scope.parent: + if base_scope != element_scope and base_scope != element_scope.parent: return reachable & break_check(evaluator, base_scope, element_scope.parent) return reachable + + +def _check_flow(evaluator, flow): + if flow.command in ('elif', 'if') and flow.inputs: + types = evaluator.eval_statement(flow.inputs[0]) + values = set(x.py__bool__() for x in types) + if len(values) == 1: + return Status.lookup_table[values.pop()] + else: + return UNSURE + elif flow.command in ('try', 'except', 'finally', 'while'): + return UNSURE diff --git a/test/completion/flow_analysis.py b/test/completion/flow_analysis.py index 772b65b5..52c75f35 100644 --- a/test/completion/flow_analysis.py +++ b/test/completion/flow_analysis.py @@ -20,3 +20,63 @@ def try_except(x): #? float() str() try_except(1) + + +# Exceptions are not analyzed. So check both if branches +def try_except(x): + try: + if 0: + return 1 + else: + return '' + except AttributeError: + return 1.0 + +#? float() str() +try_except(1) + + +# ----------------- +# elif +# ----------------- + +def elif_flows1(x): + if False: + return 1 + elif True: + return 1.0 + else: + return '' + +#? float() +elif_flows1(1) + + +def elif_flows2(x): + try: + if False: + return 1 + elif 0: + return 1.0 + else: + return '' + except ValueError: + return set + +#? str() set +elif_flows2(1) + + +def elif_flows3(x): + try: + if True: + return 1 + elif 0: + return 1.0 + else: + return '' + except ValueError: + return set + +#? int() set +elif_flows3(1)