1
0
forked from VimPlug/jedi

Merge with the linter branch (especially the changes of pep484.

This commit is contained in:
Dave Halter
2016-06-07 13:51:25 +02:00
27 changed files with 883 additions and 108 deletions

View File

@@ -46,7 +46,7 @@ def load_grammar(version='3.4'):
if version in ('3.2', '3.3'):
version = '3.4'
elif version == '2.6':
version == '2.7'
version = '2.7'
file = 'grammar' + version + '.txt'

View File

@@ -15,15 +15,17 @@
# file_input is a module or sequence of commands read from an input file;
# eval_input is the input for the eval() functions.
# NB: compound_stmt in single_input is followed by extra NEWLINE!
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
file_input: (NEWLINE | stmt)* ENDMARKER
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
eval_input: testlist NEWLINE* ENDMARKER
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef | async_funcdef)
async_funcdef: ASYNC funcdef
# NOTE: Reinoud Elhorst, using ASYNC/AWAIT keywords instead of tokens
# skipping python3.5 compatibility, in favour of 3.7 solution
async_funcdef: 'async' funcdef
funcdef: 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
@@ -69,7 +71,7 @@ nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
assert_stmt: 'assert' test [',' test]
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
async_stmt: ASYNC (funcdef | with_stmt | for_stmt)
async_stmt: 'async' (funcdef | with_stmt | for_stmt)
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
@@ -82,7 +84,9 @@ with_stmt: 'with' with_item (',' with_item)* ':' suite
with_item: test ['as' expr]
# NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test ['as' NAME]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
# Edit by David Halter: The stmt is now optional. This reflects how Jedi allows
# classes and functions to be empty, which is beneficial for autocompletion.
suite: simple_stmt | NEWLINE INDENT stmt* DEDENT
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
@@ -104,7 +108,7 @@ arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom_expr ['**' factor]
atom_expr: [AWAIT] atom trailer*
atom_expr: ['await'] atom trailer*
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |

View File

@@ -1,6 +1,6 @@
from __future__ import absolute_import
from jedi._compatibility import is_py3
from jedi._compatibility import is_py3, is_py35
from token import *
@@ -24,6 +24,11 @@ else:
tok_name[ELLIPSIS] = 'ELLIPSIS'
N_TOKENS += 1
if not is_py35:
ATEQUAL = N_TOKENS
tok_name[ATEQUAL] = 'ATEQUAL'
N_TOKENS += 1
# Map from operator to number (since tokenize doesn't do this)
@@ -68,6 +73,7 @@ opmap_raw = """\
%= PERCENTEQUAL
&= AMPEREQUAL
|= VBAREQUAL
@= ATEQUAL
^= CIRCUMFLEXEQUAL
<<= LEFTSHIFTEQUAL
>>= RIGHTSHIFTEQUAL

View File

@@ -76,7 +76,7 @@ triple = group("[uUbB]?[rR]?'''", '[uUbB]?[rR]?"""')
# recognized as two instances of =).
operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=",
r"//=?", r"->",
r"[+\-*/%&|^=<>]=?",
r"[+\-*@/%&|^=<>]=?",
r"~")
bracket = '[][(){}]'

View File

@@ -589,10 +589,44 @@ class BaseNode(Base):
c = self.parent.children
index = c.index(self)
if index == len(c) - 1:
# TODO WTF? recursion?
return self.get_next_leaf()
else:
return c[index + 1]
def last_leaf(self):
try:
return self.children[-1].last_leaf()
except AttributeError:
return self.children[-1]
def get_following_comment_same_line(self):
"""
returns (as string) any comment that appears on the same line,
after the node, including the #
"""
try:
if self.isinstance(ForStmt):
whitespace = self.children[5].first_leaf().prefix
elif self.isinstance(WithStmt):
whitespace = self.children[3].first_leaf().prefix
else:
whitespace = self.last_leaf().get_next_leaf().prefix
except AttributeError:
return None
except ValueError:
# TODO in some particular cases, the tree doesn't seem to be linked
# correctly
return None
if "#" not in whitespace:
return None
comment = whitespace[whitespace.index("#"):]
if "\r" in comment:
comment = comment[:comment.index("\r")]
if "\n" in comment:
comment = comment[:comment.index("\n")]
return comment
@utf8_repr
def __repr__(self):
code = self.get_code().replace('\n', ' ').strip()
@@ -1471,7 +1505,7 @@ def _defined_names(current):
names += _defined_names(child)
elif is_node(current, 'atom'):
names += _defined_names(current.children[1])
elif is_node(current, 'power'):
elif is_node(current, 'power', 'atom_expr'):
if current.children[-2] != '**': # Just if there's no operation
trailer = current.children[-1]
if trailer.children[0] == '.':