Coverage for src/rejuvenation/remove_unused_variable.py: 85%

34 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-15 10:34 +0000

1# Copyright (C) 2024-2026 TNO 

2# 

3# Licensed under the terms specified in the LICENSE file in the root directory 

4# of this repository, also available at: 

5# https://github.com/TNO/Renaissance.Py/blob/main/LICENSE 

6 

7"""AI: Example script demonstrating removal of unused variables from C source via the cleanup refactoring recipe.""" 

8 

9from more_itertools import flatten 

10 

11from renaissance.integrations.clang import ClangASTNode 

12from renaissance.integrations.clang.clang_json_ast_node import ClangJsonASTNode 

13from renaissance.integrations.clang.predicates import is_clang_compound_statement 

14from renaissance.recipes import CleanupRefactoring 

15from renaissance.syntax_tree import ( 

16 ASTFactory, 

17 ASTNode, 

18 ASTProcessor, 

19 ASTRewriter, 

20 ASTShower, 

21) 

22from renaissance.syntax_tree.ast_finder import find_nodes 

23from renaissance.syntax_tree.semantic_kind import SemanticKind 

24 

25example_code = """ 

26 int a = 1; 

27 int b = 2; 

28 int c = 3; 

29 int d = 4; 

30 void x(int a) { 

31 } 

32 void f(){ 

33 int unused = 0; 

34 int unused2 = 0; //must be removed 

35 if (a==1) { 

36 int unused = 0; 

37 int unused2 = 0; //should be kept 

38 int c = unused2; 

39 x(c); 

40 } 

41 } 

42 """ 

43expected_result_refactor = """ 

44 int a = 1; 

45 int b = 2; 

46 int c = 3; 

47 int d = 4; 

48 void x(int a) { 

49 } 

50 void f(){ 

51 if (a==1) { 

52 int unused2 = 0; //should be kept 

53 int c = unused2; 

54 x(c); 

55 } 

56 }""".strip() 

57 

58 

59def remove_unused_variable_using_refactor_method(node_type1: type[ASTNode]): 

60 """AI: Remove unused variables from the example code via `CleanupRefactoring.remove_unused_variables`.""" 

61 factory = ASTFactory(node_type1, []) 

62 # create translation unit 

63 atu = factory.create_from_text(example_code, "test.c") 

64 # create a Refactor 

65 refactor = ASTProcessor(atu, factory, in_memory=True) 

66 

67 CleanupRefactoring.remove_unused_variables(refactor) 

68 result = refactor.apply_to_string().strip() 

69 # print the rewritten code 

70 print(f"Using cleanup refactoring results {node_type1.__name__}:") 

71 print(result) 

72 

73 return result, expected_result_refactor 

74 

75 

76def remove_unused_variable_low_level(node_type1: type[ASTNode]): 

77 """AI: Remove unused variables from the example code using low-level pattern matching directly.""" 

78 factory = ASTFactory(ClangJsonASTNode, []) 

79 # Create a pattern factory (using the factory (hence also its args) 

80 # create translation unit 

81 atu = factory.create_from_text(example_code, "test.c") 

82 

83 # create an ASTRewriter 

84 rewriter = ASTRewriter(atu) 

85 

86 ASTShower.show_node(atu) 

87 # search matches and replace them 

88 funcs = flatten( 

89 find_nodes(func, lambda node: node.semantic_kind is SemanticKind.DECLARATION) 

90 for func in find_nodes(atu, is_clang_compound_statement) 

91 ) 

92 [rewriter.remove(node.parent, True, True) for node in funcs if len(node.referenced_by) == 0] 

93 

94 # print the rewritten code 

95 print(f"Low level results using {node_type1.__name__}:") 

96 result = rewriter.apply_to_string().strip() 

97 print(result) 

98 return result, expected_result_refactor 

99 

100 

101if __name__ == "__main__": 

102 for node_type in [ClangASTNode, ClangJsonASTNode]: 

103 remove_unused_variable_low_level(node_type) 

104 remove_unused_variable_using_refactor_method(node_type)