1
0
forked from VimPlug/jedi

Merge pull request #586 from squidarth/580_semantic_keyword_completion

Added support for correct continue & break autocompletion.
This commit is contained in:
Dave Halter
2015-05-18 11:27:05 +02:00
4 changed files with 74 additions and 15 deletions

View File

@@ -157,7 +157,7 @@ class Script(object):
if unfinished_dotted: if unfinished_dotted:
return completion_names return completion_names
else: else:
return keywords.keyword_names('import') return set([keywords.keyword('import').name])
if isinstance(user_stmt, tree.Import): if isinstance(user_stmt, tree.Import):
module = self._parser.module() module = self._parser.module()
@@ -168,7 +168,11 @@ class Script(object):
if names is None and not isinstance(user_stmt, tree.Import): if names is None and not isinstance(user_stmt, tree.Import):
if not path and not dot: if not path and not dot:
# add keywords # 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 # TODO delete? We should search for valid parser
# transformations. # transformations.
completion_names += self._simple_complete(path, dot, like) completion_names += self._simple_complete(path, dot, like)

View File

@@ -5,7 +5,7 @@ from jedi._compatibility import is_py3
from jedi import common from jedi import common
from jedi.evaluate import compiled from jedi.evaluate import compiled
from jedi.evaluate.helpers import FakeName from jedi.evaluate.helpers import FakeName
from jedi.parser.tree import Leaf
try: try:
from pydoc_data import topics as pydoc_topics from pydoc_data import topics as pydoc_topics
except ImportError: except ImportError:
@@ -18,22 +18,49 @@ else:
keys = keyword.kwlist + ['None', 'False', 'True'] keys = keyword.kwlist + ['None', 'False', 'True']
def keywords(string='', pos=(0, 0), all=False): def has_inappropriate_leaf_keyword(pos, module):
if all: relevant_errors = filter(
return set([Keyword(k, pos) for k in keys]) 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: if string in keys:
return set([Keyword(string, pos)]) return Keyword(string, pos)
return set() else:
return None
def keyword_names(*args, **kwargs):
return [k.name for k in keywords(*args, **kwargs)]
def get_operator(string, pos): def get_operator(string, pos):
return Keyword(string, pos) return Keyword(string, pos)
keywords_only_valid_as_leaf = (
'continue',
'break',
)
class Keyword(object): class Keyword(object):
def __init__(self, name, pos): def __init__(self, name, pos):
self.name = FakeName(name, self, pos) self.name = FakeName(name, self, pos)
@@ -43,6 +70,10 @@ class Keyword(object):
def get_parent_until(self): def get_parent_until(self):
return self.parent return self.parent
@property
def only_valid_as_leaf(self):
return self.name.value in keywords_only_valid_as_leaf
@property @property
def names(self): def names(self):
""" For a `parsing.Name` like comparision """ """ For a `parsing.Name` like comparision """

View File

@@ -4,3 +4,24 @@ raise
#? ['except', 'Exception'] #? ['except', 'Exception']
except except
#? []
b + continu
#? []
b + continue
#? ['continue']
b; continue
#? ['continue']
b; continu
#? []
c + brea
#? []
a + break
#? ['break']
b; break

View File

@@ -290,9 +290,12 @@ def collect_dir_tests(base_dir, test_files, check_thirdparty=False):
skip = 'Thirdparty-Library %s not found.' % lib skip = 'Thirdparty-Library %s not found.' % lib
path = os.path.join(base_dir, f_name) path = os.path.join(base_dir, f_name)
source = open(path).read()
if not is_py3: if is_py3:
source = unicode(source, 'UTF-8') source = open(path, encoding='utf-8').read()
else:
source = unicode(open(path).read(), 'UTF-8')
for case in collect_file_tests(StringIO(source), for case in collect_file_tests(StringIO(source),
lines_to_execute): lines_to_execute):
case.path = path case.path = path