1
0
forked from VimPlug/jedi

indentation reduced with iterator (see previous commit)

This commit is contained in:
David Halter
2012-11-02 18:34:15 +01:00
parent 740260b372
commit 4667ea5573

View File

@@ -1611,188 +1611,185 @@ class PyFuzzyParser(object):
self.iterator = iter(self) self.iterator = iter(self)
# This iterator stuff is not intentional. It grew historically. # This iterator stuff is not intentional. It grew historically.
for token_type, tok in self.iterator: for token_type, tok in self.iterator:
self.module.temp_used_names = [] self.module.temp_used_names = []
#debug.dbg('main: tok=[%s] type=[%s] indent=[%s]'\ #debug.dbg('main: tok=[%s] type=[%s] indent=[%s]'\
# % (tok, tokenize.tok_name[token_type], start_position[0])) # % (tok, tokenize.tok_name[token_type], start_position[0]))
while token_type == tokenize.DEDENT \ while token_type == tokenize.DEDENT and self.scope != self.module:
and self.scope != self.module: token_type, tok = self.next()
token_type, tok = self.next() if self.start_pos[1] <= self.scope.start_pos[1]:
if self.start_pos[1] <= self.scope.start_pos[1]:
self.scope.end_pos = self.start_pos
self.scope = self.scope.parent()
# check again for unindented stuff. this is true for syntax
# errors. only check for names, because thats relevant here. If
# some docstrings are not indented, I don't care.
while self.start_pos[1] <= self.scope.start_pos[1] \
and (token_type == tokenize.NAME or tok in ['(', '['])\
and self.scope != self.module:
self.scope.end_pos = self.start_pos self.scope.end_pos = self.start_pos
self.scope = self.scope.parent() self.scope = self.scope.parent()
first_pos = self.start_pos # check again for unindented stuff. this is true for syntax
if tok == 'def': # errors. only check for names, because thats relevant here. If
func = self._parsefunction() # some docstrings are not indented, I don't care.
if func is None: while self.start_pos[1] <= self.scope.start_pos[1] \
debug.warning("function: syntax error@%s" % and (token_type == tokenize.NAME or tok in ['(', '['])\
self.start_pos[0]) and self.scope != self.module:
continue self.scope.end_pos = self.start_pos
self.freshscope = True self.scope = self.scope.parent()
self.scope = self.scope.add_scope(func, decorators)
decorators = [] first_pos = self.start_pos
elif tok == 'class': if tok == 'def':
cls = self._parseclass() func = self._parsefunction()
if cls is None: if func is None:
debug.warning("class: syntax error@%s" % debug.warning("function: syntax error@%s" %
self.start_pos[0]) self.start_pos[0])
continue continue
self.freshscope = True self.freshscope = True
self.scope = self.scope.add_scope(cls, decorators) self.scope = self.scope.add_scope(func, decorators)
decorators = [] decorators = []
# import stuff elif tok == 'class':
elif tok == 'import': cls = self._parseclass()
imports = self._parseimportlist() if cls is None:
for m, alias, defunct in imports: debug.warning("class: syntax error@%s" % self.start_pos[0])
i = Import(first_pos, self.end_pos, m, alias, continue
defunct=defunct) self.freshscope = True
self._check_user_stmt(i) self.scope = self.scope.add_scope(cls, decorators)
self.scope.add_import(i) decorators = []
if not imports: # import stuff
i = Import(first_pos, self.end_pos, None, defunct=True) elif tok == 'import':
self._check_user_stmt(i) imports = self._parseimportlist()
self.freshscope = False for m, alias, defunct in imports:
elif tok == 'from': i = Import(first_pos, self.end_pos, m, alias,
defunct = False defunct=defunct)
# take care for relative imports self._check_user_stmt(i)
relative_count = 0 self.scope.add_import(i)
while 1: if not imports:
token_type, tok = self.next() i = Import(first_pos, self.end_pos, None, defunct=True)
if tok != '.': self._check_user_stmt(i)
break self.freshscope = False
relative_count += 1 elif tok == 'from':
# the from import defunct = False
mod, token_type, tok = self._parsedotname(self.current) # take care for relative imports
if str(mod) == 'import' and relative_count: relative_count = 0
while 1:
token_type, tok = self.next()
if tok != '.':
break
relative_count += 1
# the from import
mod, token_type, tok = self._parsedotname(self.current)
if str(mod) == 'import' and relative_count:
self.gen.push_back(self._current_full)
tok = 'import'
mod = None
if not mod and not relative_count or tok != "import":
debug.warning("from: syntax error@%s" % self.start_pos[0])
defunct = True
if tok != 'import':
self.gen.push_back(self._current_full) self.gen.push_back(self._current_full)
tok = 'import' names = self._parseimportlist()
mod = None for name, alias, defunct2 in names:
if not mod and not relative_count or tok != "import": star = name is not None and name.names[0] == '*'
debug.warning("from: syntax error@%s" % if star:
self.start_pos[0]) name = None
defunct = True i = Import(first_pos, self.end_pos, name, alias, mod,
if tok != 'import': star, relative_count, defunct=defunct or defunct2)
self.gen.push_back(self._current_full) self._check_user_stmt(i)
names = self._parseimportlist() self.scope.add_import(i)
for name, alias, defunct2 in names: self.freshscope = False
star = name is not None and name.names[0] == '*' #loops
if star: elif tok == 'for':
name = None set_stmt, tok = self._parse_statement(added_breaks=['in'])
i = Import(first_pos, self.end_pos, name, alias, mod, if tok == 'in':
star, relative_count, defunct=defunct or defunct2) statement, tok = self._parse_statement()
self._check_user_stmt(i) if tok == ':':
self.scope.add_import(i) s = [] if statement is None else [statement]
self.freshscope = False f = ForFlow(s, first_pos, set_stmt)
#loops self.scope = self.scope.add_statement(f)
elif tok == 'for':
set_stmt, tok = self._parse_statement(added_breaks=['in'])
if tok == 'in':
statement, tok = self._parse_statement()
if tok == ':':
s = [] if statement is None else [statement]
f = ForFlow(s, first_pos, set_stmt)
self.scope = self.scope.add_statement(f)
else:
debug.warning('syntax err, for flow started @%s',
self.start_pos[0])
if statement is not None:
statement.parent = weakref.ref(self.scope)
if set_stmt is not None:
set_stmt.parent = weakref.ref(self.scope)
else: else:
debug.warning('syntax err, for flow incomplete @%s', debug.warning('syntax err, for flow started @%s',
self.start_pos[0]) self.start_pos[0])
if statement is not None:
statement.parent = weakref.ref(self.scope)
if set_stmt is not None: if set_stmt is not None:
set_stmt.parent = weakref.ref(self.scope) set_stmt.parent = weakref.ref(self.scope)
elif tok in ['if', 'while', 'try', 'with'] + extended_flow:
added_breaks = []
command = tok
if command in ['except', 'with']:
added_breaks.append(',')
# multiple statements because of with
inits = []
first = True
while first or command == 'with' \
and tok not in [':', '\n']:
statement, tok = \
self._parse_statement(added_breaks=added_breaks)
if command == 'except' and tok in added_breaks:
# the except statement defines a var
# this is only true for python 2
n, token_type, tok = self._parsedotname()
if n:
statement.set_vars.append(n)
statement.code += ',' + n.get_code()
if statement:
inits.append(statement)
first = False
if tok == ':':
f = Flow(command, inits, first_pos)
if command in extended_flow:
# the last statement has to be another part of
# the flow statement, because a dedent releases the
# main scope, so just take the last statement.
try:
s = self.scope.statements[-1].set_next(f)
except (AttributeError, IndexError):
# If set_next doesn't exist, just add it.
s = self.scope.add_statement(f)
else:
s = self.scope.add_statement(f)
self.scope = s
else:
for i in inits:
i.parent = weakref.ref(self.scope)
debug.warning('syntax err, flow started @%s',
self.start_pos[0])
# globals
elif tok == 'global':
stmt, tok = self._parse_statement(self.current)
if stmt:
self.scope.add_statement(stmt)
for name in stmt.used_vars:
# add the global to the top, because there it is
# important.
self.module.add_global(name)
# decorator
elif tok == '@':
stmt, tok = self._parse_statement()
decorators.append(stmt)
elif tok == 'pass':
continue
elif tok == 'assert':
stmt, tok = self._parse_statement()
stmt.parent = weakref.ref(self.scope)
self.scope.asserts.append(stmt)
# default
elif token_type in [tokenize.NAME, tokenize.STRING,
tokenize.NUMBER] \
or tok in statement_toks:
# this is the main part - a name can be a function or a
# normal var, which can follow anything. but this is done
# by the statement parser.
stmt, tok = self._parse_statement(self.current)
if stmt:
self.scope.add_statement(stmt)
self.freshscope = False
else: else:
if token_type not in [tokenize.COMMENT, tokenize.INDENT, debug.warning('syntax err, for flow incomplete @%s',
tokenize.NEWLINE, tokenize.NL, self.start_pos[0])
tokenize.ENDMARKER]: if set_stmt is not None:
debug.warning('token not classified', tok, token_type, set_stmt.parent = weakref.ref(self.scope)
self.start_pos[0])
elif tok in ['if', 'while', 'try', 'with'] + extended_flow:
added_breaks = []
command = tok
if command in ['except', 'with']:
added_breaks.append(',')
# multiple statements because of with
inits = []
first = True
while first or command == 'with' \
and tok not in [':', '\n']:
statement, tok = \
self._parse_statement(added_breaks=added_breaks)
if command == 'except' and tok in added_breaks:
# the except statement defines a var
# this is only true for python 2
n, token_type, tok = self._parsedotname()
if n:
statement.set_vars.append(n)
statement.code += ',' + n.get_code()
if statement:
inits.append(statement)
first = False
if tok == ':':
f = Flow(command, inits, first_pos)
if command in extended_flow:
# the last statement has to be another part of
# the flow statement, because a dedent releases the
# main scope, so just take the last statement.
try:
s = self.scope.statements[-1].set_next(f)
except (AttributeError, IndexError):
# If set_next doesn't exist, just add it.
s = self.scope.add_statement(f)
else:
s = self.scope.add_statement(f)
self.scope = s
else:
for i in inits:
i.parent = weakref.ref(self.scope)
debug.warning('syntax err, flow started @%s',
self.start_pos[0])
# globals
elif tok == 'global':
stmt, tok = self._parse_statement(self.current)
if stmt:
self.scope.add_statement(stmt)
for name in stmt.used_vars:
# add the global to the top, because there it is
# important.
self.module.add_global(name)
# decorator
elif tok == '@':
stmt, tok = self._parse_statement()
decorators.append(stmt)
elif tok == 'pass':
continue
elif tok == 'assert':
stmt, tok = self._parse_statement()
stmt.parent = weakref.ref(self.scope)
self.scope.asserts.append(stmt)
# default
elif token_type in [tokenize.NAME, tokenize.STRING,
tokenize.NUMBER] \
or tok in statement_toks:
# this is the main part - a name can be a function or a
# normal var, which can follow anything. but this is done
# by the statement parser.
stmt, tok = self._parse_statement(self.current)
if stmt:
self.scope.add_statement(stmt)
self.freshscope = False
else:
if token_type not in [tokenize.COMMENT, tokenize.INDENT,
tokenize.NEWLINE, tokenize.NL,
tokenize.ENDMARKER]:
debug.warning('token not classified', tok, token_type,
self.start_pos[0])
del self.buf del self.buf
return self.module return self.module