From 1afdb693143947eaeec96969b591fb4898d000f8 Mon Sep 17 00:00:00 2001 From: David Halter Date: Sun, 2 Sep 2012 12:39:11 +0200 Subject: [PATCH] function annotations are now safely ignored by the evaluation. the parser just stores them in the right objects. --- README.mdown | 3 ++- evaluate.py | 1 - parsing.py | 39 +++++++++++++++++++++++++++++------- test/completion/functions.py | 17 ++++++++++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/README.mdown b/README.mdown index c5bd586c..6416789e 100644 --- a/README.mdown +++ b/README.mdown @@ -46,11 +46,12 @@ Jedi supports many of the widely used Python features: `__get__`, `__getitem__`, `__init__` - support for list.append, set.add, list.extend, etc. - (nested) list comprehensions / ternary expressions + - function annotations (py3k feature, are ignored right now, but being parsed. + I don't know what to do with them.) However, it does not yet support (and probably will in future versions, because they are on my todo list): - - function annotations (py3k feature) - class decorators (py3k feature) - getattr() / __getattr__ / __getattribute__ - sys.path modifications diff --git a/evaluate.py b/evaluate.py index 00c601ed..4875e60b 100644 --- a/evaluate.py +++ b/evaluate.py @@ -13,7 +13,6 @@ TODO evaluate asserts/isinstance (type safety) python 3 stuff: TODO class decorators -TODO annotations ? how ? type evaluation and return? TODO nonlocal statement, needed or can be ignored? TODO __ instance attributes should not be visible outside of the class. diff --git a/parsing.py b/parsing.py index 075db832..93cbbf1d 100644 --- a/parsing.py +++ b/parsing.py @@ -336,8 +336,8 @@ class Function(Scope): :param docstr: The docstring for the current Scope. :type docstr: str """ - def __init__(self, name, params, start_pos, docstr=''): - Scope.__init__(self, start_pos, docstr) + def __init__(self, name, params, start_pos, annotation): + Scope.__init__(self, start_pos) self.name = name name.parent = weakref.ref(self) self.params = params @@ -348,6 +348,10 @@ class Function(Scope): self.is_generator = False self.listeners = set() # not used here, but in evaluation. + if annotation is not None: + annotation.parent = weakref.ref(self) + self.annotation = annotation + def get_code(self, first_indent=False, indention=" "): str = "\n".join('@' + stmt.get_code() for stmt in self.decorators) params = ','.join([stmt.code for stmt in self.params]) @@ -790,6 +794,11 @@ class Param(Statement): # it is the position in the call (first argument, second...) self.position_nr = None self.is_generated = False + self.annotation_stmt = None + + def add_annotation(self, annotation_stmt): + annotation_stmt.parent = weakref.ref(self) + self.annotation_stmt = annotation_stmt def get_name(self): """ get the name of the param """ @@ -1162,12 +1171,18 @@ class PyFuzzyParser(object): names = [] tok = None pos = 0 + breaks = [',', ':'] while tok not in [')', ':']: - stmt, tok = self._parse_statement(added_breaks=',', + param, tok = self._parse_statement(added_breaks=breaks, stmt_class=Param) - if stmt: - stmt.position_nr = pos - names.append(stmt) + if param and tok == ':': + # parse annotations + annotation, tok = self._parse_statement(added_breaks=breaks) + param.add_annotation(annotation) + + if param: + param.position_nr = pos + names.append(param) pos += 1 return names @@ -1193,10 +1208,20 @@ class PyFuzzyParser(object): params = self._parseparen() token_type, colon = self.next() + annotation = None + if colon in ['-', '->']: + # parse annotations + if colon == '-': + # The Python 2 tokenizer doesn't understand this + token_type, colon = self.next() + if colon != '>': + return None + annotation, colon = self._parse_statement(added_breaks=[':']) + if colon != ':': return None - return Function(fname, params, first_pos) + return Function(fname, params, first_pos, annotation) def _parseclass(self): """ diff --git a/test/completion/functions.py b/test/completion/functions.py index 7d536a91..83cb5376 100644 --- a/test/completion/functions.py +++ b/test/completion/functions.py @@ -320,3 +320,20 @@ nested_def2('', b=1, c=1.0)[1] nested_def2('', c=1.0, b=1)[1] #? [] nested_def2('')[1] + +# ----------------- +# function annotations (should be ignored at the moment) +# ----------------- +def annot(a:3, *args:3): + return a, args[0] + +#? str() +annot('', 1.0)[0] +#? float() +annot('', 1.0)[1] + +def annot_ret(a:3) -> 3: + return a + +#? str() +annot_ret('')