Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 36 additions & 30 deletions codeflash/languages/java/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ def __init__(self) -> None:
"""Initialize the Java analyzer."""
self._parser: Parser | None = None

# Track type context (class, interface, or enum) - single allocation
self._type_declarations = ("class_declaration", "interface_declaration", "enum_declaration")

@property
def parser(self) -> Parser:
"""Get the parser, creating it lazily."""
Expand Down Expand Up @@ -165,8 +168,10 @@ def find_methods(
tree = self.parse(source_bytes)
methods: list[JavaMethodNode] = []


root = tree.root_node
self._walk_tree_for_methods(
tree.root_node,
root,
source_bytes,
methods,
include_private=include_private,
Expand All @@ -186,41 +191,42 @@ def _walk_tree_for_methods(
current_class: str | None,
) -> None:
"""Recursively walk the tree to find method definitions."""
new_class = current_class

# Track type context (class, interface, or enum)
type_declarations = ("class_declaration", "interface_declaration", "enum_declaration")
if node.type in type_declarations:
name_node = node.child_by_field_name("name")
if name_node:
new_class = self.get_node_text(name_node, source_bytes)
# Use an explicit stack to avoid recursion overhead and repeated allocations.
stack: list[tuple[Node, str | None]] = [(node, current_class)]
type_declarations = self._type_declarations # local ref for slightly faster access

while stack:
node, current_class = stack.pop()

# Track type context (class, interface, or enum)
new_class = current_class
node_type = node.type
if node_type in type_declarations:
name_node = node.child_by_field_name("name")
if name_node:
new_class = self.get_node_text(name_node, source_bytes)

if node.type == "method_declaration":
method_info = self._extract_method_info(node, source_bytes, current_class)
if node_type == "method_declaration":
method_info = self._extract_method_info(node, source_bytes, current_class)

if method_info:
# Apply filters
should_include = True
if method_info:
# Apply filters
should_include = True

if method_info.is_private and not include_private:
should_include = False
if method_info.is_private and not include_private:
should_include = False

if method_info.is_static and not include_static:
should_include = False
if method_info.is_static and not include_static:
should_include = False

if should_include:
methods.append(method_info)
if should_include:
methods.append(method_info)

# Recurse into children
for child in node.children:
self._walk_tree_for_methods(
child,
source_bytes,
methods,
include_private=include_private,
include_static=include_static,
current_class=new_class if node.type in type_declarations else current_class,
)
# Push children in reverse order to preserve original left-to-right DFS order
children = node.children
if children:
for child in reversed(children):
stack.append((child, new_class))

def _extract_method_info(
self, node: Node, source_bytes: bytes, current_class: str | None
Expand Down
Loading