WIP: Phase 6 review

This commit is contained in:
2026-05-10 15:14:54 -04:00
parent 7974f661b3
commit 2a71aff18c
10 changed files with 290 additions and 66 deletions
+127 -59
View File
@@ -106,18 +106,29 @@ class ASTParser:
if name_node:
return code_bytes[name_node.start_byte:name_node.end_byte].decode("utf8", errors="replace")
if node.type in ("function_definition", "field_declaration"):
if node.type in ("function_definition", "field_declaration", "declaration"):
def find_id(n: tree_sitter.Node) -> str:
if n.type in ("identifier", "field_identifier", "qualified_identifier", "destructor_name"):
# In C++, prefer function_declarator or operator_name
if self.language_name in ("cpp", "c"):
# Look for declarator field or child
decl = n.child_by_field_name("declarator")
if decl:
# If it's a function_declarator, the name is inside its 'declarator' or 'name'
if decl.type == "function_declarator":
nested_decl = decl.child_by_field_name("declarator")
if nested_decl:
return find_id(nested_decl)
elif decl.type == "pointer_declarator":
return find_id(decl)
elif decl.type in ("identifier", "field_identifier", "qualified_identifier", "operator_name", "destructor_name"):
return code_bytes[decl.start_byte:decl.end_byte].decode("utf8", errors="replace")
if n.type in ("identifier", "field_identifier", "qualified_identifier", "operator_name", "destructor_name"):
return code_bytes[n.start_byte:n.end_byte].decode("utf8", errors="replace")
# Try field name 'declarator' first
d = n.child_by_field_name("declarator")
if d:
res = find_id(d)
if res: return res
# Fallback to all children
# Fallback to children, but avoid bodies and types
for child in n.children:
if child.type == "compound_statement": continue # Don't look in body
if child.type in ("compound_statement", "field_declaration_list", "class_body", "declaration_list", "enum_body", "type_identifier", "primitive_type"): continue
res = find_id(child)
if res: return res
return ""
@@ -125,12 +136,12 @@ class ASTParser:
if node.type == "template_declaration":
for child in node.children:
if child.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "field_declaration"):
if child.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "field_declaration", "declaration"):
return self._get_name(child, code_bytes)
if node.type in ("struct_specifier", "class_specifier", "class_definition", "enum_specifier", "enum_definition", "namespace_definition"):
for child in node.children:
if child.type in ("type_identifier", "identifier", "namespace_identifier"):
if child.type in ("type_identifier", "identifier", "namespace_identifier", "qualified_identifier"):
return code_bytes[child.start_byte:child.end_byte].decode("utf8", errors="replace")
return ""
@@ -442,12 +453,11 @@ class ASTParser:
parts = re.split(r'::|\.', name)
def walk(node: tree_sitter.Node, target_parts: List[str]) -> Optional[tree_sitter.Node]:
"""
[C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python]
"""
if not target_parts:
return None
target = target_parts[0]
best_match = None
for child in node.children:
# If it's a field_declaration, it might wrap a class/struct/enum definition
check_node = child
@@ -457,12 +467,16 @@ class ASTParser:
check_node = sub
break
is_interesting = check_node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "field_declaration")
is_interesting = check_node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "field_declaration", "declaration")
if is_interesting:
node_name = self._get_name(check_node, code_bytes)
if node_name == target:
if len(target_parts) == 1:
return check_node if child.type != "field_declaration" else child
match = check_node if child.type != "field_declaration" else child
if match.child_by_field_name("body"):
return match
if not best_match:
best_match = match
next_parts = target_parts[1:]
else:
next_parts = target_parts
@@ -475,28 +489,44 @@ class ASTParser:
break
if body:
found = walk(body, next_parts)
if found: return found
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
for sub in check_node.children:
if sub.type in ("field_declaration_list", "class_body", "declaration_list", "enum_body"):
found = walk(sub, next_parts)
if found: return found
elif child.type in ("module", "translation_unit", "namespace_definition", "declaration_list", "field_declaration_list", "class_body"):
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
elif child.type in ("module", "translation_unit", "namespace_definition", "declaration_list", "field_declaration_list", "class_body", "preproc_if", "preproc_ifdef", "preproc_else", "preproc_elif"):
found = walk(child, target_parts)
if found: return found
return None
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
return best_match
def deep_search(node: tree_sitter.Node, target: str) -> Optional[tree_sitter.Node]:
if node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration"):
best = None
if node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "declaration"):
if self._get_name(node, code_bytes) == target:
return node
if node.child_by_field_name("body"):
return node
best = node
for child in node.children:
res = deep_search(child, target)
if res: return res
return None
if res:
if res.child_by_field_name("body"):
return res
if not best:
best = res
return best
found_node = walk(tree.root_node, parts)
if not found_node:
found_node = deep_search(tree.root_node, name)
if not found_node or not found_node.child_by_field_name("body"):
alt = deep_search(tree.root_node, name)
if alt:
if not found_node or alt.child_by_field_name("body"):
found_node = alt
if found_node:
return code_bytes[found_node.start_byte:found_node.end_byte].decode("utf8", errors="replace")
@@ -515,12 +545,11 @@ class ASTParser:
parts = re.split(r'::|\.', name)
def walk(node: tree_sitter.Node, target_parts: List[str]) -> Optional[tree_sitter.Node]:
"""
[C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python]
"""
if not target_parts:
return None
target = target_parts[0]
best_match = None
for child in node.children:
# If it's a field_declaration, it might wrap a class/struct/enum definition
check_node = child
@@ -530,12 +559,16 @@ class ASTParser:
check_node = sub
break
is_interesting = check_node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "field_declaration")
is_interesting = check_node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "field_declaration", "declaration")
if is_interesting:
node_name = self._get_name(check_node, code_bytes)
if node_name == target:
if len(target_parts) == 1:
return check_node if child.type != "field_declaration" else child
match = check_node if child.type != "field_declaration" else child
if match.child_by_field_name("body"):
return match
if not best_match:
best_match = match
next_parts = target_parts[1:]
else:
next_parts = target_parts
@@ -548,28 +581,44 @@ class ASTParser:
break
if body:
found = walk(body, next_parts)
if found: return found
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
for sub in check_node.children:
if sub.type in ("field_declaration_list", "class_body", "declaration_list", "enum_body"):
found = walk(sub, next_parts)
if found: return found
elif child.type in ("module", "translation_unit", "namespace_definition", "declaration_list", "field_declaration_list", "class_body"):
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
elif child.type in ("module", "translation_unit", "namespace_definition", "declaration_list", "field_declaration_list", "class_body", "preproc_if", "preproc_ifdef", "preproc_else", "preproc_elif"):
found = walk(child, target_parts)
if found: return found
return None
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
return best_match
def deep_search(node: tree_sitter.Node, target: str) -> Optional[tree_sitter.Node]:
if node.type in ("function_definition", "template_declaration"):
best = None
if node.type in ("function_definition", "template_declaration", "declaration"):
if self._get_name(node, code_bytes) == target:
return node
if node.child_by_field_name("body"):
return node
best = node
for child in node.children:
res = deep_search(child, target)
if res: return res
return None
if res:
if res.child_by_field_name("body"):
return res
if not best:
best = res
return best
found_node = walk(tree.root_node, parts)
if not found_node:
found_node = deep_search(tree.root_node, name)
if not found_node or not found_node.child_by_field_name("body"):
alt = deep_search(tree.root_node, name)
if alt:
if not found_node or alt.child_by_field_name("body"):
found_node = alt
if found_node:
target_node = found_node
@@ -639,12 +688,11 @@ class ASTParser:
parts = re.split(r'::|\.', name)
def walk(node: tree_sitter.Node, target_parts: List[str]) -> Optional[tree_sitter.Node]:
"""
[C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python]
"""
if not target_parts:
return None
target = target_parts[0]
best_match = None
for child in node.children:
# If it's a field_declaration, it might wrap a class/struct/enum definition
check_node = child
@@ -654,12 +702,16 @@ class ASTParser:
check_node = sub
break
is_interesting = check_node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "field_declaration")
is_interesting = check_node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "field_declaration", "declaration")
if is_interesting:
node_name = self._get_name(check_node, code_bytes)
if node_name == target:
if len(target_parts) == 1:
return check_node if child.type != "field_declaration" else child
match = check_node if child.type != "field_declaration" else child
if match.child_by_field_name("body"):
return match
if not best_match:
best_match = match
next_parts = target_parts[1:]
else:
next_parts = target_parts
@@ -672,28 +724,44 @@ class ASTParser:
break
if body:
found = walk(body, next_parts)
if found: return found
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
for sub in check_node.children:
if sub.type in ("field_declaration_list", "class_body", "declaration_list", "enum_body"):
found = walk(sub, next_parts)
if found: return found
elif child.type in ("module", "translation_unit", "namespace_definition", "declaration_list", "field_declaration_list", "class_body"):
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
elif child.type in ("module", "translation_unit", "namespace_definition", "declaration_list", "field_declaration_list", "class_body", "preproc_if", "preproc_ifdef", "preproc_else", "preproc_elif"):
found = walk(child, target_parts)
if found: return found
return None
if found:
if found.child_by_field_name("body"): return found
if not best_match: best_match = found
return best_match
def deep_search(node: tree_sitter.Node, target: str) -> Optional[tree_sitter.Node]:
if node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration"):
best = None
if node.type in ("function_definition", "class_definition", "class_specifier", "struct_specifier", "enum_specifier", "enum_definition", "namespace_definition", "template_declaration", "declaration"):
if self._get_name(node, code_bytes) == target:
return node
if node.child_by_field_name("body"):
return node
best = node
for child in node.children:
res = deep_search(child, target)
if res: return res
return None
if res:
if res.child_by_field_name("body"):
return res
if not best:
best = res
return best
found_node = walk(tree.root_node, parts)
if not found_node:
found_node = deep_search(tree.root_node, name)
if not found_node or not found_node.child_by_field_name("body"):
alt = deep_search(tree.root_node, name)
if alt:
if not found_node or alt.child_by_field_name("body"):
found_node = alt
if found_node:
code_bytearray = bytearray(code_bytes)