From 258d5aee4a8733b8aedcc12e6acafa1104b2796e Mon Sep 17 00:00:00 2001 From: Sid Shanker Date: Sun, 10 May 2015 18:59:55 -0700 Subject: [PATCH] Added support for correct continue & break autocompletion. --- jedi/api/__init__.py | 8 ++++-- jedi/api/keywords.py | 51 +++++++++++++++++++++++++++++-------- test/completion/keywords.py | 21 +++++++++++++++ 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index a5b0b109..31300974 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -157,7 +157,7 @@ class Script(object): if unfinished_dotted: return completion_names else: - return keywords.keyword_names('import') + return set([keywords.keyword('import').name]) if isinstance(user_stmt, tree.Import): module = self._parser.module() @@ -168,7 +168,11 @@ class Script(object): if names is None and not isinstance(user_stmt, tree.Import): if not path and not dot: # add keywords - completion_names += keywords.keyword_names(all=True) + completion_names += keywords.completion_names( + self._evaluator, + user_stmt, + self._pos, + module) # TODO delete? We should search for valid parser # transformations. completion_names += self._simple_complete(path, dot, like) diff --git a/jedi/api/keywords.py b/jedi/api/keywords.py index 2a54ba2d..4feb39fd 100644 --- a/jedi/api/keywords.py +++ b/jedi/api/keywords.py @@ -5,7 +5,7 @@ from jedi._compatibility import is_py3 from jedi import common from jedi.evaluate import compiled from jedi.evaluate.helpers import FakeName - +from jedi.parser.tree import Leaf try: from pydoc_data import topics as pydoc_topics except ImportError: @@ -18,22 +18,49 @@ else: keys = keyword.kwlist + ['None', 'False', 'True'] -def keywords(string='', pos=(0, 0), all=False): - if all: - return set([Keyword(k, pos) for k in keys]) +def has_inappropriate_leaf_keyword(pos, module): + relevant_errors = filter( + lambda error: error.first_pos[0] == pos[0], + module.error_statement_stacks) + + for error in relevant_errors: + if error.next_token in keys: + return True + + return False + +def completion_names(evaluator, stmt, pos, module): + keyword_list = all_keywords() + + if not isinstance(stmt, Leaf) or has_inappropriate_leaf_keyword(pos, module): + keyword_list = filter( + lambda keyword: not keyword.only_valid_as_leaf, + keyword_list + ) + return [keyword.name for keyword in keyword_list] + + +def all_keywords(pos=(0,0)): + return set([Keyword(k, pos) for k in keys]) + + +def keyword(string, pos=(0,0)): if string in keys: - return set([Keyword(string, pos)]) - return set() - - -def keyword_names(*args, **kwargs): - return [k.name for k in keywords(*args, **kwargs)] + return Keyword(string, pos) + else: + return None def get_operator(string, pos): return Keyword(string, pos) +keywords_only_valid_as_leaf = ( + 'continue', + 'break', +) + + class Keyword(object): def __init__(self, name, pos): self.name = FakeName(name, self, pos) @@ -43,6 +70,10 @@ class Keyword(object): def get_parent_until(self): return self.parent + @property + def only_valid_as_leaf(self): + return self.name.value in keywords_only_valid_as_leaf + @property def names(self): """ For a `parsing.Name` like comparision """ diff --git a/test/completion/keywords.py b/test/completion/keywords.py index 851140b1..ba56c210 100644 --- a/test/completion/keywords.py +++ b/test/completion/keywords.py @@ -4,3 +4,24 @@ raise #? ['except', 'Exception'] except + +#? [] +b + continu + +#? [] +b + continue + +#? ['continue'] +b; continue + +#? ['continue'] +b; continu + +#? [] +c + brea + +#? [] +a + break + +#? ['break'] +b; break