Coverage for src / renaissance / integrations / clang / clang_adapter.py: 87%

31 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-09-09 14:04 +0000

1from clang import cindex 

2 

3from renaissance.integrations.tree_sitter.lst import LST, LSTNode 

4from renaissance.utils.ast_utils import detect_placeholder 

5 

6 

7class ClangAdapter: 

8 def __init__(self, clang_path: str | None = None, args: list | None = None): 

9 if clang_path and cindex.Config.library_path is None: 

10 cindex.Config.set_library_path(clang_path) 

11 self.args = args or ["-std=c++17"] 

12 

13 def parse(self, file_path: str) -> LST: 

14 index = cindex.Index.create() 

15 translation_unit = index.parse(file_path, args=self.args) 

16 return LST(self._convert_node(translation_unit.cursor)) 

17 

18 def load_from_text(self, text: str, file_name: str): 

19 index = cindex.Index.create() 

20 translation_unit = index.parse(file_name, unsaved_files=[(file_name, text)], args=[]) 

21 return LST(self._convert_node(translation_unit.cursor)) 

22 

23 def to_lst(self, source_code: str) -> LST: 

24 # source_code= replace_dollar(source_code) 

25 return self.load_from_text(source_code, "no_src.cpp") 

26 

27 def _convert_node(self, cursor: cindex.Cursor, parent: LSTNode | None = None) -> LSTNode: 

28 try: 

29 kind = cursor.kind.name 

30 except Exception as e: 

31 print(e.__cause__) 

32 kind = "invalid kind" 

33 signature = cursor.spelling or cursor.displayname or kind 

34 

35 is_ph, coerced_type, ph_name = detect_placeholder(signature, kind) 

36 

37 node = LSTNode( 

38 node_type=coerced_type if is_ph else kind, 

39 properties={ 

40 "spelling": cursor.spelling, 

41 "type": str(cursor.type.spelling), 

42 "location": str(cursor.location), 

43 "is_definition": cursor.is_definition(), 

44 "name": ph_name, 

45 **( 

46 { 

47 "placeholder": True, 

48 "placeholder_name": ph_name, 

49 "original_node_type": cursor.kind.name, 

50 } 

51 if is_ph 

52 else {} 

53 ), 

54 }, 

55 signature=signature, 

56 offset=cursor.extent.start.offset, 

57 parent=parent, 

58 ) 

59 

60 for child in cursor.get_children(): 

61 child_node = self._convert_node(child, parent=node) 

62 node.add_child(child_node) 

63 return node