feat(parser): Implement C/C++ skeleton and outline extraction
This commit is contained in:
+63
-3
@@ -110,7 +110,7 @@ class ASTParser:
|
||||
def walk(node: tree_sitter.Node) -> None:
|
||||
if node.type == "function_definition":
|
||||
body = node.child_by_field_name("body")
|
||||
if body and body.type == "block":
|
||||
if body and body.type in ("block", "compound_statement"):
|
||||
indent = " " * body.start_point.column
|
||||
first_stmt = None
|
||||
for child in body.children:
|
||||
@@ -178,7 +178,7 @@ class ASTParser:
|
||||
def walk(node: tree_sitter.Node) -> None:
|
||||
if node.type == "function_definition":
|
||||
body = node.child_by_field_name("body")
|
||||
if body and body.type == "block":
|
||||
if body and body.type in ("block", "compound_statement"):
|
||||
# Check if we should preserve it
|
||||
preserve = has_core_logic_decorator(node) or has_hot_comment(node)
|
||||
if not preserve:
|
||||
@@ -315,7 +315,7 @@ class ASTParser:
|
||||
fullname = f"{parent_class}.{fname}" if parent_class else fname
|
||||
if fullname in all_found:
|
||||
body = node.child_by_field_name("body")
|
||||
if body and body.type == "block":
|
||||
if body and body.type in ("block", "compound_statement"):
|
||||
indent = " " * body.start_point.column
|
||||
first_stmt = None
|
||||
for child in body.children:
|
||||
@@ -368,6 +368,66 @@ class ASTParser:
|
||||
result = re.sub(r'\n\s*\n\s*\n+', '\n\n', result)
|
||||
return result.strip() + "\n"
|
||||
|
||||
def get_code_outline(self, code: str, path: Optional[str] = None) -> str:
|
||||
"""
|
||||
Returns a hierarchical outline of the code (classes, structs, functions, methods).
|
||||
"""
|
||||
tree = self.get_cached_tree(path, code)
|
||||
output = []
|
||||
|
||||
def get_name(node: tree_sitter.Node) -> str:
|
||||
name_node = node.child_by_field_name("name")
|
||||
if name_node:
|
||||
return code[name_node.start_byte:name_node.end_byte]
|
||||
|
||||
if node.type == "function_definition":
|
||||
decl = node.child_by_field_name("declarator")
|
||||
while decl:
|
||||
if decl.type in ("identifier", "field_identifier"):
|
||||
return code[decl.start_byte:decl.end_byte]
|
||||
next_decl = decl.child_by_field_name("declarator")
|
||||
if not next_decl and decl.child_count > 0:
|
||||
for child in decl.children:
|
||||
if child.type in ("identifier", "field_identifier"):
|
||||
return code[child.start_byte:child.end_byte]
|
||||
decl = decl.children[0]
|
||||
else:
|
||||
decl = next_decl
|
||||
|
||||
if node.type in ("struct_specifier", "class_specifier"):
|
||||
for child in node.children:
|
||||
if child.type in ("type_identifier", "identifier"):
|
||||
return code[child.start_byte:child.end_byte]
|
||||
return ""
|
||||
|
||||
def walk(node: tree_sitter.Node, indent: int = 0) -> None:
|
||||
ntype = node.type
|
||||
label = ""
|
||||
if ntype in ("class_definition", "class_specifier"):
|
||||
label = "[Class]"
|
||||
elif ntype == "struct_specifier":
|
||||
label = "[Struct]"
|
||||
elif ntype == "function_definition":
|
||||
label = "[Method]" if indent > 0 else "[Func]"
|
||||
|
||||
if label:
|
||||
name = get_name(node)
|
||||
if name:
|
||||
start = node.start_point.row + 1
|
||||
end = node.end_point.row + 1
|
||||
output.append(f"{' ' * indent}{label} {name} (Lines {start}-{end})")
|
||||
body = node.child_by_field_name("body")
|
||||
if body:
|
||||
for child in body.children:
|
||||
walk(child, indent + 1)
|
||||
return
|
||||
|
||||
for child in node.children:
|
||||
walk(child, indent)
|
||||
|
||||
walk(tree.root_node)
|
||||
return "\n".join(output)
|
||||
|
||||
def reset_client() -> None:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user