lambda-graphs 0.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lambda_graphs/__init__.py +18 -0
- lambda_graphs/__main__.py +7 -0
- lambda_graphs/cli.py +183 -0
- lambda_graphs/codeviews/AST/AST.py +120 -0
- lambda_graphs/codeviews/AST/AST_driver.py +37 -0
- lambda_graphs/codeviews/AST/__init__.py +0 -0
- lambda_graphs/codeviews/CFG/CFG.py +42 -0
- lambda_graphs/codeviews/CFG/CFG_c.py +1182 -0
- lambda_graphs/codeviews/CFG/CFG_cpp.py +5604 -0
- lambda_graphs/codeviews/CFG/CFG_driver.py +45 -0
- lambda_graphs/codeviews/CFG/CFG_java.py +1722 -0
- lambda_graphs/codeviews/CFG/__init__.py +0 -0
- lambda_graphs/codeviews/CST/CST_driver.py +70 -0
- lambda_graphs/codeviews/CST/__init__.py +0 -0
- lambda_graphs/codeviews/DFG/DFG_driver.py +42 -0
- lambda_graphs/codeviews/DFG/__init__.py +0 -0
- lambda_graphs/codeviews/SDFG/SDFG.py +135 -0
- lambda_graphs/codeviews/SDFG/SDFG_c.py +2041 -0
- lambda_graphs/codeviews/SDFG/SDFG_cpp.py +4030 -0
- lambda_graphs/codeviews/SDFG/SDFG_java.py +1618 -0
- lambda_graphs/codeviews/SDFG/__init__.py +0 -0
- lambda_graphs/codeviews/__init__.py +0 -0
- lambda_graphs/codeviews/combined_graph/__init__.py +0 -0
- lambda_graphs/codeviews/combined_graph/combined_driver.py +163 -0
- lambda_graphs/tree_parser/__init__.py +0 -0
- lambda_graphs/tree_parser/c_parser.py +565 -0
- lambda_graphs/tree_parser/cpp_parser.py +424 -0
- lambda_graphs/tree_parser/custom_parser.py +66 -0
- lambda_graphs/tree_parser/java_parser.py +254 -0
- lambda_graphs/tree_parser/parser_driver.py +54 -0
- lambda_graphs/utils/DFG_utils.py +44 -0
- lambda_graphs/utils/__init__.py +0 -0
- lambda_graphs/utils/c_nodes.py +431 -0
- lambda_graphs/utils/cpp_nodes.py +1331 -0
- lambda_graphs/utils/java_nodes.py +756 -0
- lambda_graphs/utils/multi_file_merger.py +444 -0
- lambda_graphs/utils/postprocessor.py +83 -0
- lambda_graphs/utils/preprocessor.py +68 -0
- lambda_graphs/utils/src_parser.py +23 -0
- lambda_graphs-0.1.4.dist-info/METADATA +380 -0
- lambda_graphs-0.1.4.dist-info/RECORD +45 -0
- lambda_graphs-0.1.4.dist-info/WHEEL +5 -0
- lambda_graphs-0.1.4.dist-info/entry_points.txt +2 -0
- lambda_graphs-0.1.4.dist-info/licenses/LICENSE +21 -0
- lambda_graphs-0.1.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1331 @@
|
|
|
1
|
+
statement_types = {
|
|
2
|
+
"node_list_type": [
|
|
3
|
+
"declaration",
|
|
4
|
+
"expression_statement",
|
|
5
|
+
"labeled_statement",
|
|
6
|
+
"if_statement",
|
|
7
|
+
"while_statement",
|
|
8
|
+
"for_statement",
|
|
9
|
+
"for_range_loop",
|
|
10
|
+
"do_statement",
|
|
11
|
+
"break_statement",
|
|
12
|
+
"continue_statement",
|
|
13
|
+
"return_statement",
|
|
14
|
+
"goto_statement",
|
|
15
|
+
"switch_statement",
|
|
16
|
+
"case_statement",
|
|
17
|
+
"throw_statement",
|
|
18
|
+
"try_statement",
|
|
19
|
+
"function_definition",
|
|
20
|
+
"class_specifier",
|
|
21
|
+
"struct_specifier",
|
|
22
|
+
"using_declaration",
|
|
23
|
+
"alias_declaration",
|
|
24
|
+
"template_declaration",
|
|
25
|
+
"field_declaration",
|
|
26
|
+
"access_specifier",
|
|
27
|
+
"constructor_or_destructor_definition",
|
|
28
|
+
"operator_cast",
|
|
29
|
+
"lambda_expression",
|
|
30
|
+
"enum_specifier",
|
|
31
|
+
"union_specifier",
|
|
32
|
+
"type_definition",
|
|
33
|
+
"friend_declaration",
|
|
34
|
+
"catch_clause",
|
|
35
|
+
"attributed_statement",
|
|
36
|
+
"static_assert_declaration",
|
|
37
|
+
"namespace_alias_definition",
|
|
38
|
+
"preproc_include",
|
|
39
|
+
"preproc_def",
|
|
40
|
+
"preproc_ifdef",
|
|
41
|
+
"preproc_if",
|
|
42
|
+
"preproc_elif",
|
|
43
|
+
"preproc_else",
|
|
44
|
+
],
|
|
45
|
+
"non_control_statement": [
|
|
46
|
+
"declaration",
|
|
47
|
+
"expression_statement",
|
|
48
|
+
"field_declaration",
|
|
49
|
+
"using_declaration",
|
|
50
|
+
"alias_declaration",
|
|
51
|
+
"access_specifier",
|
|
52
|
+
"enum_specifier",
|
|
53
|
+
"union_specifier",
|
|
54
|
+
"type_definition",
|
|
55
|
+
"friend_declaration",
|
|
56
|
+
"static_assert_declaration",
|
|
57
|
+
"namespace_alias_definition",
|
|
58
|
+
"attributed_statement",
|
|
59
|
+
],
|
|
60
|
+
"control_statement": [
|
|
61
|
+
"if_statement",
|
|
62
|
+
"while_statement",
|
|
63
|
+
"for_statement",
|
|
64
|
+
"for_range_loop",
|
|
65
|
+
"do_statement",
|
|
66
|
+
"break_statement",
|
|
67
|
+
"continue_statement",
|
|
68
|
+
"return_statement",
|
|
69
|
+
"goto_statement",
|
|
70
|
+
"switch_statement",
|
|
71
|
+
"try_statement",
|
|
72
|
+
"throw_statement",
|
|
73
|
+
],
|
|
74
|
+
"loop_control_statement": [
|
|
75
|
+
"while_statement",
|
|
76
|
+
"for_statement",
|
|
77
|
+
"for_range_loop",
|
|
78
|
+
],
|
|
79
|
+
"not_implemented": [],
|
|
80
|
+
"inner_node_type": [
|
|
81
|
+
"declaration",
|
|
82
|
+
"expression_statement",
|
|
83
|
+
],
|
|
84
|
+
"outer_node_type": ["for_statement", "for_range_loop"],
|
|
85
|
+
"statement_holders": [
|
|
86
|
+
"compound_statement",
|
|
87
|
+
"case_statement",
|
|
88
|
+
"function_definition",
|
|
89
|
+
"class_specifier",
|
|
90
|
+
"struct_specifier",
|
|
91
|
+
"namespace_definition",
|
|
92
|
+
"translation_unit",
|
|
93
|
+
],
|
|
94
|
+
"definition_types": [
|
|
95
|
+
"function_definition",
|
|
96
|
+
"class_specifier",
|
|
97
|
+
"struct_specifier",
|
|
98
|
+
"field_declaration",
|
|
99
|
+
"namespace_definition",
|
|
100
|
+
"template_declaration",
|
|
101
|
+
"enum_specifier",
|
|
102
|
+
"union_specifier",
|
|
103
|
+
"type_definition",
|
|
104
|
+
],
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
method_return_types = [
|
|
108
|
+
"primitive_type",
|
|
109
|
+
"type_identifier",
|
|
110
|
+
"template_type",
|
|
111
|
+
"qualified_identifier",
|
|
112
|
+
"sized_type_specifier",
|
|
113
|
+
"auto",
|
|
114
|
+
"decltype",
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def get_child_of_type(node, type_list):
|
|
119
|
+
"""Get first child of node matching any type in type_list"""
|
|
120
|
+
out = list(filter(lambda x: x.type in type_list, node.children))
|
|
121
|
+
if len(out) > 0:
|
|
122
|
+
return out[0]
|
|
123
|
+
else:
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def return_switch_child(node):
|
|
128
|
+
bfs_queue = []
|
|
129
|
+
for child in node.children:
|
|
130
|
+
bfs_queue.append(child)
|
|
131
|
+
while bfs_queue != []:
|
|
132
|
+
top = bfs_queue.pop(0)
|
|
133
|
+
if top.type == "switch_statement":
|
|
134
|
+
return top
|
|
135
|
+
if top.type in statement_types["node_list_type"]:
|
|
136
|
+
return None
|
|
137
|
+
for child in top.children:
|
|
138
|
+
bfs_queue.append(child)
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def return_switch_parent(node, non_control_statement):
|
|
143
|
+
while node.parent is not None and (
|
|
144
|
+
node.parent.type != "class_specifier"
|
|
145
|
+
and node.parent.type != "compound_statement"
|
|
146
|
+
):
|
|
147
|
+
if node.parent.type == "compound_statement" and node.type == "switch_statement":
|
|
148
|
+
return node
|
|
149
|
+
if node.parent.type in non_control_statement:
|
|
150
|
+
return node.parent
|
|
151
|
+
node = node.parent
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def return_switch_parent_statement(node, non_control_statement):
|
|
156
|
+
while node.parent is not None and (
|
|
157
|
+
node.parent.type != "class_specifier"
|
|
158
|
+
and node.parent.type != "compound_statement"
|
|
159
|
+
):
|
|
160
|
+
if node.parent.type in non_control_statement:
|
|
161
|
+
return node.parent
|
|
162
|
+
node = node.parent
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def has_inner_definition(node):
|
|
167
|
+
if node.type in ["struct_specifier", "class_specifier", "union_specifier"]:
|
|
168
|
+
has_body = any(
|
|
169
|
+
child.type == "field_declaration_list" for child in node.named_children
|
|
170
|
+
)
|
|
171
|
+
if has_body:
|
|
172
|
+
return True
|
|
173
|
+
for child in node.children:
|
|
174
|
+
if has_inner_definition(child):
|
|
175
|
+
return True
|
|
176
|
+
return False
|
|
177
|
+
|
|
178
|
+
if node.type in statement_types["definition_types"]:
|
|
179
|
+
return True
|
|
180
|
+
|
|
181
|
+
for child in node.children:
|
|
182
|
+
if has_inner_definition(child):
|
|
183
|
+
return True
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def is_function_declaration(node):
|
|
188
|
+
if node.type != "declaration":
|
|
189
|
+
return False
|
|
190
|
+
|
|
191
|
+
has_function_declarator = False
|
|
192
|
+
has_body = False
|
|
193
|
+
|
|
194
|
+
for child in node.children:
|
|
195
|
+
if child.type == "function_declarator":
|
|
196
|
+
has_function_declarator = True
|
|
197
|
+
if child.type == "compound_statement":
|
|
198
|
+
has_body = True
|
|
199
|
+
|
|
200
|
+
return has_function_declarator and not has_body
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def find_function_definition(node):
|
|
204
|
+
while node.parent is not None:
|
|
205
|
+
if node.parent.type == "function_definition":
|
|
206
|
+
return node.parent
|
|
207
|
+
node = node.parent
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def is_virtual_function(node):
|
|
212
|
+
if node.type not in ["function_definition", "field_declaration"]:
|
|
213
|
+
return False
|
|
214
|
+
|
|
215
|
+
for child in node.children:
|
|
216
|
+
if child.type == "virtual":
|
|
217
|
+
return True
|
|
218
|
+
return False
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def is_pure_virtual_function(node):
|
|
222
|
+
if not is_virtual_function(node):
|
|
223
|
+
return False
|
|
224
|
+
|
|
225
|
+
has_equals = False
|
|
226
|
+
for child in node.children:
|
|
227
|
+
if child.type == "=" or child.text == b"=":
|
|
228
|
+
has_equals = True
|
|
229
|
+
if has_equals and child.type == "number_literal" and child.text == b"0":
|
|
230
|
+
return True
|
|
231
|
+
return False
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def has_field_initializer_list(node):
|
|
235
|
+
if node.type != "function_definition":
|
|
236
|
+
return False
|
|
237
|
+
|
|
238
|
+
for child in node.children:
|
|
239
|
+
if child.type == "field_initializer_list":
|
|
240
|
+
return True
|
|
241
|
+
return False
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def is_deleted_or_defaulted(node):
|
|
245
|
+
if node.type not in ["function_definition", "field_declaration"]:
|
|
246
|
+
return None
|
|
247
|
+
|
|
248
|
+
for child in node.children:
|
|
249
|
+
if child.type == "default_method_clause":
|
|
250
|
+
return "default"
|
|
251
|
+
if child.type == "delete_method_clause":
|
|
252
|
+
return "delete"
|
|
253
|
+
return None
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def is_operator_overload(node):
|
|
257
|
+
if node.type != "function_definition":
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
declarator = node.child_by_field_name("declarator")
|
|
261
|
+
if declarator:
|
|
262
|
+
for child in declarator.children:
|
|
263
|
+
if child.type == "operator_name":
|
|
264
|
+
return True
|
|
265
|
+
return False
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def is_constexpr_function(node):
|
|
269
|
+
if node.type not in ["function_definition", "field_declaration"]:
|
|
270
|
+
return False
|
|
271
|
+
|
|
272
|
+
for child in node.children:
|
|
273
|
+
if child.type == "constexpr":
|
|
274
|
+
return True
|
|
275
|
+
return False
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def is_inline_function(node):
|
|
279
|
+
if node.type not in ["function_definition", "field_declaration"]:
|
|
280
|
+
return False
|
|
281
|
+
|
|
282
|
+
for child in node.children:
|
|
283
|
+
if child.type == "inline":
|
|
284
|
+
return True
|
|
285
|
+
return False
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def has_noexcept_specifier(node):
|
|
289
|
+
if node.type not in ["function_definition", "field_declaration"]:
|
|
290
|
+
return False
|
|
291
|
+
|
|
292
|
+
for child in node.children:
|
|
293
|
+
if child.type == "noexcept":
|
|
294
|
+
return True
|
|
295
|
+
return False
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def get_attributes(node):
|
|
299
|
+
attributes = []
|
|
300
|
+
for child in node.children:
|
|
301
|
+
if child.type == "attribute_specifier":
|
|
302
|
+
for attr_child in child.children:
|
|
303
|
+
if attr_child.type == "attribute":
|
|
304
|
+
for identifier in attr_child.children:
|
|
305
|
+
if identifier.type == "identifier":
|
|
306
|
+
attributes.append(identifier.text.decode("utf-8"))
|
|
307
|
+
return attributes
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def has_auto_type(node):
|
|
311
|
+
if node.type not in ["declaration", "parameter_declaration"]:
|
|
312
|
+
return False
|
|
313
|
+
|
|
314
|
+
for child in node.children:
|
|
315
|
+
if child.type == "auto":
|
|
316
|
+
return True
|
|
317
|
+
if child.type in ["init_declarator", "parameter_declarator"]:
|
|
318
|
+
for subchild in child.children:
|
|
319
|
+
if subchild.type == "auto":
|
|
320
|
+
return True
|
|
321
|
+
return False
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def is_rvalue_reference(node):
|
|
325
|
+
if node.type not in ["declaration", "parameter_declaration", "field_declaration"]:
|
|
326
|
+
return False
|
|
327
|
+
|
|
328
|
+
for child in node.children:
|
|
329
|
+
if child.type == "rvalue_reference_declarator":
|
|
330
|
+
return True
|
|
331
|
+
if hasattr(child, "children"):
|
|
332
|
+
for subchild in child.children:
|
|
333
|
+
if subchild.type == "rvalue_reference_declarator":
|
|
334
|
+
return True
|
|
335
|
+
return False
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def is_template_specialization(node):
|
|
339
|
+
if node.type != "template_declaration":
|
|
340
|
+
return False
|
|
341
|
+
|
|
342
|
+
for child in node.children:
|
|
343
|
+
if child.type == "template_parameter_list":
|
|
344
|
+
named_children = [c for c in child.children if c.is_named]
|
|
345
|
+
if len(named_children) == 0:
|
|
346
|
+
return True
|
|
347
|
+
return False
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def get_signature(node):
|
|
351
|
+
signature = []
|
|
352
|
+
parameter_list = node.child_by_field_name("parameters")
|
|
353
|
+
if parameter_list is None:
|
|
354
|
+
return tuple(signature)
|
|
355
|
+
|
|
356
|
+
def count_array_dimensions(array_node):
|
|
357
|
+
count = 0
|
|
358
|
+
if array_node.type == "array_declarator":
|
|
359
|
+
count = 1
|
|
360
|
+
for subchild in array_node.children:
|
|
361
|
+
if subchild.type == "array_declarator":
|
|
362
|
+
count += count_array_dimensions(subchild)
|
|
363
|
+
return count
|
|
364
|
+
|
|
365
|
+
for param in parameter_list.children:
|
|
366
|
+
if param.type in ["parameter_declaration", "optional_parameter_declaration"]:
|
|
367
|
+
base_type = None
|
|
368
|
+
for child in param.children:
|
|
369
|
+
if child.type in [
|
|
370
|
+
"primitive_type",
|
|
371
|
+
"type_identifier",
|
|
372
|
+
"template_type",
|
|
373
|
+
"qualified_identifier",
|
|
374
|
+
"sized_type_specifier",
|
|
375
|
+
]:
|
|
376
|
+
base_type = child.text.decode("utf-8")
|
|
377
|
+
break
|
|
378
|
+
|
|
379
|
+
if base_type:
|
|
380
|
+
declarator = param.child_by_field_name("declarator")
|
|
381
|
+
if declarator:
|
|
382
|
+
if declarator.type == "reference_declarator":
|
|
383
|
+
declarator_text = declarator.text.decode("utf-8")
|
|
384
|
+
if declarator_text.startswith("&&"):
|
|
385
|
+
signature.append(base_type + "&&")
|
|
386
|
+
else:
|
|
387
|
+
signature.append(base_type + "&")
|
|
388
|
+
elif declarator.type == "pointer_declarator":
|
|
389
|
+
signature.append(base_type + "*")
|
|
390
|
+
elif declarator.type == "array_declarator":
|
|
391
|
+
pointer_count = count_array_dimensions(declarator)
|
|
392
|
+
signature.append(base_type + "*" * pointer_count)
|
|
393
|
+
else:
|
|
394
|
+
signature.append(base_type)
|
|
395
|
+
else:
|
|
396
|
+
signature.append(base_type)
|
|
397
|
+
elif param.type == "...":
|
|
398
|
+
signature.append("...")
|
|
399
|
+
|
|
400
|
+
return tuple(signature)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def get_lambda_body(node):
|
|
404
|
+
bfs_queue = []
|
|
405
|
+
bfs_queue.append(node)
|
|
406
|
+
while bfs_queue != []:
|
|
407
|
+
top = bfs_queue.pop(0)
|
|
408
|
+
if top.type == "lambda_expression":
|
|
409
|
+
return top
|
|
410
|
+
for child in top.children:
|
|
411
|
+
bfs_queue.append(child)
|
|
412
|
+
return None
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def get_all_lambda_body(node):
|
|
416
|
+
bfs_queue = []
|
|
417
|
+
output = []
|
|
418
|
+
bfs_queue.append(node)
|
|
419
|
+
while bfs_queue != []:
|
|
420
|
+
top = bfs_queue.pop(0)
|
|
421
|
+
if top.type == "lambda_expression":
|
|
422
|
+
output.append(top)
|
|
423
|
+
for child in top.children:
|
|
424
|
+
if (
|
|
425
|
+
child.type == "lambda_expression"
|
|
426
|
+
or child.type not in statement_types["node_list_type"]
|
|
427
|
+
):
|
|
428
|
+
bfs_queue.append(child)
|
|
429
|
+
return output
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def check_lambda(node):
|
|
433
|
+
if get_lambda_body(node) is None:
|
|
434
|
+
return False
|
|
435
|
+
else:
|
|
436
|
+
initial_node = node
|
|
437
|
+
lambda_node = get_lambda_body(node)
|
|
438
|
+
parent_node = lambda_node.parent
|
|
439
|
+
while parent_node is not None:
|
|
440
|
+
if parent_node.type in statement_types["node_list_type"]:
|
|
441
|
+
if parent_node == initial_node:
|
|
442
|
+
return True
|
|
443
|
+
else:
|
|
444
|
+
return False
|
|
445
|
+
parent_node = parent_node.parent
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def get_class_name(node, index):
|
|
449
|
+
"""Returns the class name or namespace when a function definition or method is passed to it.
|
|
450
|
+
|
|
451
|
+
For namespaces, builds the fully qualified name (e.g., "Outer::Inner").
|
|
452
|
+
Returns tuple: (index, [name]) where name can be class, struct, or namespace.
|
|
453
|
+
"""
|
|
454
|
+
type_identifiers = ["type_identifier", "template_type", "qualified_identifier"]
|
|
455
|
+
|
|
456
|
+
namespace_parts = []
|
|
457
|
+
temp_node = node
|
|
458
|
+
while temp_node is not None:
|
|
459
|
+
if temp_node.type == "namespace_definition":
|
|
460
|
+
namespace_name_node = temp_node.child_by_field_name("name")
|
|
461
|
+
if namespace_name_node:
|
|
462
|
+
namespace_name = namespace_name_node.text.decode("UTF-8")
|
|
463
|
+
namespace_parts.insert(0, namespace_name)
|
|
464
|
+
else:
|
|
465
|
+
pass
|
|
466
|
+
temp_node = temp_node.parent
|
|
467
|
+
|
|
468
|
+
if namespace_parts:
|
|
469
|
+
qualified_namespace = "::".join(namespace_parts)
|
|
470
|
+
temp_node = node
|
|
471
|
+
while temp_node is not None:
|
|
472
|
+
if temp_node.type == "namespace_definition":
|
|
473
|
+
namespace_index = index.get(
|
|
474
|
+
(temp_node.start_point, temp_node.end_point, temp_node.type)
|
|
475
|
+
)
|
|
476
|
+
if namespace_index is not None:
|
|
477
|
+
return namespace_index, [qualified_namespace]
|
|
478
|
+
temp_node = temp_node.parent
|
|
479
|
+
|
|
480
|
+
while node is not None:
|
|
481
|
+
if (
|
|
482
|
+
node.type == "field_declaration_list"
|
|
483
|
+
and node.parent.type == "class_specifier"
|
|
484
|
+
):
|
|
485
|
+
node = node.parent
|
|
486
|
+
class_index = index[(node.start_point, node.end_point, node.type)]
|
|
487
|
+
class_name_node = get_child_of_type(node, ["type_identifier"])
|
|
488
|
+
if class_name_node:
|
|
489
|
+
class_name = [class_name_node.text.decode("UTF-8")]
|
|
490
|
+
else:
|
|
491
|
+
class_name = ["anonymous_class"]
|
|
492
|
+
|
|
493
|
+
base_list = node.child_by_field_name("base_class_clause")
|
|
494
|
+
if base_list is not None:
|
|
495
|
+
for child in base_list.children:
|
|
496
|
+
if child.type in type_identifiers:
|
|
497
|
+
class_name.append(child.text.decode("UTF-8"))
|
|
498
|
+
|
|
499
|
+
return class_index, class_name
|
|
500
|
+
|
|
501
|
+
elif (
|
|
502
|
+
node.type == "field_declaration_list"
|
|
503
|
+
and node.parent.type == "struct_specifier"
|
|
504
|
+
):
|
|
505
|
+
node = node.parent
|
|
506
|
+
class_index = index[(node.start_point, node.end_point, node.type)]
|
|
507
|
+
class_name_node = get_child_of_type(node, ["type_identifier"])
|
|
508
|
+
if class_name_node:
|
|
509
|
+
class_name = [class_name_node.text.decode("UTF-8")]
|
|
510
|
+
else:
|
|
511
|
+
class_name = ["anonymous_struct"]
|
|
512
|
+
|
|
513
|
+
return class_index, class_name
|
|
514
|
+
|
|
515
|
+
node = node.parent
|
|
516
|
+
return None
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
def evaluate_preprocessor_condition(condition_text, macro_definitions):
|
|
520
|
+
"""
|
|
521
|
+
Evaluate a preprocessor condition based on defined macros.
|
|
522
|
+
Returns True if the condition is satisfied, False otherwise, None if cannot evaluate.
|
|
523
|
+
|
|
524
|
+
Supports:
|
|
525
|
+
- #ifdef MACRO
|
|
526
|
+
- #ifndef MACRO
|
|
527
|
+
- #if MACRO == VALUE
|
|
528
|
+
- #if defined(MACRO)
|
|
529
|
+
- Simple comparisons and logic
|
|
530
|
+
"""
|
|
531
|
+
import re
|
|
532
|
+
|
|
533
|
+
if not any(
|
|
534
|
+
op in condition_text for op in ["==", "!=", ">", "<", "&&", "||", "defined"]
|
|
535
|
+
):
|
|
536
|
+
identifier = condition_text.strip()
|
|
537
|
+
return identifier in macro_definitions
|
|
538
|
+
|
|
539
|
+
defined_pattern = r"defined\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)"
|
|
540
|
+
condition_text = re.sub(
|
|
541
|
+
defined_pattern,
|
|
542
|
+
lambda m: "1" if m.group(1) in macro_definitions else "0",
|
|
543
|
+
condition_text,
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
for macro, value in macro_definitions.items():
|
|
547
|
+
condition_text = re.sub(r"\b" + macro + r"\b", str(value), condition_text)
|
|
548
|
+
|
|
549
|
+
try:
|
|
550
|
+
if re.match(r"^[\d\s+\-*/<>=!&|()]+$", condition_text):
|
|
551
|
+
result = eval(condition_text)
|
|
552
|
+
return bool(result)
|
|
553
|
+
except:
|
|
554
|
+
pass
|
|
555
|
+
|
|
556
|
+
return None
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def get_nodes(
|
|
560
|
+
root_node=None,
|
|
561
|
+
node_list={},
|
|
562
|
+
graph_node_list=[],
|
|
563
|
+
index={},
|
|
564
|
+
records={},
|
|
565
|
+
macro_definitions=None,
|
|
566
|
+
):
|
|
567
|
+
"""
|
|
568
|
+
Returns statement level nodes recursively from the concrete syntax tree passed to it.
|
|
569
|
+
Uses records to maintain required supplementary information.
|
|
570
|
+
node_list maintains an intermediate representation and graph_node_list returns the final list.
|
|
571
|
+
|
|
572
|
+
Args:
|
|
573
|
+
macro_definitions: Dictionary of defined macros {name: value} for preprocessor evaluation
|
|
574
|
+
"""
|
|
575
|
+
import os
|
|
576
|
+
|
|
577
|
+
if macro_definitions is None:
|
|
578
|
+
macro_definitions = {}
|
|
579
|
+
|
|
580
|
+
if root_node.type == "catch_clause":
|
|
581
|
+
node_list[(root_node.start_point, root_node.end_point, root_node.type)] = (
|
|
582
|
+
root_node
|
|
583
|
+
)
|
|
584
|
+
catch_parameter = list(
|
|
585
|
+
filter(lambda child: child.type == "parameter_list", root_node.children)
|
|
586
|
+
)
|
|
587
|
+
if catch_parameter:
|
|
588
|
+
param_text = catch_parameter[0].text.decode("UTF-8")
|
|
589
|
+
if param_text.startswith("(") and param_text.endswith(")"):
|
|
590
|
+
param_text = param_text[1:-1]
|
|
591
|
+
|
|
592
|
+
if param_text.strip() == "...":
|
|
593
|
+
label = "catch (...)"
|
|
594
|
+
else:
|
|
595
|
+
label = "catch (" + param_text + ")"
|
|
596
|
+
else:
|
|
597
|
+
label = "catch (...)"
|
|
598
|
+
type_label = "catch"
|
|
599
|
+
graph_node_list.append(
|
|
600
|
+
(
|
|
601
|
+
index[(root_node.start_point, root_node.end_point, root_node.type)],
|
|
602
|
+
root_node.start_point[0],
|
|
603
|
+
label,
|
|
604
|
+
type_label,
|
|
605
|
+
)
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
elif (
|
|
609
|
+
root_node.type == "parenthesized_expression"
|
|
610
|
+
and root_node.parent is not None
|
|
611
|
+
and root_node.parent.type == "do_statement"
|
|
612
|
+
):
|
|
613
|
+
label = "while" + root_node.text.decode("UTF-8")
|
|
614
|
+
type_label = "while"
|
|
615
|
+
node_list[(root_node.start_point, root_node.end_point, root_node.type)] = (
|
|
616
|
+
root_node
|
|
617
|
+
)
|
|
618
|
+
graph_node_list.append(
|
|
619
|
+
(
|
|
620
|
+
index[(root_node.start_point, root_node.end_point, root_node.type)],
|
|
621
|
+
root_node.start_point[0],
|
|
622
|
+
label,
|
|
623
|
+
type_label,
|
|
624
|
+
)
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
elif root_node.type in [
|
|
628
|
+
"preproc_include",
|
|
629
|
+
"preproc_def",
|
|
630
|
+
"preproc_function_def",
|
|
631
|
+
"preproc_call",
|
|
632
|
+
"preproc_if",
|
|
633
|
+
"preproc_ifdef",
|
|
634
|
+
"preproc_elif",
|
|
635
|
+
"preproc_else",
|
|
636
|
+
]:
|
|
637
|
+
|
|
638
|
+
if root_node.type == "preproc_def":
|
|
639
|
+
text = root_node.text.decode("UTF-8")
|
|
640
|
+
parts = text.split(None, 2)
|
|
641
|
+
if len(parts) >= 2:
|
|
642
|
+
macro_name = parts[1]
|
|
643
|
+
macro_value = parts[2].strip() if len(parts) > 2 else "1"
|
|
644
|
+
macro_definitions[macro_name] = macro_value
|
|
645
|
+
if os.environ.get("DEBUG_PREPROC"):
|
|
646
|
+
print(f"[DEFINE] {macro_name} = {macro_value}")
|
|
647
|
+
|
|
648
|
+
elif root_node.type in statement_types["node_list_type"]:
|
|
649
|
+
if root_node.type == "field_declaration":
|
|
650
|
+
pass
|
|
651
|
+
|
|
652
|
+
elif root_node.type in ["struct_specifier", "class_specifier"]:
|
|
653
|
+
parent = root_node.parent
|
|
654
|
+
should_skip = False
|
|
655
|
+
|
|
656
|
+
if parent and parent.type in ["translation_unit", "declaration_list"]:
|
|
657
|
+
if parent.type == "declaration_list":
|
|
658
|
+
grandparent = parent.parent if parent else None
|
|
659
|
+
if grandparent and grandparent.type in [
|
|
660
|
+
"namespace_definition",
|
|
661
|
+
"translation_unit",
|
|
662
|
+
]:
|
|
663
|
+
should_skip = True
|
|
664
|
+
else:
|
|
665
|
+
should_skip = True
|
|
666
|
+
|
|
667
|
+
elif parent and parent.type == "field_declaration_list":
|
|
668
|
+
should_skip = True
|
|
669
|
+
|
|
670
|
+
if should_skip:
|
|
671
|
+
pass
|
|
672
|
+
elif is_function_declaration(root_node):
|
|
673
|
+
pass
|
|
674
|
+
elif root_node.type == "template_declaration":
|
|
675
|
+
pass
|
|
676
|
+
elif root_node.type == "access_specifier":
|
|
677
|
+
pass
|
|
678
|
+
elif root_node.parent and root_node.parent.type == "attributed_statement":
|
|
679
|
+
pass
|
|
680
|
+
elif root_node.type == "lambda_expression":
|
|
681
|
+
parent = root_node.parent
|
|
682
|
+
while parent and parent.type not in statement_types["node_list_type"]:
|
|
683
|
+
parent = parent.parent
|
|
684
|
+
|
|
685
|
+
if parent and parent.type != "lambda_expression":
|
|
686
|
+
node_list[
|
|
687
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
688
|
+
] = root_node
|
|
689
|
+
else:
|
|
690
|
+
node_list[
|
|
691
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
692
|
+
] = root_node
|
|
693
|
+
label = root_node.text.decode("UTF-8")
|
|
694
|
+
type_label = "expression_statement"
|
|
695
|
+
try:
|
|
696
|
+
if "{" in label:
|
|
697
|
+
label = label.split("{")[0] + label.split("}")[-1]
|
|
698
|
+
else:
|
|
699
|
+
label = root_node.text.decode("utf-8")
|
|
700
|
+
except:
|
|
701
|
+
pass
|
|
702
|
+
graph_node_list.append(
|
|
703
|
+
(
|
|
704
|
+
index[
|
|
705
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
706
|
+
],
|
|
707
|
+
root_node.start_point[0],
|
|
708
|
+
label,
|
|
709
|
+
type_label,
|
|
710
|
+
)
|
|
711
|
+
)
|
|
712
|
+
elif (
|
|
713
|
+
root_node.type in statement_types["inner_node_type"]
|
|
714
|
+
and root_node.parent is not None
|
|
715
|
+
and root_node.parent.type in statement_types["outer_node_type"]
|
|
716
|
+
and root_node.parent.child_by_field_name("body") != root_node
|
|
717
|
+
):
|
|
718
|
+
pass
|
|
719
|
+
elif (
|
|
720
|
+
root_node.type in statement_types["inner_node_type"]
|
|
721
|
+
and return_switch_child(root_node) is not None
|
|
722
|
+
):
|
|
723
|
+
switch_child = return_switch_child(root_node)
|
|
724
|
+
child_index = index[
|
|
725
|
+
(switch_child.start_point, switch_child.end_point, switch_child.type)
|
|
726
|
+
]
|
|
727
|
+
current_index = index[
|
|
728
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
729
|
+
]
|
|
730
|
+
records["switch_child_map"][current_index] = child_index
|
|
731
|
+
else:
|
|
732
|
+
node_list[(root_node.start_point, root_node.end_point, root_node.type)] = (
|
|
733
|
+
root_node
|
|
734
|
+
)
|
|
735
|
+
label = root_node.text.decode("UTF-8")
|
|
736
|
+
type_label = "expression_statement"
|
|
737
|
+
|
|
738
|
+
if (
|
|
739
|
+
check_lambda(root_node)
|
|
740
|
+
and root_node.type not in statement_types["definition_types"]
|
|
741
|
+
):
|
|
742
|
+
raw_label = root_node.text.decode("utf-8")
|
|
743
|
+
label = ""
|
|
744
|
+
for lambda_expression in get_all_lambda_body(root_node):
|
|
745
|
+
split_label = raw_label.split(
|
|
746
|
+
lambda_expression.text.decode("utf-8"), 2
|
|
747
|
+
)
|
|
748
|
+
raw_label = split_label[0]
|
|
749
|
+
if len(split_label) > 1:
|
|
750
|
+
label = split_label[1] + label
|
|
751
|
+
lambda_node = (
|
|
752
|
+
lambda_expression.start_point,
|
|
753
|
+
lambda_expression.end_point,
|
|
754
|
+
lambda_expression.type,
|
|
755
|
+
)
|
|
756
|
+
records["lambda_map"][lambda_node] = root_node
|
|
757
|
+
label = raw_label + label
|
|
758
|
+
|
|
759
|
+
if root_node.type == "function_definition":
|
|
760
|
+
label = ""
|
|
761
|
+
declarator = root_node.child_by_field_name("declarator")
|
|
762
|
+
|
|
763
|
+
is_virtual = is_virtual_function(root_node)
|
|
764
|
+
is_pure_virtual = is_pure_virtual_function(root_node)
|
|
765
|
+
is_operator = is_operator_overload(root_node)
|
|
766
|
+
deleted_or_defaulted = is_deleted_or_defaulted(root_node)
|
|
767
|
+
has_initializers = has_field_initializer_list(root_node)
|
|
768
|
+
|
|
769
|
+
is_constexpr = is_constexpr_function(root_node)
|
|
770
|
+
is_inline = is_inline_function(root_node)
|
|
771
|
+
has_noexcept = has_noexcept_specifier(root_node)
|
|
772
|
+
attributes = get_attributes(root_node)
|
|
773
|
+
|
|
774
|
+
if declarator:
|
|
775
|
+
for child in root_node.children:
|
|
776
|
+
if child.type not in [
|
|
777
|
+
"compound_statement",
|
|
778
|
+
"function_body",
|
|
779
|
+
"field_initializer_list",
|
|
780
|
+
]:
|
|
781
|
+
label = label + " " + child.text.decode("utf-8")
|
|
782
|
+
|
|
783
|
+
function_name_node = None
|
|
784
|
+
if declarator:
|
|
785
|
+
if declarator.type == "function_declarator":
|
|
786
|
+
operator_name_node = None
|
|
787
|
+
for child in declarator.children:
|
|
788
|
+
if child.type == "operator_name":
|
|
789
|
+
operator_name_node = child
|
|
790
|
+
break
|
|
791
|
+
|
|
792
|
+
if operator_name_node:
|
|
793
|
+
function_name_node = operator_name_node
|
|
794
|
+
else:
|
|
795
|
+
function_name_node = declarator.child_by_field_name(
|
|
796
|
+
"declarator"
|
|
797
|
+
)
|
|
798
|
+
elif (
|
|
799
|
+
declarator.type == "pointer_declarator"
|
|
800
|
+
or declarator.type == "reference_declarator"
|
|
801
|
+
):
|
|
802
|
+
nested = declarator
|
|
803
|
+
while nested and nested.type in [
|
|
804
|
+
"pointer_declarator",
|
|
805
|
+
"reference_declarator",
|
|
806
|
+
]:
|
|
807
|
+
found_nested = None
|
|
808
|
+
for child in nested.children:
|
|
809
|
+
if child.type in [
|
|
810
|
+
"function_declarator",
|
|
811
|
+
"pointer_declarator",
|
|
812
|
+
"reference_declarator",
|
|
813
|
+
]:
|
|
814
|
+
found_nested = child
|
|
815
|
+
break
|
|
816
|
+
nested = found_nested
|
|
817
|
+
|
|
818
|
+
if nested and nested.type == "function_declarator":
|
|
819
|
+
operator_name_node = None
|
|
820
|
+
for child in nested.children:
|
|
821
|
+
if child.type == "operator_name":
|
|
822
|
+
operator_name_node = child
|
|
823
|
+
break
|
|
824
|
+
|
|
825
|
+
if operator_name_node:
|
|
826
|
+
function_name_node = operator_name_node
|
|
827
|
+
else:
|
|
828
|
+
function_name_node = nested.child_by_field_name(
|
|
829
|
+
"declarator"
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
if function_name_node:
|
|
833
|
+
function_name = function_name_node.text.decode("UTF-8")
|
|
834
|
+
else:
|
|
835
|
+
function_name = "unknown"
|
|
836
|
+
|
|
837
|
+
function_index = index[
|
|
838
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
839
|
+
]
|
|
840
|
+
type_label = root_node.type
|
|
841
|
+
|
|
842
|
+
try:
|
|
843
|
+
sig_node = declarator
|
|
844
|
+
if declarator and declarator.type in [
|
|
845
|
+
"pointer_declarator",
|
|
846
|
+
"reference_declarator",
|
|
847
|
+
]:
|
|
848
|
+
nested = declarator
|
|
849
|
+
while nested and nested.type in [
|
|
850
|
+
"pointer_declarator",
|
|
851
|
+
"reference_declarator",
|
|
852
|
+
]:
|
|
853
|
+
found_nested = None
|
|
854
|
+
for child in nested.children:
|
|
855
|
+
if child.type == "function_declarator":
|
|
856
|
+
sig_node = child
|
|
857
|
+
break
|
|
858
|
+
elif child.type in [
|
|
859
|
+
"pointer_declarator",
|
|
860
|
+
"reference_declarator",
|
|
861
|
+
]:
|
|
862
|
+
found_nested = child
|
|
863
|
+
break
|
|
864
|
+
if sig_node and sig_node.type == "function_declarator":
|
|
865
|
+
break
|
|
866
|
+
nested = found_nested
|
|
867
|
+
|
|
868
|
+
signature = get_signature(
|
|
869
|
+
sig_node
|
|
870
|
+
if sig_node and sig_node.type == "function_declarator"
|
|
871
|
+
else root_node
|
|
872
|
+
)
|
|
873
|
+
class_info = get_class_name(root_node, index)
|
|
874
|
+
|
|
875
|
+
if class_info:
|
|
876
|
+
class_index, class_name_list = class_info
|
|
877
|
+
if function_name == "main":
|
|
878
|
+
records["main_function"] = function_index
|
|
879
|
+
records["main_class"] = class_index
|
|
880
|
+
|
|
881
|
+
for class_name in class_name_list:
|
|
882
|
+
key = ((class_name, function_name), signature)
|
|
883
|
+
records["function_list"][key] = function_index
|
|
884
|
+
|
|
885
|
+
if len(signature) > 0 and signature[-1] == "...":
|
|
886
|
+
records["variadic_functions"][key] = True
|
|
887
|
+
|
|
888
|
+
return_type_node = root_node.child_by_field_name("type")
|
|
889
|
+
if return_type_node:
|
|
890
|
+
return_type = return_type_node.text.decode("UTF-8")
|
|
891
|
+
else:
|
|
892
|
+
return_type = "void"
|
|
893
|
+
records["return_type"][key] = return_type
|
|
894
|
+
|
|
895
|
+
if is_virtual or is_pure_virtual:
|
|
896
|
+
records["virtual_functions"][function_index] = {
|
|
897
|
+
"is_virtual": is_virtual,
|
|
898
|
+
"is_pure_virtual": is_pure_virtual,
|
|
899
|
+
}
|
|
900
|
+
if is_operator:
|
|
901
|
+
records["operator_overloads"][
|
|
902
|
+
function_index
|
|
903
|
+
] = function_name
|
|
904
|
+
if deleted_or_defaulted:
|
|
905
|
+
records["special_functions"][
|
|
906
|
+
function_index
|
|
907
|
+
] = deleted_or_defaulted
|
|
908
|
+
if has_initializers:
|
|
909
|
+
records["functions_with_initializers"][
|
|
910
|
+
function_index
|
|
911
|
+
] = True
|
|
912
|
+
|
|
913
|
+
if is_constexpr:
|
|
914
|
+
records["constexpr_functions"][function_index] = True
|
|
915
|
+
if is_inline:
|
|
916
|
+
records["inline_functions"][function_index] = True
|
|
917
|
+
if has_noexcept:
|
|
918
|
+
records["noexcept_functions"][function_index] = True
|
|
919
|
+
if attributes:
|
|
920
|
+
records["attributed_functions"][
|
|
921
|
+
function_index
|
|
922
|
+
] = attributes
|
|
923
|
+
else:
|
|
924
|
+
if function_name == "main":
|
|
925
|
+
records["main_function"] = function_index
|
|
926
|
+
|
|
927
|
+
records["function_list"][
|
|
928
|
+
((None, function_name), signature)
|
|
929
|
+
] = function_index
|
|
930
|
+
return_type_node = root_node.child_by_field_name("type")
|
|
931
|
+
if return_type_node:
|
|
932
|
+
return_type = return_type_node.text.decode("UTF-8")
|
|
933
|
+
else:
|
|
934
|
+
return_type = "void"
|
|
935
|
+
records["return_type"][
|
|
936
|
+
((None, function_name), signature)
|
|
937
|
+
] = return_type
|
|
938
|
+
except:
|
|
939
|
+
pass
|
|
940
|
+
|
|
941
|
+
graph_node_list.append(
|
|
942
|
+
(function_index, root_node.start_point[0], label, type_label)
|
|
943
|
+
)
|
|
944
|
+
|
|
945
|
+
elif (
|
|
946
|
+
root_node.type == "class_specifier"
|
|
947
|
+
or root_node.type == "struct_specifier"
|
|
948
|
+
):
|
|
949
|
+
class_name_node = get_child_of_type(root_node, ["type_identifier"])
|
|
950
|
+
if class_name_node:
|
|
951
|
+
class_name = class_name_node.text.decode("UTF-8")
|
|
952
|
+
label = f"{root_node.type.replace('_specifier', '')} {class_name}"
|
|
953
|
+
else:
|
|
954
|
+
label = f"anonymous_{root_node.type.replace('_specifier', '')}"
|
|
955
|
+
class_name = label
|
|
956
|
+
|
|
957
|
+
type_label = root_node.type
|
|
958
|
+
class_index = index[
|
|
959
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
960
|
+
]
|
|
961
|
+
records["class_list"][class_name] = class_index
|
|
962
|
+
|
|
963
|
+
base_list = root_node.child_by_field_name("base_class_clause")
|
|
964
|
+
if base_list is not None:
|
|
965
|
+
for child in base_list.children:
|
|
966
|
+
if child.type in [
|
|
967
|
+
"type_identifier",
|
|
968
|
+
"template_type",
|
|
969
|
+
"qualified_identifier",
|
|
970
|
+
]:
|
|
971
|
+
parent_name = child.text.decode("UTF-8")
|
|
972
|
+
try:
|
|
973
|
+
records["extends"][class_name].append(parent_name)
|
|
974
|
+
except:
|
|
975
|
+
records["extends"][class_name] = [parent_name]
|
|
976
|
+
|
|
977
|
+
elif root_node.type == "namespace_definition":
|
|
978
|
+
namespace_name_node = root_node.child_by_field_name("name")
|
|
979
|
+
if namespace_name_node:
|
|
980
|
+
namespace_name = namespace_name_node.text.decode("UTF-8")
|
|
981
|
+
label = f"namespace {namespace_name}"
|
|
982
|
+
else:
|
|
983
|
+
label = "anonymous namespace"
|
|
984
|
+
type_label = "namespace_definition"
|
|
985
|
+
|
|
986
|
+
elif root_node.type == "if_statement":
|
|
987
|
+
condition = root_node.child_by_field_name("condition")
|
|
988
|
+
if condition:
|
|
989
|
+
label = "if(" + condition.text.decode("UTF-8") + ")"
|
|
990
|
+
else:
|
|
991
|
+
label = "if"
|
|
992
|
+
type_label = "if"
|
|
993
|
+
|
|
994
|
+
elif root_node.type == "for_statement":
|
|
995
|
+
try:
|
|
996
|
+
init = root_node.child_by_field_name("initializer")
|
|
997
|
+
init_text = init.text.decode("UTF-8") if init else ""
|
|
998
|
+
if init_text and not init_text.endswith(";"):
|
|
999
|
+
init_text = init_text + ";"
|
|
1000
|
+
except:
|
|
1001
|
+
init_text = ""
|
|
1002
|
+
try:
|
|
1003
|
+
condition = root_node.child_by_field_name("condition")
|
|
1004
|
+
condition_text = condition.text.decode("UTF-8") if condition else ""
|
|
1005
|
+
except:
|
|
1006
|
+
condition_text = ""
|
|
1007
|
+
try:
|
|
1008
|
+
update = root_node.child_by_field_name("update")
|
|
1009
|
+
update_text = update.text.decode("UTF-8") if update else ""
|
|
1010
|
+
except:
|
|
1011
|
+
update_text = ""
|
|
1012
|
+
label = "for(" + init_text + condition_text + ";" + update_text + ")"
|
|
1013
|
+
type_label = "for"
|
|
1014
|
+
|
|
1015
|
+
elif root_node.type == "for_range_loop":
|
|
1016
|
+
try:
|
|
1017
|
+
declarator = root_node.child_by_field_name("declarator")
|
|
1018
|
+
declarator_text = (
|
|
1019
|
+
declarator.text.decode("UTF-8") if declarator else ""
|
|
1020
|
+
)
|
|
1021
|
+
range_expr = root_node.child_by_field_name("right")
|
|
1022
|
+
range_text = range_expr.text.decode("UTF-8") if range_expr else ""
|
|
1023
|
+
label = f"for({declarator_text} : {range_text})"
|
|
1024
|
+
except:
|
|
1025
|
+
label = "for(range)"
|
|
1026
|
+
type_label = "for"
|
|
1027
|
+
|
|
1028
|
+
elif root_node.type == "while_statement":
|
|
1029
|
+
condition = root_node.child_by_field_name("condition")
|
|
1030
|
+
if condition:
|
|
1031
|
+
label = "while(" + condition.text.decode("UTF-8") + ")"
|
|
1032
|
+
else:
|
|
1033
|
+
label = "while"
|
|
1034
|
+
type_label = "while"
|
|
1035
|
+
|
|
1036
|
+
elif root_node.type == "do_statement":
|
|
1037
|
+
label = "do"
|
|
1038
|
+
type_label = "do"
|
|
1039
|
+
|
|
1040
|
+
elif root_node.type == "switch_statement":
|
|
1041
|
+
condition = root_node.child_by_field_name("condition")
|
|
1042
|
+
if condition:
|
|
1043
|
+
label = "switch(" + condition.text.decode("UTF-8") + ")"
|
|
1044
|
+
else:
|
|
1045
|
+
label = "switch"
|
|
1046
|
+
type_label = "switch"
|
|
1047
|
+
|
|
1048
|
+
elif root_node.type == "case_statement":
|
|
1049
|
+
value = root_node.child_by_field_name("value")
|
|
1050
|
+
if value:
|
|
1051
|
+
label = "case " + value.text.decode("UTF-8") + ":"
|
|
1052
|
+
else:
|
|
1053
|
+
label = "default:"
|
|
1054
|
+
type_label = "case"
|
|
1055
|
+
|
|
1056
|
+
elif root_node.type == "try_statement":
|
|
1057
|
+
label = "try"
|
|
1058
|
+
type_label = "try"
|
|
1059
|
+
|
|
1060
|
+
elif root_node.type == "labeled_statement":
|
|
1061
|
+
label_node = root_node.child_by_field_name("label")
|
|
1062
|
+
if label_node:
|
|
1063
|
+
label = label_node.text.decode("UTF-8") + ":"
|
|
1064
|
+
records["label_statement_map"][label] = (
|
|
1065
|
+
root_node.start_point,
|
|
1066
|
+
root_node.end_point,
|
|
1067
|
+
root_node.type,
|
|
1068
|
+
)
|
|
1069
|
+
else:
|
|
1070
|
+
label = "label:"
|
|
1071
|
+
type_label = "label"
|
|
1072
|
+
|
|
1073
|
+
elif root_node.type == "return_statement":
|
|
1074
|
+
if has_inner_definition(root_node):
|
|
1075
|
+
label = "return"
|
|
1076
|
+
else:
|
|
1077
|
+
label = root_node.text.decode("UTF-8")
|
|
1078
|
+
type_label = "return"
|
|
1079
|
+
|
|
1080
|
+
elif root_node.type == "enum_specifier":
|
|
1081
|
+
enum_name_node = get_child_of_type(root_node, ["type_identifier"])
|
|
1082
|
+
is_scoped = "class" in [child.type for child in root_node.children]
|
|
1083
|
+
if enum_name_node:
|
|
1084
|
+
enum_name = enum_name_node.text.decode("UTF-8")
|
|
1085
|
+
if is_scoped:
|
|
1086
|
+
label = f"enum class {enum_name}"
|
|
1087
|
+
else:
|
|
1088
|
+
label = f"enum {enum_name}"
|
|
1089
|
+
else:
|
|
1090
|
+
label = "enum (anonymous)"
|
|
1091
|
+
type_label = "enum"
|
|
1092
|
+
|
|
1093
|
+
enum_index = index[
|
|
1094
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
1095
|
+
]
|
|
1096
|
+
if enum_name_node:
|
|
1097
|
+
records["enum_list"][enum_name] = enum_index
|
|
1098
|
+
|
|
1099
|
+
elif root_node.type == "union_specifier":
|
|
1100
|
+
union_name_node = get_child_of_type(root_node, ["type_identifier"])
|
|
1101
|
+
if union_name_node:
|
|
1102
|
+
union_name = union_name_node.text.decode("UTF-8")
|
|
1103
|
+
label = f"union {union_name}"
|
|
1104
|
+
else:
|
|
1105
|
+
label = "union (anonymous)"
|
|
1106
|
+
type_label = "union"
|
|
1107
|
+
|
|
1108
|
+
union_index = index[
|
|
1109
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
1110
|
+
]
|
|
1111
|
+
if union_name_node:
|
|
1112
|
+
records["union_list"][union_name] = union_index
|
|
1113
|
+
|
|
1114
|
+
elif root_node.type == "type_definition":
|
|
1115
|
+
type_identifier_node = get_child_of_type(root_node, ["type_identifier"])
|
|
1116
|
+
if type_identifier_node:
|
|
1117
|
+
typedef_name = type_identifier_node.text.decode("UTF-8")
|
|
1118
|
+
label = f"typedef {typedef_name}"
|
|
1119
|
+
else:
|
|
1120
|
+
label = "typedef"
|
|
1121
|
+
type_label = "typedef"
|
|
1122
|
+
|
|
1123
|
+
typedef_index = index[
|
|
1124
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
1125
|
+
]
|
|
1126
|
+
if type_identifier_node:
|
|
1127
|
+
records["typedef_list"][typedef_name] = typedef_index
|
|
1128
|
+
|
|
1129
|
+
elif root_node.type == "friend_declaration":
|
|
1130
|
+
label = (
|
|
1131
|
+
"friend "
|
|
1132
|
+
+ root_node.text.decode("UTF-8").replace("friend", "").strip()
|
|
1133
|
+
)
|
|
1134
|
+
if len(label) > 80:
|
|
1135
|
+
label = label[:77] + "..."
|
|
1136
|
+
type_label = "friend"
|
|
1137
|
+
|
|
1138
|
+
elif root_node.type == "static_assert_declaration":
|
|
1139
|
+
label = root_node.text.decode("UTF-8")
|
|
1140
|
+
if len(label) > 80:
|
|
1141
|
+
label = label[:77] + "..."
|
|
1142
|
+
type_label = "static_assert"
|
|
1143
|
+
|
|
1144
|
+
elif root_node.type == "namespace_alias_definition":
|
|
1145
|
+
label = root_node.text.decode("UTF-8")
|
|
1146
|
+
if len(label) > 80:
|
|
1147
|
+
label = label[:77] + "..."
|
|
1148
|
+
type_label = "namespace_alias"
|
|
1149
|
+
|
|
1150
|
+
elif root_node.type == "using_declaration":
|
|
1151
|
+
label = root_node.text.decode("UTF-8")
|
|
1152
|
+
if len(label) > 80:
|
|
1153
|
+
label = label[:77] + "..."
|
|
1154
|
+
type_label = "using"
|
|
1155
|
+
|
|
1156
|
+
elif root_node.type == "attributed_statement":
|
|
1157
|
+
attributes = []
|
|
1158
|
+
for child in root_node.children:
|
|
1159
|
+
if child.type == "attribute_declaration":
|
|
1160
|
+
for attr_child in child.named_children:
|
|
1161
|
+
if attr_child.type == "attribute":
|
|
1162
|
+
attr_text = attr_child.text.decode("utf-8")
|
|
1163
|
+
attr_name = attr_text.split("(")[0].strip()
|
|
1164
|
+
attributes.append(attr_name)
|
|
1165
|
+
|
|
1166
|
+
label = root_node.text.decode("UTF-8")
|
|
1167
|
+
if len(label) > 80:
|
|
1168
|
+
label = label[:77] + "..."
|
|
1169
|
+
type_label = "expression_statement"
|
|
1170
|
+
|
|
1171
|
+
elif root_node.type == "new_expression":
|
|
1172
|
+
label = root_node.text.decode("UTF-8")
|
|
1173
|
+
if len(label) > 80:
|
|
1174
|
+
label = label[:77] + "..."
|
|
1175
|
+
type_label = "new"
|
|
1176
|
+
|
|
1177
|
+
excluded_from_graph = {
|
|
1178
|
+
"function_definition",
|
|
1179
|
+
"preproc_include",
|
|
1180
|
+
"preproc_def",
|
|
1181
|
+
"preproc_function_def",
|
|
1182
|
+
"preproc_call",
|
|
1183
|
+
"preproc_if",
|
|
1184
|
+
"preproc_ifdef",
|
|
1185
|
+
"preproc_elif",
|
|
1186
|
+
"preproc_else",
|
|
1187
|
+
"using_declaration",
|
|
1188
|
+
"alias_declaration",
|
|
1189
|
+
"namespace_alias_definition",
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
if root_node.type not in excluded_from_graph:
|
|
1193
|
+
graph_node_list.append(
|
|
1194
|
+
(
|
|
1195
|
+
index[
|
|
1196
|
+
(root_node.start_point, root_node.end_point, root_node.type)
|
|
1197
|
+
],
|
|
1198
|
+
root_node.start_point[0],
|
|
1199
|
+
label,
|
|
1200
|
+
type_label,
|
|
1201
|
+
)
|
|
1202
|
+
)
|
|
1203
|
+
|
|
1204
|
+
if root_node.type in ["preproc_ifdef", "preproc_if", "preproc_elif"]:
|
|
1205
|
+
condition = None
|
|
1206
|
+
is_ifndef = False
|
|
1207
|
+
|
|
1208
|
+
if root_node.type == "preproc_ifdef":
|
|
1209
|
+
for child in root_node.children:
|
|
1210
|
+
if child.type == "#ifndef":
|
|
1211
|
+
is_ifndef = True
|
|
1212
|
+
elif child.type == "identifier":
|
|
1213
|
+
condition = child.text.decode("UTF-8")
|
|
1214
|
+
break
|
|
1215
|
+
elif root_node.type == "preproc_if" or root_node.type == "preproc_elif":
|
|
1216
|
+
found_directive = False
|
|
1217
|
+
for child in root_node.children:
|
|
1218
|
+
if child.type in ["#if", "#elif"]:
|
|
1219
|
+
found_directive = True
|
|
1220
|
+
elif (
|
|
1221
|
+
found_directive
|
|
1222
|
+
and child.is_named
|
|
1223
|
+
and child.type
|
|
1224
|
+
not in [
|
|
1225
|
+
"preproc_elif",
|
|
1226
|
+
"preproc_else",
|
|
1227
|
+
"declaration",
|
|
1228
|
+
"expression_statement",
|
|
1229
|
+
]
|
|
1230
|
+
):
|
|
1231
|
+
condition = child.text.decode("UTF-8")
|
|
1232
|
+
break
|
|
1233
|
+
|
|
1234
|
+
condition_met = False
|
|
1235
|
+
if condition:
|
|
1236
|
+
result = evaluate_preprocessor_condition(condition, macro_definitions)
|
|
1237
|
+
if result is not None:
|
|
1238
|
+
condition_met = (not result) if is_ifndef else result
|
|
1239
|
+
if os.environ.get("DEBUG_PREPROC"):
|
|
1240
|
+
print(
|
|
1241
|
+
f"[PREPROC] {root_node.type} condition='{condition}' is_ifndef={is_ifndef} macros={macro_definitions} result={result} condition_met={condition_met}"
|
|
1242
|
+
)
|
|
1243
|
+
else:
|
|
1244
|
+
condition_met = True
|
|
1245
|
+
if os.environ.get("DEBUG_PREPROC"):
|
|
1246
|
+
print(
|
|
1247
|
+
f"[PREPROC] {root_node.type} condition='{condition}' macros={macro_definitions} CANNOT_EVALUATE, including by default"
|
|
1248
|
+
)
|
|
1249
|
+
|
|
1250
|
+
if root_node.type == "preproc_elif":
|
|
1251
|
+
if condition_met:
|
|
1252
|
+
for child in root_node.children:
|
|
1253
|
+
if child.is_named and child.type not in [
|
|
1254
|
+
"preproc_else",
|
|
1255
|
+
"preproc_elif",
|
|
1256
|
+
]:
|
|
1257
|
+
root_node, node_list, graph_node_list, records = get_nodes(
|
|
1258
|
+
root_node=child,
|
|
1259
|
+
node_list=node_list,
|
|
1260
|
+
graph_node_list=graph_node_list,
|
|
1261
|
+
index=index,
|
|
1262
|
+
records=records,
|
|
1263
|
+
macro_definitions=macro_definitions,
|
|
1264
|
+
)
|
|
1265
|
+
elif root_node.type == "preproc_ifdef" or root_node.type == "preproc_if":
|
|
1266
|
+
found_elif_or_else = False
|
|
1267
|
+
for child in root_node.children:
|
|
1268
|
+
if not child.is_named:
|
|
1269
|
+
continue
|
|
1270
|
+
|
|
1271
|
+
if child.type in ["preproc_elif", "preproc_else"]:
|
|
1272
|
+
if condition_met:
|
|
1273
|
+
continue
|
|
1274
|
+
found_elif_or_else = True
|
|
1275
|
+
|
|
1276
|
+
if child.type == "preproc_elif":
|
|
1277
|
+
root_node, node_list, graph_node_list, records = get_nodes(
|
|
1278
|
+
root_node=child,
|
|
1279
|
+
node_list=node_list,
|
|
1280
|
+
graph_node_list=graph_node_list,
|
|
1281
|
+
index=index,
|
|
1282
|
+
records=records,
|
|
1283
|
+
macro_definitions=macro_definitions,
|
|
1284
|
+
)
|
|
1285
|
+
elif child.type == "preproc_else":
|
|
1286
|
+
if not condition_met:
|
|
1287
|
+
for else_child in child.children:
|
|
1288
|
+
if else_child.is_named:
|
|
1289
|
+
root_node, node_list, graph_node_list, records = (
|
|
1290
|
+
get_nodes(
|
|
1291
|
+
root_node=else_child,
|
|
1292
|
+
node_list=node_list,
|
|
1293
|
+
graph_node_list=graph_node_list,
|
|
1294
|
+
index=index,
|
|
1295
|
+
records=records,
|
|
1296
|
+
macro_definitions=macro_definitions,
|
|
1297
|
+
)
|
|
1298
|
+
)
|
|
1299
|
+
elif condition_met:
|
|
1300
|
+
root_node, node_list, graph_node_list, records = get_nodes(
|
|
1301
|
+
root_node=child,
|
|
1302
|
+
node_list=node_list,
|
|
1303
|
+
graph_node_list=graph_node_list,
|
|
1304
|
+
index=index,
|
|
1305
|
+
records=records,
|
|
1306
|
+
macro_definitions=macro_definitions,
|
|
1307
|
+
)
|
|
1308
|
+
|
|
1309
|
+
elif root_node.type == "preproc_else":
|
|
1310
|
+
pass
|
|
1311
|
+
|
|
1312
|
+
elif root_node.type in [
|
|
1313
|
+
"preproc_include",
|
|
1314
|
+
"preproc_def",
|
|
1315
|
+
"preproc_function_def",
|
|
1316
|
+
"preproc_call",
|
|
1317
|
+
]:
|
|
1318
|
+
pass
|
|
1319
|
+
|
|
1320
|
+
else:
|
|
1321
|
+
for child in root_node.children:
|
|
1322
|
+
root_node, node_list, graph_node_list, records = get_nodes(
|
|
1323
|
+
root_node=child,
|
|
1324
|
+
node_list=node_list,
|
|
1325
|
+
graph_node_list=graph_node_list,
|
|
1326
|
+
index=index,
|
|
1327
|
+
records=records,
|
|
1328
|
+
macro_definitions=macro_definitions,
|
|
1329
|
+
)
|
|
1330
|
+
|
|
1331
|
+
return root_node, node_list, graph_node_list, records
|