Skip to content

Conversation

@jose
Copy link

@jose jose commented Mar 16, 2021

In order to get the end line number of a node element, I've been using the following piece of code (also described in here):

def find_end_line_number(node):
    """Finds end line of a node."""
    max_line = node.position.line

    def traverse(node):
        for child in node.children:
            if isinstance(child, list) and (len(child) > 0):
                for item in child:
                    traverse(item)
            else:
                if hasattr(child, '_position'):
                    nonlocal max_line
                    if child._position.line > max_line:
                        max_line = child._position.line
                        return

    traverse(node)
    return max_line

which does not work for some cases, e.g., classes or methods with empty bodies. This pull request adds support to collect the end position (line number and column) of a node out-of-the-box.

@Yanivmd
Copy link

Yanivmd commented Jun 2, 2021

Hey @jose, thanks for this contribution! Saved me a lot of time.
Until this is merged I switched to using your fork.

One thing to note (for anyone else considering this) - in the main repo node.position will always exist, but sometimes be None. In the fork start_position (and I guess end_poisition) might not exist for these cases (so check with hasattr).

@emsi
Copy link

emsi commented Jul 29, 2022

@jose I'm having following error while parsing code using javalang with your patch:

File /usr/local/lib/python3.9/site-packages/javalang/ast.py:54, in Node.filter(self, pattern)
     53 def filter(self, pattern):
---> 54     for path, node in self:
     55         if ((isinstance(pattern, type) and isinstance(node, pattern)) or
     56             (node == pattern)):
     57             yield path, node

File /usr/local/lib/python3.9/site-packages/javalang/ast.py:72, in walk_tree(root)
     69 else:
     70     children = root
---> 72 for child in children:
     73     if isinstance(child, (Node, list, tuple)):
     74         for path, node in walk_tree(child):

File /usr/local/lib/python3.9/site-packages/javalang/ast.py:72, in walk_tree(root)
     69 else:
     70     children = root
---> 72 for child in children:
     73     if isinstance(child, (Node, list, tuple)):
     74         for path, node in walk_tree(child):

    [... skipping similar frames: walk_tree at line 72 (2966 times)]

File /usr/local/lib/python3.9/site-packages/javalang/ast.py:72, in walk_tree(root)
     69 else:
     70     children = root
---> 72 for child in children:
     73     if isinstance(child, (Node, list, tuple)):
     74         for path, node in walk_tree(child):

File /usr/local/lib/python3.9/site-packages/javalang/ast.py:66, in walk_tree(root)
     63 def walk_tree(root):
     64     children = None
---> 66     if isinstance(root, Node):
     67         yield (), root
     68         children = root.children

RecursionError: maximum recursion depth exceeded while calling a Python object

@emsi
Copy link

emsi commented Aug 1, 2022

I've provided alternative implementation of end position just for methods in pr #120

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants