308 lines
7.7 KiB
Python
308 lines
7.7 KiB
Python
from src.file_cache import ASTParser
|
|
|
|
def test_ast_parser_initialization() -> None:
|
|
"""Verify that ASTParser can be initialized with a language string."""
|
|
parser = ASTParser(language="python")
|
|
assert parser.language.name == "python"
|
|
|
|
def test_ast_parser_parse() -> None:
|
|
"""Verify that the parse method returns a tree_sitter.Tree."""
|
|
parser = ASTParser(language="python")
|
|
code = "def hello(): print('world')"
|
|
tree = parser.parse(code)
|
|
assert tree is not None
|
|
assert tree.root_node.type == "module"
|
|
|
|
def test_ast_parser_get_skeleton_python() -> None:
|
|
"""Verify that get_skeleton replaces function bodies with '...' while preserving docstrings."""
|
|
parser = ASTParser(language="python")
|
|
code = '''
|
|
def complex_function(a, b):
|
|
"""This is a docstring."""
|
|
x = a + b
|
|
return x
|
|
|
|
class MyClass:
|
|
def method(self):
|
|
"""Method docstring."""
|
|
pass
|
|
'''
|
|
skeleton = parser.get_skeleton(code)
|
|
assert 'def complex_function(a, b):' in skeleton
|
|
assert '"""This is a docstring."""' in skeleton
|
|
assert '...' in skeleton
|
|
assert 'x = a + b' not in skeleton
|
|
assert 'class MyClass:' in skeleton
|
|
assert 'def method(self):' in skeleton
|
|
assert '"""Method docstring."""' in skeleton
|
|
|
|
def test_ast_parser_get_skeleton_c() -> None:
|
|
"""Verify that get_skeleton replaces function bodies with '...' for C while preserving structs."""
|
|
parser = ASTParser(language="c")
|
|
code = """
|
|
struct MyStruct {
|
|
int x;
|
|
};
|
|
|
|
void my_func() {
|
|
printf("hello\\n");
|
|
}
|
|
"""
|
|
skeleton = parser.get_skeleton(code)
|
|
assert 'struct MyStruct {' in skeleton
|
|
assert 'int x;' in skeleton
|
|
assert 'void my_func()' in skeleton
|
|
assert '...' in skeleton
|
|
assert 'printf("hello\\n");' not in skeleton
|
|
|
|
def test_ast_parser_get_skeleton_cpp() -> None:
|
|
"""Verify that get_skeleton replaces function and method bodies with '...' for C++."""
|
|
parser = ASTParser(language="cpp")
|
|
code = """
|
|
class MyClass {
|
|
public:
|
|
void myMethod() {
|
|
int x = 1;
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
void myTemplateFunc(T x) {
|
|
x.doSomething();
|
|
}
|
|
"""
|
|
skeleton = parser.get_skeleton(code)
|
|
assert 'class MyClass {' in skeleton
|
|
assert 'void myMethod() ...' in skeleton
|
|
assert 'template <typename T>' in skeleton
|
|
assert 'void myTemplateFunc(T x) ...' in skeleton
|
|
assert 'int x = 1;' not in skeleton
|
|
assert 'x.doSomething();' not in skeleton
|
|
|
|
def test_ast_parser_invalid_language() -> None:
|
|
"""Verify handling of unsupported or invalid languages."""
|
|
# Currently ASTParser defaults to Python if language not supported or just fails tree-sitter init
|
|
# If it's intended to raise or handle gracefully, test it here.
|
|
pass
|
|
|
|
def test_ast_parser_cpp_init() -> None:
|
|
"""Verify that ASTParser can be initialized with 'cpp'."""
|
|
parser = ASTParser(language="cpp")
|
|
assert parser.language_name == "cpp"
|
|
|
|
def test_ast_parser_c_init() -> None:
|
|
"""Verify that ASTParser can be initialized with 'c'."""
|
|
parser = ASTParser(language="c")
|
|
assert parser.language_name == "c"
|
|
|
|
def test_ast_parser_get_curated_view() -> None:
|
|
"""Verify that get_curated_view preserves function bodies with @core_logic or # [HOT]."""
|
|
parser = ASTParser(language="python")
|
|
code = '''
|
|
def normal_func():
|
|
print("hide me")
|
|
|
|
@core_logic
|
|
def important_func():
|
|
print("keep me")
|
|
|
|
def hot_func():
|
|
# [HOT]
|
|
print("keep me too")
|
|
'''
|
|
curated = parser.get_curated_view(code)
|
|
assert 'print("hide me")' not in curated
|
|
assert 'print("keep me")' in curated
|
|
assert 'print("keep me too")' in curated
|
|
assert '@core_logic' in curated
|
|
assert '# [HOT]' in curated
|
|
|
|
def test_ast_parser_get_targeted_view() -> None:
|
|
"""Verify get_targeted_view includes targeted functions and dependencies."""
|
|
parser = ASTParser(language="python")
|
|
code = '''
|
|
import sys
|
|
|
|
def dep2():
|
|
"""Dep 2"""
|
|
print("dep2")
|
|
|
|
def dep1():
|
|
"""Dep 1"""
|
|
dep2()
|
|
|
|
def targeted():
|
|
"""Targeted"""
|
|
dep1()
|
|
|
|
def unrelated():
|
|
"""Unrelated"""
|
|
print("unrelated")
|
|
|
|
class MyClass:
|
|
def method1(self):
|
|
"""Method 1"""
|
|
targeted()
|
|
def method2(self):
|
|
"""Method 2"""
|
|
pass
|
|
'''
|
|
# Depth 0: targeted
|
|
# Depth 1: dep1 (called by targeted)
|
|
# Depth 2: dep2 (called by dep1)
|
|
view = parser.get_targeted_view(code, ["targeted"])
|
|
assert 'def targeted():' in view
|
|
assert '"""Targeted"""' in view
|
|
assert 'def dep1():' in view
|
|
assert '"""Dep 1"""' in view
|
|
assert 'def dep2():' in view
|
|
assert '"""Dep 2"""' in view
|
|
assert 'def unrelated():' not in view
|
|
assert 'class MyClass:' not in view
|
|
assert 'import sys' in view
|
|
|
|
# Test depth limit
|
|
# Depth 0: MyClass.method1
|
|
# Depth 1: targeted (called by method1)
|
|
# Depth 2: dep1 (called by targeted)
|
|
# Depth 3: dep2 (called by dep1) -> should be elided
|
|
view2 = parser.get_targeted_view(code, ["MyClass.method1"])
|
|
assert 'class MyClass:' in view2
|
|
assert 'def method1(self):' in view2
|
|
assert 'def targeted():' in view2
|
|
assert 'def dep1():' in view2
|
|
assert 'def dep2():' not in view2
|
|
assert 'def method2(self):' not in view2
|
|
|
|
def test_ast_parser_get_code_outline_c() -> None:
|
|
"""Verify that get_code_outline works for C."""
|
|
parser = ASTParser(language="c")
|
|
code = """
|
|
struct MyStruct {
|
|
int x;
|
|
};
|
|
|
|
void my_func() {
|
|
printf("hello\\n");
|
|
}
|
|
"""
|
|
outline = parser.get_code_outline(code)
|
|
assert '[Struct] MyStruct (Lines 2-4)' in outline
|
|
assert '[Func] my_func (Lines 6-8)' in outline
|
|
|
|
def test_ast_parser_get_code_outline_cpp() -> None:
|
|
"""Verify that get_code_outline works for C++."""
|
|
parser = ASTParser(language="cpp")
|
|
code = """
|
|
class MyClass {
|
|
public:
|
|
void myMethod() {
|
|
}
|
|
};
|
|
"""
|
|
outline = parser.get_code_outline(code)
|
|
assert '[Class] MyClass (Lines 2-6)' in outline
|
|
assert ' [Method] myMethod (Lines 4-5)' in outline
|
|
|
|
def test_ast_parser_get_definition_c() -> None:
|
|
"""Verify get_definition for C."""
|
|
parser = ASTParser(language="c")
|
|
code = """
|
|
void my_func() {
|
|
printf("hello\\n");
|
|
}
|
|
|
|
struct MyStruct {
|
|
int x;
|
|
};
|
|
"""
|
|
def1 = parser.get_definition(code, "my_func")
|
|
assert 'void my_func() {' in def1
|
|
assert 'printf("hello\\n");' in def1
|
|
|
|
def2 = parser.get_definition(code, "MyStruct")
|
|
assert 'struct MyStruct {' in def2
|
|
assert 'int x;' in def2
|
|
|
|
def test_ast_parser_get_definition_cpp() -> None:
|
|
"""Verify get_definition for C++ including scoped methods."""
|
|
parser = ASTParser(language="cpp")
|
|
code = """
|
|
class MyClass {
|
|
public:
|
|
void myMethod() {
|
|
int x = 1;
|
|
}
|
|
};
|
|
|
|
namespace MyNamespace {
|
|
void nsFunc() {}
|
|
}
|
|
"""
|
|
# Scoped lookup
|
|
def1 = parser.get_definition(code, "MyClass::myMethod")
|
|
assert 'void myMethod() {' in def1
|
|
assert 'int x = 1;' in def1
|
|
|
|
# Just name lookup
|
|
def2 = parser.get_definition(code, "myMethod")
|
|
assert 'void myMethod() {' in def2
|
|
|
|
# Namespace lookup
|
|
def3 = parser.get_definition(code, "MyNamespace::nsFunc")
|
|
assert 'void nsFunc() {}' in def3
|
|
|
|
def test_ast_parser_get_definition_cpp_template() -> None:
|
|
"""Verify get_definition for C++ templates."""
|
|
parser = ASTParser(language="cpp")
|
|
code = """
|
|
template <typename T>
|
|
void myTemplateFunc(T x) {
|
|
}
|
|
"""
|
|
def1 = parser.get_definition(code, "myTemplateFunc")
|
|
assert 'template <typename T>' in def1
|
|
assert 'void myTemplateFunc(T x) {' in def1
|
|
|
|
def test_ast_parser_get_signature_c() -> None:
|
|
"""Verify get_signature for C."""
|
|
parser = ASTParser(language="c")
|
|
code = """
|
|
void my_func(int a,
|
|
char* b) {
|
|
printf("hello\\n");
|
|
}
|
|
"""
|
|
sig = parser.get_signature(code, "my_func")
|
|
assert 'void my_func(int a,' in sig
|
|
assert 'char* b)' in sig
|
|
assert '{' not in sig
|
|
assert 'printf' not in sig
|
|
|
|
def test_ast_parser_get_signature_cpp() -> None:
|
|
"""Verify get_signature for C++ templates and methods."""
|
|
parser = ASTParser(language="cpp")
|
|
code = """
|
|
class MyClass {
|
|
public:
|
|
template <typename T>
|
|
T myTemplateMethod(T x) {
|
|
return x;
|
|
}
|
|
|
|
void normalMethod() {
|
|
}
|
|
};
|
|
"""
|
|
# Template method
|
|
sig1 = parser.get_signature(code, "MyClass::myTemplateMethod")
|
|
assert 'template <typename T>' in sig1
|
|
assert 'T myTemplateMethod(T x)' in sig1
|
|
assert '{' not in sig1
|
|
|
|
# Normal method
|
|
sig2 = parser.get_signature(code, "MyClass::normalMethod")
|
|
assert 'void normalMethod()' in sig2
|
|
assert '{' not in sig2
|
|
|