Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start position and End position #94

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

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