diff --git a/pycomplete.py b/pycomplete.py index 475ae99e..3b42b397 100755 --- a/pycomplete.py +++ b/pycomplete.py @@ -6,6 +6,7 @@ import sys import types from pyfuzzyparser import PyFuzzyParser +import pyfuzzyparser def complete(file_name, line, colon): @@ -222,13 +223,13 @@ showdbg() print cmpl.parser.top.get_code() #print cmpl.parser.top.subscopes[1].subscopes[0].get_code() +print 'global names:' names = cmpl.parser.top.get_names() -for n in names: - try: - print n.names - except: - print n.name - +print [n.names for n in names] + +print 'global names:' +names = cmpl.parser.top.subscopes[0].get_names() +print [n.names for n in names] p = cmpl.parser s = p.top diff --git a/pyfuzzyparser.py b/pyfuzzyparser.py index dfd209ce..76efb46c 100644 --- a/pyfuzzyparser.py +++ b/pyfuzzyparser.py @@ -30,9 +30,7 @@ Ignored statements: TODO be tolerant with indents TODO dictionaries not working with statement parser -TODO except has local vars TODO take special care for future imports -TODO add global statements """ import sys @@ -71,6 +69,7 @@ class Scope(object): self.subscopes = [] self.imports = [] self.statements = [] + self.global_vars = [] self.docstr = docstr self.parent = None self.indent = indent @@ -109,6 +108,17 @@ class Scope(object): def add_import(self, imp): self.imports.append(imp) + def add_global(self, name): + """ + Global means in these context a function (subscope) which has a global + statement. + This is only relevant for the top scope. + + :param name: The name of the global. + :type name: Name + """ + self.global_vars.append(name) + def _checkexisting(self, test): "Convienance function... keep out duplicates" if test.find('=') > -1: @@ -148,7 +158,10 @@ class Scope(object): n = [] for stmt in self.statements: n += stmt.get_names() - n += self.subscopes + + # function and class names + n += [s.name for s in self.subscopes] + n += self.global_vars return n def is_empty(self): @@ -196,7 +209,7 @@ class Function(Scope): :param name: The Function name. :type name: string - :param params: The parameters of a Function. + :param params: The parameters (Name) of a Function. :type name: list :param indent: The indent level of the flow statement. :type indent: int @@ -218,14 +231,8 @@ class Function(Scope): return str def get_names(self): - """ - Get the names for the flow. This includes also a call to the super - class. - """ - n = self.set_args - if self.next: - n += self.next.get_names() - n += super(Flow, self).get_names() + n = self.params + n += super(Function, self).get_names() return n @@ -323,8 +330,6 @@ class Import(object): :type star: bool :raises: None - - TODO check star? """ def __init__(self, line_nr, namespace, alias='', from_ns='', star=False): self.line_nr = line_nr @@ -396,7 +401,7 @@ class Name(object): """ def __init__(self, names, indent, line_nr): super(Name, self).__init__() - self.names = names + self.names = tuple(names) self.indent = indent self.line_nr = line_nr self.parent = None @@ -408,6 +413,17 @@ class Name(object): def __str__(self): return self.get_code() + def __eq__(self, other): + return self.names == other.names \ + and self.indent == other.indent \ + and self.line_nr == self.line_nr + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self.names) + hash(self.indent) + hash(self.line_nr) + class PyFuzzyParser(object): """ @@ -549,6 +565,8 @@ class PyFuzzyParser(object): if token_type != tokenize.NAME: return None + fname = Name([fname], ind, self.line_nr) + token_type, open, ind = self.next() if open != '(': return None @@ -574,6 +592,8 @@ class PyFuzzyParser(object): % (self.line_nr, token.tok_name[token_type], cname) return None + cname = Name([cname], ind, self.line_nr) + super = [] token_type, next, ind = self.next() if next == '(': @@ -661,17 +681,14 @@ class PyFuzzyParser(object): else: path, token_type, tok, start_indent = \ self._parsedotname(self.current) - print 'path', path n = Name(path, start_indent, self.line_nr) if tok == '(': # it must be a function used_funcs.append(n) else: - used_vars.append(n) - if string: - print 'str', string[-1] + if not n.names[0] in ['global']: + used_vars.append(n) if string and re.match(r'[\w\d]', string[-1]): - print 'yay' string += ' ' #if token_type == tokenize.NAME \ # and self.last_token[0] == tokenize.NAME: @@ -762,7 +779,10 @@ class PyFuzzyParser(object): mod = Name(mod, start_indent, self.line_nr) names = self._parseimportlist() for name, alias in names: - i = Import(self.line_nr, name, alias, mod) + star = name.names[0] == '*' + if star: + name = None + i = Import(self.line_nr, name, alias, mod, star) self.scope.add_import(i) freshscope = False #loops @@ -778,6 +798,7 @@ class PyFuzzyParser(object): elif tok in ['if', 'while', 'try', 'with'] + extended_flow: # TODO with statement has local variables + # TODO except has local vars command = tok statement, tok = self._parse_statement() if tok == ':': @@ -791,9 +812,14 @@ class PyFuzzyParser(object): self.scope = self.scope.add_statement(f) elif tok == 'global': - self._parse_statement(self.current) - pass - # TODO add suport for global + stmt, tok = self._parse_statement(self.current) + if stmt: + self.scope.add_statement(stmt) + print 'global_vars', stmt.used_vars + for name in stmt.used_vars: + # add the global to the top, because there it is + # important. + self.top.add_global(name) elif token_type == tokenize.STRING: if freshscope: self.scope.add_docstr(tok) @@ -806,9 +832,9 @@ class PyFuzzyParser(object): #print "_not_implemented_", tok, self.parserline except StopIteration: # thrown on EOF pass - #except: - # dbg("parse error: %s, %s @ %s" % - # (sys.exc_info()[0], sys.exc_info()[1], self.parserline)) + except StopIteration: # TODO catch the right error + dbg("parse error: %s, %s @ %s" % + (sys.exc_info()[0], sys.exc_info()[1], self.parserline)) return self.top diff --git a/test.py b/test.py index 73442fe0..d748ca49 100644 --- a/test.py +++ b/test.py @@ -10,6 +10,13 @@ from token import OP as OP_TEST, INDENT as INDENT_TEST aaa = 6; bbb = 13 ccc = bbb; d = open("test.py"); +def func(): + #def test: + # return 2 + cdef = A() + return test + + class Intro(object): def testing(self, string): return string+"," @@ -46,12 +53,6 @@ class Empty(): cdef = 5 cdef cdef -def func(): - #def test: - # return 2 - cdef = A() - return test - for i in range(3): asdf = aaa print 'blub' @@ -67,6 +68,7 @@ def ass_test(a): # test strange statements [a,c] ; {1: a}; (1,); `a` result = int((a+b)*2) + global global_test return result matrix = [[1,2,3], [4,5,6], [7,8,9]]