Coverage for src/renaissance/integrations/clang/clang_compilation_database.py: 47%
19 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-10-02 13:12 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-10-02 13:12 +0000
1"""AI: Load a Clang compilation database and iterate its translation units as AST nodes."""
3from collections.abc import Iterator
4from pathlib import Path
6from clang.cindex import CompilationDatabase as ClangCompilationDatabase
8from renaissance.syntax_tree import ASTFactory, ASTNode
11class CompilationDatabase:
12 """AI: Load a Clang compilation database and iterate its translation units as AST nodes."""
14 @staticmethod
15 def walk(typ: type[ASTNode], path: Path) -> Iterator[tuple[ASTFactory, ASTNode]]:
16 """Load the Clang compilation database and yield factory and AST node type tuples.
18 Args:
19 typ (type[ASTNode]): The type of AST node to be used.
20 path (Path): The path to the directory containing the compilation database.
22 Yields:
23 Iterator[tuple[ASTFactory, ASTNode]]: An iterator of tuples, each containing
24 an AST factory and an AST node type.
26 Be careful to not use the Iterable is a list as it will load ALL the AST nodes in memory.
28 """
29 db = ClangCompilationDatabase.fromDirectory(str(path))
31 def factory_and_atu(command):
32 return CompilationDatabase.__create_processor(typ, command)
34 yield from map(factory_and_atu, db.getAllCompileCommands())
36 @staticmethod
37 def __create_processor(typ: type[ASTNode], compile_command) -> tuple[ASTFactory, ASTNode]:
38 extra_args = list(compile_command.arguments)
39 skip = ["-o", "-c"]
40 filtered_args = [
41 arg
42 for idx, arg in enumerate(extra_args)
43 if arg != compile_command.filename and arg not in skip and (idx == 0 or extra_args[idx - 1] not in skip)
44 ]
45 factory = ASTFactory(typ, extra_args=filtered_args, working_dir=Path(compile_command.directory))
46 atu = factory.create(Path(compile_command.filename)) # The first argument is the file path
47 return factory, atu