summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Thénault <sylvain.thenault@logilab.fr>2009-03-19 09:55:41 +0100
committerSylvain Thénault <sylvain.thenault@logilab.fr>2009-03-19 09:55:41 +0100
commit3993719a083006b98df1d06258f7a1b31b049e5f (patch)
treecd2021fe422a018d7ededef7f5c5280527100b00
parent439dea370cdb048a0871510dae9818ec7fbaa5c4 (diff)
downloadastroid-git-3993719a083006b98df1d06258f7a1b31b049e5f.tar.gz
fix line numbering of
* decorated function for _ast * decorators node for compiler --HG-- branch : _ast_compat
-rw-r--r--_nodes_ast.py4
-rw-r--r--patchcomptransformer.py3
-rw-r--r--scoped_nodes.py3
-rw-r--r--test/unittest_builder.py19
4 files changed, 26 insertions, 3 deletions
diff --git a/_nodes_ast.py b/_nodes_ast.py
index 670e5c1d..cb66c9aa 100644
--- a/_nodes_ast.py
+++ b/_nodes_ast.py
@@ -231,6 +231,8 @@ class TreeRebuilder(ASTVisitor):
_init_set_doc(node)
if node.decorators:
node.decorators = Decorators(node.decorators)
+ else:
+ node.decorators = None
def visit_getattr(self, node):
node.attrname = node.attr
@@ -318,7 +320,7 @@ def function_factory(name, args, defaults, flag=0, doc=None):
# XXX local import necessary due to cyclic deps
from logilab.astng.nodes import const_factory
node = Function()
- node.decorators = []
+ node.decorators = None
node.body = []
node.name = name
# XXX ensure we get a compatible representation
diff --git a/patchcomptransformer.py b/patchcomptransformer.py
index b14d249e..5f3e3c92 100644
--- a/patchcomptransformer.py
+++ b/patchcomptransformer.py
@@ -112,7 +112,8 @@ class ASTNGTransformer(BaseTransformer):
def funcdef(self, nodelist):
node = BaseTransformer.funcdef(self, nodelist)
- # XXX decorators
+ if node.decorators is not None:
+ fix_lineno(node.decorators, nodelist[0])
return fix_lineno(node, nodelist[-5], nodelist[-1], nodelist[-3])
def lambdef(self, nodelist):
diff --git a/scoped_nodes.py b/scoped_nodes.py
index a8f9bdc8..68053fc7 100644
--- a/scoped_nodes.py
+++ b/scoped_nodes.py
@@ -339,6 +339,9 @@ class FunctionNG(object):
def set_line_info(self, lastchild):
self.fromlineno = self.lineno
+ # lineno is the line number of the first decorator, we want the def statement lineno
+ if self.decorators is not None:
+ self.fromlineno += len(self.decorators.nodes)
self.tolineno = lastchild.tolineno
self.blockstart_tolineno = self.args.tolineno
diff --git a/test/unittest_builder.py b/test/unittest_builder.py
index 8ef5043d..8d864381 100644
--- a/test/unittest_builder.py
+++ b/test/unittest_builder.py
@@ -97,7 +97,24 @@ class FromToLineNoTC(TestCase):
self.assertIsInstance(return_, nodes.Return)
self.assertEquals(return_.fromlineno, 18)
self.assertEquals(return_.tolineno, 18)
-
+
+ def test_decorated_function_lineno(self):
+ if sys.version_info < (2, 4):
+ self.skip('require python >=2.4')
+ astng = builder.ASTNGBuilder().string_build('''
+@decorator
+def function(
+ arg):
+ print arg
+''', __name__, __file__)
+ function = astng['function']
+ self.assertEquals(function.fromlineno, 3) # XXX discussable, but that's what is expected by pylint right now
+ self.assertEquals(function.tolineno, 5)
+ self.assertEquals(function.blockstart_tolineno, 4)
+ self.assertEquals(function.decorators.fromlineno, 2)
+ self.assertEquals(function.decorators.tolineno, 2)
+
+
def test_class_lineno(self):
stmts = self.astng.body
# on line 20: