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.
Files changed (45) hide show
  1. lambda_graphs/__init__.py +18 -0
  2. lambda_graphs/__main__.py +7 -0
  3. lambda_graphs/cli.py +183 -0
  4. lambda_graphs/codeviews/AST/AST.py +120 -0
  5. lambda_graphs/codeviews/AST/AST_driver.py +37 -0
  6. lambda_graphs/codeviews/AST/__init__.py +0 -0
  7. lambda_graphs/codeviews/CFG/CFG.py +42 -0
  8. lambda_graphs/codeviews/CFG/CFG_c.py +1182 -0
  9. lambda_graphs/codeviews/CFG/CFG_cpp.py +5604 -0
  10. lambda_graphs/codeviews/CFG/CFG_driver.py +45 -0
  11. lambda_graphs/codeviews/CFG/CFG_java.py +1722 -0
  12. lambda_graphs/codeviews/CFG/__init__.py +0 -0
  13. lambda_graphs/codeviews/CST/CST_driver.py +70 -0
  14. lambda_graphs/codeviews/CST/__init__.py +0 -0
  15. lambda_graphs/codeviews/DFG/DFG_driver.py +42 -0
  16. lambda_graphs/codeviews/DFG/__init__.py +0 -0
  17. lambda_graphs/codeviews/SDFG/SDFG.py +135 -0
  18. lambda_graphs/codeviews/SDFG/SDFG_c.py +2041 -0
  19. lambda_graphs/codeviews/SDFG/SDFG_cpp.py +4030 -0
  20. lambda_graphs/codeviews/SDFG/SDFG_java.py +1618 -0
  21. lambda_graphs/codeviews/SDFG/__init__.py +0 -0
  22. lambda_graphs/codeviews/__init__.py +0 -0
  23. lambda_graphs/codeviews/combined_graph/__init__.py +0 -0
  24. lambda_graphs/codeviews/combined_graph/combined_driver.py +163 -0
  25. lambda_graphs/tree_parser/__init__.py +0 -0
  26. lambda_graphs/tree_parser/c_parser.py +565 -0
  27. lambda_graphs/tree_parser/cpp_parser.py +424 -0
  28. lambda_graphs/tree_parser/custom_parser.py +66 -0
  29. lambda_graphs/tree_parser/java_parser.py +254 -0
  30. lambda_graphs/tree_parser/parser_driver.py +54 -0
  31. lambda_graphs/utils/DFG_utils.py +44 -0
  32. lambda_graphs/utils/__init__.py +0 -0
  33. lambda_graphs/utils/c_nodes.py +431 -0
  34. lambda_graphs/utils/cpp_nodes.py +1331 -0
  35. lambda_graphs/utils/java_nodes.py +756 -0
  36. lambda_graphs/utils/multi_file_merger.py +444 -0
  37. lambda_graphs/utils/postprocessor.py +83 -0
  38. lambda_graphs/utils/preprocessor.py +68 -0
  39. lambda_graphs/utils/src_parser.py +23 -0
  40. lambda_graphs-0.1.4.dist-info/METADATA +380 -0
  41. lambda_graphs-0.1.4.dist-info/RECORD +45 -0
  42. lambda_graphs-0.1.4.dist-info/WHEEL +5 -0
  43. lambda_graphs-0.1.4.dist-info/entry_points.txt +2 -0
  44. lambda_graphs-0.1.4.dist-info/licenses/LICENSE +21 -0
  45. lambda_graphs-0.1.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1618 @@
1
+ import copy
2
+ import pprint
3
+ import time
4
+ import os
5
+ from collections import defaultdict
6
+
7
+ import networkx as nx
8
+ from deepdiff import DeepDiff
9
+ from loguru import logger
10
+
11
+ from ...utils.java_nodes import statement_types
12
+ from ...utils.src_parser import traverse_tree
13
+
14
+ assignment = ["assignment_expression"]
15
+ def_statement = ["variable_declarator"]
16
+ increment_statement = ["update_expression"]
17
+ variable_type = ["identifier", "this"]
18
+ method_calls = ["method_invocation"]
19
+
20
+ switch_type = ["switch_expression"]
21
+ inner_types = [
22
+ "declaration",
23
+ "expression_statement",
24
+ "local_variable_declaration",
25
+ ]
26
+ method_invocation = method_calls + [
27
+ "object_creation_expression",
28
+ "explicit_constructor_invocation",
29
+ ]
30
+ method_declaration = ["method_declaration", "constructor_declaration"]
31
+ handled_types = (
32
+ assignment
33
+ + def_statement
34
+ + increment_statement
35
+ + method_calls
36
+ + method_declaration
37
+ + switch_type
38
+ + [
39
+ "catch_clause",
40
+ "return_statement",
41
+ "throw_statement",
42
+ "enhanced_for_statement",
43
+ "for_statement",
44
+ "object_creation_expression",
45
+ "lambda_expression",
46
+ ]
47
+ )
48
+
49
+ pp = pprint.PrettyPrinter(indent=4)
50
+ system_type = ("Console", "System", "String", "Collections")
51
+ # call_variable_map = {}
52
+ # node_list = {}
53
+ debug = False
54
+ # if any(
55
+ # # GITHUB_ACTIONS
56
+ # x in os.environ for x in ("PYCHARM_HOSTED",)
57
+ # ):
58
+ # debug = True
59
+ # properties = {
60
+ # "last_use": False,
61
+ # "last_def": False,
62
+ # "alex_algo": False
63
+ # }
64
+
65
+
66
+ def scope_check(parent_scope, child_scope):
67
+ for p in parent_scope:
68
+ if p not in child_scope:
69
+ return False
70
+ return True
71
+
72
+
73
+ class Identifier:
74
+ def __init__(
75
+ self,
76
+ parser,
77
+ node,
78
+ line=None,
79
+ declaration=False,
80
+ full_ref=None,
81
+ method_call=False,
82
+ ):
83
+ self.core = st(node)
84
+ # field_declaration = return_first_parent_of_types(node, "field_declaration")
85
+ # param_declaration = return_first_parent_of_types(node, "formal_parameter")
86
+ # self.param_declaration = False
87
+ # if param_declaration is not None:
88
+ # self.param_declaration = True
89
+ # self.immutable_declaration = False
90
+ # if field_declaration is not None:
91
+ # self.immutable_declaration = True
92
+ class_node = return_first_parent_of_types(node, "class_declaration")
93
+ if full_ref is None:
94
+ full_ref = node
95
+ self.parent_class = class_node
96
+ self.unresolved_name = st(full_ref)
97
+ if self.unresolved_name.startswith("this."):
98
+ self.unresolved_name = st(full_ref)[5:]
99
+ if class_node is not None:
100
+ class_name = st(class_node.child_by_field_name("name"))
101
+ self.parent_class = class_name
102
+ if self.unresolved_name.startswith(class_name + "."):
103
+ self.unresolved_name = self.unresolved_name[len(class_name) + 1 :]
104
+ self.line = line
105
+ self.declaration = declaration
106
+ self.method_call = method_call
107
+ self.satisfied = method_call
108
+ if self.method_call and self.declaration:
109
+ method_resolution = self.unresolved_name.split(".")
110
+ # br.attribute2.attr.method1
111
+ # Option 1 - method call affects main object
112
+ # resolved_name = br
113
+ # resolved_name = method_resolution[0]
114
+ # resolved_name = br.attribute2.attr
115
+ # Option 2 - method call only affects subattribute
116
+ resolved_name = ".".join(method_resolution[:-1])
117
+ self.name = resolved_name
118
+ else:
119
+ self.name = self.unresolved_name
120
+ if not self.name:
121
+ self.name = self.unresolved_name
122
+ if node.type == "field_access":
123
+ node = recursively_get_children_of_types(
124
+ node,
125
+ ["identifier"],
126
+ index=parser.index,
127
+ check_list=parser.symbol_table["scope_map"],
128
+ )[-1]
129
+ variable_index = get_index(node, parser.index)
130
+ self.variable_scope = parser.symbol_table["scope_map"][variable_index]
131
+ if variable_index in parser.declaration_map:
132
+ self.scope = parser.symbol_table["scope_map"][
133
+ parser.declaration_map[variable_index]
134
+ ]
135
+ else:
136
+ # self.scope = variable_scope
137
+ # Declaration does not exist hence it is given
138
+ # the outermost scope
139
+ self.scope = [0]
140
+ if line is not None:
141
+ self.real_line_no = read_index(parser.index, line)[0][0]
142
+
143
+ def __eq__(self, other):
144
+ # if not isinstance(other, Identifier):
145
+ # return NotImplemented
146
+ # if self.name == other.name:
147
+ # if other.line is None and other.line is not None:
148
+ # other.line = self.line
149
+ # elif other.line is not None and self.line is None:
150
+ # self.line = other.line
151
+
152
+ # if self.method_call and self.declaration:
153
+ # method_resolution = self.name.split(".")
154
+ # # Option 1 - method call affects main object
155
+ # # resolved_name = method_resolution[0]
156
+ # # Option 2 - method call only affects subattribute
157
+ # resolved_name = ".".join(method_resolution[:-1])
158
+ # return resolved_name == other.name and self.line == other.line and sorted(self.scope) == sorted(
159
+ # other.scope)
160
+ # else:
161
+ return (
162
+ self.name == other.name
163
+ and self.line == other.line
164
+ and sorted(self.scope) == sorted(other.scope)
165
+ and self.method_call == other.method_call
166
+ )
167
+
168
+ def __hash__(self):
169
+ # if self.method_call and self.declaration:
170
+ # method_resolution = self.name.split(".")
171
+ # # Option 1 - method call affects main object
172
+ # resolved_name = method_resolution[0]
173
+ # # Option 2 - method call only affects subattribute
174
+ # # resolved_name = ".".join(method_resolution[:-1])
175
+ # return hash((resolved_name, self.line, str(self.scope), False))
176
+ # else:
177
+ return hash((self.name, self.line, str(self.scope), self.method_call))
178
+
179
+ def __str__(self):
180
+ result = [self.name]
181
+ if self.line:
182
+ result += [str(self.real_line_no)]
183
+ result += ["|".join(map(str, self.scope))]
184
+ else:
185
+ result += ["?"]
186
+ if self.method_call:
187
+ result += ["()"]
188
+ return f"{{{','.join(result)}}}"
189
+
190
+
191
+ def st(child):
192
+ if child is None:
193
+ # logger.error
194
+ return ""
195
+ else:
196
+ return child.text.decode()
197
+
198
+
199
+ def get_index(node, index):
200
+ try:
201
+ return index[(node.start_point, node.end_point, node.type)]
202
+ except:
203
+ return None
204
+
205
+
206
+ def read_index(index, idx):
207
+ return list(index.keys())[list(index.values()).index(idx)]
208
+
209
+
210
+ def parent_remapping_callback(node, remap=True):
211
+ if node is None:
212
+ return None
213
+ elif node.type == "do_statement":
214
+ if not remap:
215
+ return None
216
+ while_node = None
217
+ for child in node.children:
218
+ if child.type == "while":
219
+ while_node = child.next_named_sibling
220
+ break
221
+ return while_node
222
+ elif node.type == "try_statement":
223
+ return None
224
+ else:
225
+ return node
226
+
227
+
228
+ def return_first_parent_of_types(node, parent_types, stop_types=None, remap=True):
229
+ if stop_types is None:
230
+ stop_types = []
231
+ if node.type in parent_types:
232
+ return parent_remapping_callback(node, remap=remap)
233
+ while node.parent is not None:
234
+ if node.type in stop_types:
235
+ return None
236
+ if node.parent.type in parent_types:
237
+ return parent_remapping_callback(node.parent, remap=remap)
238
+ node = node.parent
239
+ return None
240
+
241
+
242
+ #
243
+ # def set_add(lst, item):
244
+ # for entry in lst:
245
+ # if item == entry:
246
+ # return
247
+ # lst.append(item)
248
+ #
249
+ #
250
+ # def set_union(first_list, second_list):
251
+ # resulting_list = list(first_list)
252
+ # for x in second_list:
253
+ # set_add(resulting_list, x)
254
+ # return resulting_list
255
+ #
256
+ #
257
+ # def set_difference(first_list, second_list):
258
+ # resulting_list = []
259
+ # for item in first_list:
260
+ # match_found = False
261
+ # for item2 in second_list:
262
+ # if item == item2:
263
+ # match_found = True
264
+ # break
265
+ # if not match_found:
266
+ # resulting_list.append(item)
267
+ # return resulting_list
268
+ #
269
+ #
270
+ # def set_intersection(first_list, second_list):
271
+ # resulting_list = []
272
+ # for item in first_list:
273
+ # match_found = False
274
+ # for item2 in second_list:
275
+ # if item == item2:
276
+ # match_found = True
277
+ # break
278
+ # if match_found:
279
+ # resulting_list.append(item)
280
+ # return resulting_list
281
+
282
+
283
+ def set_add(lst, item):
284
+ for entry in lst:
285
+ if item == entry:
286
+ return
287
+ lst.append(item)
288
+
289
+
290
+ def set_union(first_list, second_list):
291
+ resulting_list = list(first_list)
292
+ resulting_list.extend(x for x in second_list if x not in resulting_list)
293
+ return resulting_list
294
+
295
+
296
+ def set_difference(first_list, second_list):
297
+ resulting_list = [item for item in first_list if item not in second_list]
298
+ return resulting_list
299
+
300
+
301
+ def set_intersection(first_list, second_list):
302
+ resulting_list = [item for item in first_list if item in second_list]
303
+ return resulting_list
304
+
305
+
306
+ def add_entry(
307
+ parser,
308
+ rda_table,
309
+ statement_id,
310
+ used=None,
311
+ defined=None,
312
+ declaration=False,
313
+ core=None,
314
+ method_call=False,
315
+ ):
316
+ # global node_list
317
+ if statement_id not in rda_table:
318
+ rda_table[statement_id] = defaultdict(list)
319
+ if not used and not defined:
320
+ return
321
+ mapped_node = None
322
+ # meth_statement = return_first_parent_of_types(used or defined, ['method_declaration', 'constructor_declaration'])
323
+ # if meth_statement is not None:
324
+ # meth_statement_id = get_index(meth_statement, parser.index)
325
+ # if meth_statement_id in call_variable_map and meth_statement_id != statement_id:
326
+ # checker = st(core).split(".")[0] or st(defined).split(".")[0] or st(used).split(".")[0]
327
+ # if checker in call_variable_map[meth_statement_id]:
328
+ # mapped_node = call_variable_map[meth_statement_id][checker]
329
+ # # if mapped_node.parent.type == "field_access":
330
+ # # mapped_node = recursively_get_children_of_types(mapped_node, ['identifier'], index=parser.index,
331
+ # # check_list=parser.symbol_table["scope_map"])[-1]
332
+ if core is None:
333
+ current_node = used or defined
334
+ if current_node.type == "field_access":
335
+ current_node = recursively_get_children_of_types(
336
+ current_node,
337
+ ["identifier"],
338
+ index=parser.index,
339
+ check_list=parser.symbol_table["scope_map"],
340
+ )[-1]
341
+ if defined is not None:
342
+ defined = current_node
343
+ else:
344
+ used = current_node
345
+ if (
346
+ current_node.parent is not None
347
+ and current_node.parent.type == "field_access"
348
+ ):
349
+ # LOOK AT THE SYMBOL TABLE COMMENT AS WELL #? TODO
350
+ # object_node = current_node.parent.child_by_field_name("name")
351
+ # object_index = get_index(object_node, parser.index)
352
+ # current_index = get_index(current_node, parser.index)
353
+ # if object_index == current_index:
354
+ # all_calls.append(current_index)
355
+
356
+ while (
357
+ current_node.parent is not None
358
+ and current_node.parent.type == "field_access"
359
+ ):
360
+ current_node = current_node.parent
361
+
362
+ if (
363
+ current_node.parent is not None
364
+ and current_node.parent.type == "method_invocation"
365
+ ):
366
+ if not st(current_node).startswith(system_type):
367
+ add_entry(
368
+ parser,
369
+ rda_table,
370
+ statement_id,
371
+ defined=used or defined,
372
+ core=current_node.parent,
373
+ # declaration=True,
374
+ method_call=True,
375
+ )
376
+ add_entry(
377
+ parser,
378
+ rda_table,
379
+ statement_id,
380
+ used=used or defined,
381
+ core=current_node.parent,
382
+ # declaration=True,
383
+ method_call=True,
384
+ )
385
+ if mapped_node is not None:
386
+ set_add(
387
+ rda_table[statement_id]["def"],
388
+ Identifier(
389
+ parser,
390
+ mapped_node,
391
+ statement_id,
392
+ full_ref=mapped_node,
393
+ declaration=declaration,
394
+ method_call=method_call,
395
+ ),
396
+ )
397
+ return
398
+ if defined is not None:
399
+ add_entry(
400
+ parser,
401
+ rda_table,
402
+ statement_id,
403
+ defined=defined,
404
+ core=current_node,
405
+ declaration=declaration,
406
+ method_call=method_call,
407
+ )
408
+ if mapped_node is not None:
409
+ set_add(
410
+ rda_table[statement_id]["def"],
411
+ Identifier(
412
+ parser,
413
+ mapped_node,
414
+ statement_id,
415
+ full_ref=mapped_node,
416
+ declaration=declaration,
417
+ method_call=method_call,
418
+ ),
419
+ )
420
+ else:
421
+ add_entry(
422
+ parser,
423
+ rda_table,
424
+ statement_id,
425
+ used=used,
426
+ core=current_node,
427
+ declaration=declaration,
428
+ method_call=method_call,
429
+ )
430
+ return
431
+ elif (
432
+ current_node.next_sibling
433
+ and current_node.next_sibling.type == "."
434
+ and current_node.parent is not None
435
+ and current_node.parent.type == "method_invocation"
436
+ ):
437
+ if not st(current_node).startswith(system_type):
438
+ if (used or defined).type == "identifier":
439
+ set_add(
440
+ rda_table[statement_id]["def"],
441
+ Identifier(
442
+ parser,
443
+ used or defined,
444
+ statement_id,
445
+ full_ref=None,
446
+ # declaration=True,
447
+ method_call=True,
448
+ ),
449
+ )
450
+ if st(core).startswith(system_type):
451
+ return
452
+ if defined is not None:
453
+ if get_index(defined, parser.index) not in parser.symbol_table["scope_map"]:
454
+ return
455
+ set_add(
456
+ rda_table[statement_id]["def"],
457
+ Identifier(
458
+ parser,
459
+ defined,
460
+ statement_id,
461
+ full_ref=core,
462
+ declaration=declaration,
463
+ method_call=method_call,
464
+ ),
465
+ )
466
+ if mapped_node is not None:
467
+ set_add(
468
+ rda_table[statement_id]["def"],
469
+ Identifier(
470
+ parser,
471
+ mapped_node,
472
+ statement_id,
473
+ full_ref=mapped_node,
474
+ declaration=declaration,
475
+ method_call=method_call,
476
+ ),
477
+ )
478
+ else:
479
+ if get_index(used, parser.index) not in parser.symbol_table["scope_map"]:
480
+ return
481
+ if mapped_node is not None and method_call:
482
+ set_add(
483
+ rda_table[statement_id]["def"],
484
+ Identifier(
485
+ parser,
486
+ mapped_node,
487
+ statement_id,
488
+ full_ref=mapped_node,
489
+ declaration=declaration,
490
+ method_call=method_call,
491
+ ),
492
+ )
493
+ set_add(
494
+ rda_table[statement_id]["use"],
495
+ Identifier(
496
+ parser,
497
+ used,
498
+ full_ref=core,
499
+ declaration=declaration,
500
+ method_call=method_call,
501
+ ),
502
+ )
503
+
504
+
505
+ def check_field_name(req_child):
506
+ for i, child in enumerate(req_child.parent.children):
507
+ if req_child == child:
508
+ field_type = child.parent.field_name_for_child(i)
509
+ if field_type is not None and field_type == "type":
510
+ return False
511
+ return True
512
+
513
+
514
+ def recursively_get_children_of_types(
515
+ node, st_types, check_list=None, index=None, result=None, stop_types=None
516
+ ):
517
+ if isinstance(st_types, str):
518
+ st_types = [st_types]
519
+ if stop_types is None:
520
+ stop_types = []
521
+ if result is None:
522
+ result = []
523
+ if node.type in stop_types:
524
+ return result
525
+ if check_list and index:
526
+ result.extend(
527
+ list(
528
+ filter(
529
+ lambda child: child.type in st_types
530
+ and get_index(child, index) in check_list
531
+ and check_field_name(child),
532
+ # and child.parent.type in ['variable_declaration', 'object_creation_expression',
533
+ # 'field_access'],
534
+ node.children,
535
+ )
536
+ )
537
+ )
538
+ else:
539
+ result.extend(list(filter(lambda child: child.type in st_types, node.children)))
540
+ for child in node.named_children:
541
+ if child in stop_types:
542
+ continue
543
+ # if child.type not in st_types:
544
+ result = recursively_get_children_of_types(
545
+ child,
546
+ st_types,
547
+ result=result,
548
+ stop_types=stop_types,
549
+ index=index,
550
+ check_list=check_list,
551
+ )
552
+ return result
553
+
554
+
555
+ def compute_out(old_result, connected_derivers, def_set):
556
+ result = []
557
+ for node in connected_derivers:
558
+ result = set_union(result, old_result[node]["IN"])
559
+ # for node in result:
560
+ # if node in def_set:
561
+ # continue
562
+ return result
563
+
564
+
565
+ def compute_in(use_set, out_set, def_set, all_defs):
566
+ result = set_union(use_set, set_difference(out_set, def_set))
567
+ # for node in result:
568
+ # if node in all_defs:
569
+ # continue
570
+ return result
571
+
572
+
573
+ def print_table(index, new_result, iteration=0):
574
+ table = [f"\nRDA: iteration {iteration}\n"]
575
+ for key in new_result:
576
+ try:
577
+ table.append(str(read_index(index, key)[0][0] + 1) + "\n")
578
+ except:
579
+ table.append(str(key) + "\n")
580
+ for key2 in new_result[key]:
581
+ table.append(f"\t{key2}:")
582
+ for entry in new_result[key][key2]:
583
+ table.append(str(entry) + ",")
584
+ table.append("\n")
585
+ logger.debug("".join(table))
586
+
587
+
588
+ def start_rda(index, rda_table, graph, pre_solve=False):
589
+ if debug and not pre_solve:
590
+ print_table(index, rda_table)
591
+ remove_set = []
592
+ # "method_return", "class_return"
593
+ if pre_solve:
594
+ remove_set = [
595
+ "method_call",
596
+ "method_return",
597
+ "class_return",
598
+ "constructor_call",
599
+ ]
600
+ graph = copy.deepcopy(graph)
601
+ remove_edges = []
602
+ if remove_set:
603
+ for edge in graph.edges:
604
+ if (
605
+ "label" in graph.edges[edge]
606
+ and graph.edges[edge]["label"] in remove_set
607
+ ):
608
+ remove_edges.append(edge)
609
+ graph.remove_edges_from(remove_edges)
610
+
611
+ cfg = graph
612
+ nodes = graph.nodes
613
+ old_result = {}
614
+ iteration = 0
615
+ for node in nodes:
616
+ old_result[node] = {"IN": set(), "OUT": set()}
617
+ # for node in nodes:
618
+ # connected_derivers = [t for (s, t) in cfg.out_edges(node)]
619
+ # old_result[node]["OUT"] = compute_out(old_result, connected_derivers, rda_table[node]["def"] if node in rda_table else [])
620
+ new_result = copy.deepcopy(old_result)
621
+ while True:
622
+ iteration = iteration + 1
623
+ iteration_returners = {}
624
+ for node in nodes:
625
+ connected_feeders = []
626
+ returning_feeders = []
627
+ for s, t in cfg.in_edges(node):
628
+ if "label" in cfg.edges[s, t, 0] and cfg.edges[s, t, 0]["label"] in [
629
+ "method_return",
630
+ "class_return",
631
+ ]:
632
+ returning_feeders.append(s)
633
+ else:
634
+ connected_feeders.append(s)
635
+ feeder_union = set()
636
+ returner_union = set()
637
+ for feeder in connected_feeders:
638
+ feeder_union = feeder_union.union(old_result[feeder]["OUT"])
639
+ for returner in returning_feeders:
640
+ returner_union = returner_union.union(old_result[returner]["OUT"])
641
+ for s, t in cfg.out_edges(node):
642
+ if s != t:
643
+ iteration_returners[t] = (
644
+ iteration_returners[t].union(returner_union)
645
+ if t in iteration_returners
646
+ else returner_union
647
+ )
648
+ new_result[node]["IN"] = feeder_union
649
+ def_info = rda_table[node]["def"] if node in rda_table else set()
650
+ names_defined = [defined.name for defined in def_info]
651
+ # if defined.param_declaration is None
652
+ selective_difference = set()
653
+ for already_defined in feeder_union:
654
+ # if already_defined.immutable_declaration:
655
+ # selective_difference.add(already_defined)
656
+ if already_defined.name in names_defined:
657
+ continue
658
+ else:
659
+ selective_difference.add(already_defined)
660
+ new_result[node]["OUT"] = selective_difference.union(def_info)
661
+ for node in iteration_returners:
662
+ def_info = rda_table[node]["def"] if node in rda_table else set()
663
+ names_defined = [defined.name for defined in def_info]
664
+ selective_difference = set()
665
+ for already_defined in iteration_returners[node]:
666
+ # if already_defined.immutable_declaration:
667
+ # selective_difference.add(already_defined)
668
+ if already_defined.name in names_defined:
669
+ continue
670
+ else:
671
+ selective_difference.add(already_defined)
672
+ new_result[node]["OUT"] = new_result[node]["OUT"].union(
673
+ selective_difference
674
+ )
675
+ ddiff = DeepDiff(
676
+ old_result,
677
+ new_result,
678
+ ignore_order=True,
679
+ )
680
+ if ddiff == {}:
681
+ # for node in nodes:
682
+ # all_defs = []
683
+ # connected_feeders = [t for (s, t) in cfg.in_edges(node)]
684
+ # for feeder in connected_feeders:
685
+ # defs = rda_table[feeder]["def"] if feeder in rda_table else []
686
+ # all_defs += defs
687
+ # for outgoing in new_result[node]["IN"]:
688
+ # if outgoing in all_defs:
689
+ # continue
690
+ # connected_derivers = [t for (s, t) in cfg.out_edges(node)]
691
+ # for deriver in connected_derivers:
692
+ # for incoming in new_result[deriver]["IN"]:
693
+ # if incoming in rda_table[node]["def"]:
694
+ # continue
695
+ if debug and not pre_solve:
696
+ logger.info("RDA: Completed in iteration {}", iteration)
697
+ print_table(index, new_result, iteration)
698
+ break
699
+ old_result = copy.deepcopy(new_result)
700
+ return new_result
701
+
702
+
703
+ def add_edge(final_graph, a, b, attrib=None, pre_solve=False):
704
+ if (pre_solve and attrib) or not final_graph.has_edge(a, b):
705
+ final_graph.add_edge(a, b)
706
+ if attrib is not None:
707
+ nx.set_edge_attributes(final_graph, {(a, b, 0): attrib})
708
+
709
+
710
+ def get_required_edges_from_def_to_use(
711
+ index,
712
+ cfg,
713
+ rda_solution,
714
+ rda_table,
715
+ graph_nodes,
716
+ all_classes,
717
+ additional_edges=None,
718
+ processed_edges=None,
719
+ pre_solve=False,
720
+ properties=None,
721
+ ):
722
+ if additional_edges is None:
723
+ additional_edges = []
724
+ if processed_edges is None:
725
+ processed_edges = []
726
+ final_graph = copy.deepcopy(cfg)
727
+ # twin_edges = [
728
+ # "constructor_call", "method_call"
729
+ # ]
730
+ # twins = []
731
+ # retain_edges = [
732
+ # "constructor_call", "class_return", "method_call", "method_return"
733
+ # ]
734
+ # retains = []
735
+ # additional_edges = []
736
+ # for edge in list(final_graph.edges()):
737
+ # edge_data = final_graph.get_edge_data(*edge)[0]
738
+ # if edge_data["label"] in retain_edges:
739
+ # retains.append(edge)
740
+ # # if edge_data["label"] in twin_edges:
741
+ # # twins.append(edge)
742
+ final_graph.remove_edges_from(list(final_graph.edges()))
743
+ for node in graph_nodes:
744
+ rda_info = rda_table[node] if node in rda_table else None
745
+ if rda_info is not None:
746
+ use_info = rda_info["use"]
747
+ # def_info = rda_info["def"]
748
+ else:
749
+ use_info = set()
750
+ # def_info = set()
751
+ # names_used = [used.name for used in use_info]
752
+ for used in use_info:
753
+ for available_def in rda_solution[node]["IN"]:
754
+ if available_def.name == used.name:
755
+ # if available_def not in rda_solution[node]["OUT"]:
756
+ # for line_def in rda_table[node]["def"]:
757
+ # if line_def.name == available_def.name:
758
+ # if line_def.declaration:
759
+ # available_def = line_def
760
+ # if available_def in rda_table[available_def.line]["def"]:
761
+ if scope_check(available_def.scope, used.scope):
762
+ # if available_def.declaration:
763
+ # if available_def.immutable_declaration:
764
+ # for other_def in rda_solution[node]["IN"]:
765
+ # if other_def.name == available_def.name and other_def.param_declaration:
766
+ # if not used.core.startswith("this"):
767
+ # available_def = other_def
768
+ # break
769
+ add_edge(
770
+ final_graph,
771
+ available_def.line,
772
+ node,
773
+ {"used_def": used.name},
774
+ pre_solve,
775
+ )
776
+ used.satisfied = True
777
+ # else:
778
+ # add_edge(final_graph, available_def.line, node, {'used_def': used.name}, pre_solve)
779
+ # used.satisfied = True
780
+ elif "." in used.name or "." in available_def.name:
781
+ if len(used.name.split(".")) < len(available_def.name.split(".")):
782
+ smaller = used
783
+ bigger = available_def
784
+ else:
785
+ smaller = available_def
786
+ bigger = used
787
+ if bigger.name.strip().startswith(smaller.name.strip()):
788
+ if (
789
+ not bigger.name.strip()
790
+ .replace(smaller.name.strip(), "")
791
+ .strip()
792
+ .startswith(".")
793
+ ):
794
+ continue
795
+
796
+ # add_edge(final_graph, bigger.line or node, smaller.line or node)
797
+ add_edge(
798
+ final_graph,
799
+ available_def.line or node,
800
+ used.line or node,
801
+ {"used_def": used.name},
802
+ pre_solve,
803
+ )
804
+ used.satisfied = True
805
+ if not used.satisfied:
806
+ if used.core in all_classes:
807
+ static_derive_class = all_classes[used.core]
808
+ fields = recursively_get_children_of_types(
809
+ static_derive_class, "field_declaration"
810
+ )
811
+ for field in fields:
812
+ field_pieces = st(field).split()
813
+ if "static" in field_pieces:
814
+ if used.name.replace(used.core + ".", "") in field_pieces:
815
+ processed_edges.append((get_index(field, index), node))
816
+ else:
817
+ if not pre_solve and properties.get("last_use", False):
818
+ for i in rda_table:
819
+ for entry in rda_table[i]["use"]:
820
+ if entry.name == used.name and i != node:
821
+ # TODO: THIS IS AN AP - Make sure edges added here are right
822
+ if i in cfg and node in cfg:
823
+ # TODO: check missing i and handle it
824
+ if not nx.has_path(cfg, i, node):
825
+ continue
826
+ add_edge(
827
+ final_graph, i, node, {"color": "green"}
828
+ )
829
+ # used.satisfied = True
830
+ # break
831
+ # if used.satisfied:
832
+ # break
833
+ if properties.get("last_def", False):
834
+ for available_def in rda_solution[node]["IN"] - rda_solution[node]["OUT"]:
835
+ ignore_nodes = [
836
+ "for_statement",
837
+ "while_statement",
838
+ "if_statement",
839
+ "switch_statement",
840
+ ]
841
+ if (
842
+ read_index(index, node)[-1] in ignore_nodes
843
+ or read_index(index, available_def.line)[-1] in ignore_nodes
844
+ ):
845
+ continue
846
+ add_edge(final_graph, available_def.line, node, {"color": "orange"})
847
+ # for definition in def_info:
848
+ # for available_def in rda_solution[node]["IN"]:
849
+ # if "." in definition.name or "." in available_def.name:
850
+ # if len(definition.name.split(".")) < len(available_def.name.split(".")):
851
+ # smaller = definition
852
+ # bigger = available_def
853
+ # else:
854
+ # smaller = available_def
855
+ # bigger = definition
856
+ # if bigger.name.strip().startswith(smaller.name.strip()):
857
+ # if not bigger.name.strip().replace(smaller.name.strip(), "").strip().startswith("."):
858
+ # continue
859
+ # # add_edge(final_graph, bigger.line or node, smaller.line or node)
860
+ # add_edge(final_graph, smaller.line or node, bigger.line or node)
861
+ if not pre_solve:
862
+ for edge in additional_edges:
863
+ if debug:
864
+ add_edge(final_graph, *edge, {"color": "yellow"})
865
+ else:
866
+ add_edge(final_graph, *edge)
867
+ for edge in processed_edges:
868
+ add_edge(final_graph, *edge)
869
+ # for edge in twins:
870
+ # continue
871
+ # add_edge(final_graph, edge[0], edge[1])
872
+ # add_edge(final_graph, edge[1], edge[0])
873
+ return final_graph
874
+
875
+
876
+ def rda_cfg_map(rda_solution, CFG_results):
877
+ graph = CFG_results.graph
878
+ attrs = {}
879
+ for edge in list(graph.edges):
880
+ out_set = rda_solution[edge[0]]["OUT"]
881
+ in_set = rda_solution[edge[1]]["IN"]
882
+ intersection = set_intersection(out_set, in_set)
883
+ data = graph.get_edge_data(*edge)
884
+ if intersection:
885
+ data["label"] = ",".join([str(intr) for intr in intersection])
886
+ else:
887
+ graph.remove_edge(*edge)
888
+ # logger.warning("Unable to remap edge {}", edge)
889
+ attrs[edge] = data
890
+ nx.set_edge_attributes(graph, attrs)
891
+ return graph
892
+
893
+
894
+ def node_has_parent(nvalue, parent_class):
895
+ if nvalue == parent_class:
896
+ return True
897
+ while nvalue.parent:
898
+ if nvalue.parent == parent_class:
899
+ return True
900
+ else:
901
+ nvalue = nvalue.parent
902
+ return False
903
+
904
+
905
+ def call_variable(call_variable_map, node, edge_for, check_virtual=True):
906
+ for virtual_var, actual_var in call_variable_map[node]:
907
+ if check_virtual:
908
+ if st(virtual_var) == edge_for:
909
+ return actual_var
910
+ else:
911
+ if st(actual_var) == edge_for:
912
+ return virtual_var
913
+ return None
914
+
915
+
916
+ def dfg_java(prop, CFG_results):
917
+ # global properties
918
+ properties = prop
919
+ parser = CFG_results.parser
920
+ index = parser.index
921
+ tree = parser.tree
922
+
923
+ call_variable_map = {}
924
+ handled_cases = []
925
+
926
+ # if_statement = ["if_statement", "else"]
927
+ # for_statement = ["for_statement"]
928
+ # enhanced_for_statement = ["for_each_statement"]
929
+ # while_statement = ["while_statement"]
930
+
931
+ additional_edges = []
932
+ processed_edges = []
933
+ cfg_graph = copy.deepcopy(CFG_results.graph)
934
+
935
+ # Temperory edge adding logic when CFG is broken
936
+ # 41 -> 57
937
+ # 57 -> 27
938
+ # add_edge(cfg_graph, 41, 57, {'controlflow_type': 'method_return', 'edge_type': 'CFG_edge', 'label': 'method_return', 'color': 'blue'})
939
+ # add_edge(cfg_graph, 57, 27, {'controlflow_type': 'method_call', 'edge_type': 'CFG_edge', 'label': 'method_call', 'color': 'blue'})
940
+
941
+ # global node_list
942
+ node_list = CFG_results.node_list
943
+
944
+ all_classes = {
945
+ st(node_list[read_index(index, x)].child_by_field_name("name")): node_list[
946
+ read_index(index, x)
947
+ ]
948
+ for x, y in cfg_graph.nodes(data=True)
949
+ if "type_label" in y and y["type_label"] == "class_declaration"
950
+ }
951
+ uninitiated_classes = [
952
+ x
953
+ for x, y in cfg_graph.nodes(data=True)
954
+ if "type_label" in y
955
+ and y["type_label"] == "class_declaration"
956
+ and cfg_graph.in_degree(x) == 0
957
+ ]
958
+
959
+ start_rda_init_time = time.time()
960
+ for edge in list(cfg_graph.edges()):
961
+ edge_data = cfg_graph.get_edge_data(*edge)[0]
962
+ # If there is object creation
963
+ if edge_data["label"] == "class_return":
964
+ # call_statement = node_list[read_index(index, edge[1])]
965
+ # call_node = recursively_get_children_of_types(call_statement, method_invocation)[0]
966
+ last_statement = node_list[read_index(index, edge[0])]
967
+ class_node = return_first_parent_of_types(
968
+ last_statement, "class_declaration"
969
+ )
970
+ class_name = st(class_node.child_by_field_name("name"))
971
+ class_methods = recursively_get_children_of_types(
972
+ class_node, method_declaration
973
+ )
974
+ class_id = get_index(class_node, index)
975
+ # find all simple paths between class_id and edge[0]
976
+ all_paths = nx.all_simple_paths(cfg_graph, source=class_id, target=edge[0])
977
+ # only_path = nx.shortest_path(cfg_graph, source=class_id, target=edge[0])
978
+ unique_constructor_children = set()
979
+ for path in all_paths:
980
+ for node in path:
981
+ unique_constructor_children.add(node)
982
+ if len(unique_constructor_children) == 0:
983
+ unique_constructor_children.add(edge[0])
984
+ # unique_constructor_children = set(only_path)
985
+ # for nkey, nvalue in node_list.items():
986
+ # if node_has_parent(nvalue, class_node):
987
+ # unique_constructor_children.add(index[nkey])
988
+ for class_method in class_methods:
989
+ class_method_name = st(class_method.child_by_field_name("name"))
990
+ if class_method_name != class_name:
991
+ add_edge(cfg_graph, edge[0], get_index(class_method, index))
992
+
993
+ for n_id in unique_constructor_children:
994
+ additional_edges.append((n_id, edge[1]))
995
+ # Handle method_call edges and all constructor calls if there are parameters
996
+ elif edge_data["label"] in ["constructor_call", "method_call"]:
997
+ call_statement = node_list[read_index(index, edge[0])]
998
+ if call_statement.type in method_invocation:
999
+ call_node = call_statement
1000
+ else:
1001
+ marked_index = int(edge_data["controlflow_type"].rsplit("|", 1)[-1])
1002
+ call_nodes = recursively_get_children_of_types(
1003
+ call_statement, method_invocation
1004
+ )
1005
+ for call_node in call_nodes:
1006
+ if marked_index == get_index(call_node, index):
1007
+ break
1008
+ method = node_list[read_index(index, edge[1])]
1009
+ if method.type == "class_declaration":
1010
+ class_node = method
1011
+ constructors = recursively_get_children_of_types(
1012
+ class_node, "constructor_declaration"
1013
+ )
1014
+ if constructors:
1015
+ if "target_constructor" in edge_data:
1016
+ target_constructor = edge_data["target_constructor"]
1017
+ for constructor in constructors:
1018
+ if get_index(constructor, index) == target_constructor:
1019
+ method = constructor
1020
+ break
1021
+ else:
1022
+ continue
1023
+ # TODO if this else is hit its an AP
1024
+ # method = constructors[0]
1025
+ else:
1026
+ continue
1027
+ actual_variables = call_node.child_by_field_name("arguments").named_children
1028
+ virtual_variables = []
1029
+ for node in method.named_children:
1030
+ if "formal_parameter" in node.type:
1031
+ virtual_variables = recursively_get_children_of_types(
1032
+ node,
1033
+ variable_type,
1034
+ index=parser.index,
1035
+ stop_types=statement_types["statement_holders"],
1036
+ )
1037
+ if actual_variables:
1038
+ # TODO: Handle var_args Type... IterableObject
1039
+ var_args = False
1040
+ if var_args or len(actual_variables) == len(virtual_variables):
1041
+ for actual_var, virtual_var in zip(
1042
+ actual_variables, virtual_variables
1043
+ ):
1044
+ method_statement_id = edge[1]
1045
+ if method_statement_id not in call_variable_map:
1046
+ call_variable_map[method_statement_id] = []
1047
+ call_variable_map[method_statement_id].append(
1048
+ (virtual_var, actual_var)
1049
+ )
1050
+ processed_edges.append(edge)
1051
+ else:
1052
+ logger.error("Number of actual and virtual variables do not match")
1053
+ if not var_args:
1054
+ pass
1055
+ # assert len(actual_variables) == len(virtual_variables)
1056
+ elif edge_data["label"] == "method_return":
1057
+ return_statement = node_list[read_index(index, edge[0])]
1058
+ if (
1059
+ return_statement.type == "return_statement"
1060
+ and return_statement.named_children
1061
+ ):
1062
+ processed_edges.append(edge)
1063
+ elif edge_data["label"] == "lambda_invocation":
1064
+ processed_edges.append(edge)
1065
+
1066
+ for class_id in uninitiated_classes:
1067
+ class_node = node_list[read_index(index, class_id)]
1068
+ class_name = st(class_node.child_by_field_name("name"))
1069
+ class_methods = recursively_get_children_of_types(
1070
+ class_node, method_declaration
1071
+ )
1072
+
1073
+ descendants = [
1074
+ x
1075
+ for x in nx.descendants(cfg_graph, class_id)
1076
+ if cfg_graph.out_degree(x) == 0 and cfg_graph.in_degree(x) == 1
1077
+ ]
1078
+
1079
+ for class_method in class_methods:
1080
+ class_method_name = st(class_method.child_by_field_name("name"))
1081
+ if class_method_name != class_name:
1082
+ for descendant in descendants:
1083
+ add_edge(cfg_graph, descendant, get_index(class_method, index))
1084
+
1085
+ rda_table = {}
1086
+ for root_node in traverse_tree(tree, variable_type):
1087
+ if not root_node.is_named:
1088
+ if root_node.type == "while" and root_node.parent.type == "do_statement":
1089
+ root_node = root_node.next_named_sibling
1090
+ parent_id = get_index(root_node, index)
1091
+ identifiers_used = recursively_get_children_of_types(
1092
+ root_node,
1093
+ variable_type,
1094
+ index=parser.index,
1095
+ stop_types=statement_types["statement_holders"],
1096
+ check_list=parser.symbol_table["scope_map"],
1097
+ )
1098
+ for identifier in identifiers_used:
1099
+ # if identifier.parent.type == "method_invocation":
1100
+ # continue
1101
+ add_entry(parser, rda_table, parent_id, used=identifier)
1102
+ else:
1103
+ continue
1104
+ if root_node.type == "catch_clause":
1105
+ parent_id = get_index(root_node, index)
1106
+ if len(root_node.named_children) > 1:
1107
+ identifiers_used = recursively_get_children_of_types(
1108
+ root_node.named_children[-2],
1109
+ variable_type,
1110
+ index=parser.index,
1111
+ check_list=parser.symbol_table["scope_map"],
1112
+ )
1113
+ add_entry(parser, rda_table, parent_id, defined=identifiers_used[-1])
1114
+ if root_node.type == "return_statement":
1115
+ parent_id = get_index(root_node, index)
1116
+ identifiers_used = recursively_get_children_of_types(
1117
+ root_node,
1118
+ variable_type,
1119
+ index=parser.index,
1120
+ check_list=parser.symbol_table["scope_map"],
1121
+ )
1122
+ for identifier in identifiers_used:
1123
+ if identifier.parent.type == "method_invocation":
1124
+ continue
1125
+ add_entry(parser, rda_table, parent_id, used=identifier)
1126
+ if root_node.type in def_statement:
1127
+ parent_statement = return_first_parent_of_types(
1128
+ root_node, statement_types["node_list_type"]
1129
+ )
1130
+ parent_id = get_index(parent_statement, index)
1131
+ if parent_statement is None:
1132
+ continue
1133
+ if parent_id not in CFG_results.graph.nodes:
1134
+ if parent_statement and parent_statement.type in inner_types:
1135
+ parent_statement = return_first_parent_of_types(
1136
+ parent_statement, statement_types["node_list_type"]
1137
+ )
1138
+ parent_id = get_index(parent_statement, index)
1139
+ elif parent_statement.type in handled_cases:
1140
+ continue
1141
+ else:
1142
+ raise NotImplementedError
1143
+ # print(parent_id)
1144
+ # print(st(parent_statement))
1145
+ if len(root_node.named_children) == 2:
1146
+ name = root_node.named_children[0]
1147
+ value = root_node.named_children[1]
1148
+ else:
1149
+ name = root_node.named_children[0]
1150
+ value = None
1151
+ add_entry(parser, rda_table, parent_id, defined=name, declaration=True)
1152
+ if value is not None:
1153
+ if value.type == "identifier":
1154
+ identifiers_used = [value]
1155
+ else:
1156
+ identifiers_used = recursively_get_children_of_types(
1157
+ value,
1158
+ variable_type,
1159
+ index=parser.index,
1160
+ stop_types=statement_types["statement_holders"],
1161
+ check_list=parser.symbol_table["scope_map"],
1162
+ )
1163
+ for identifier in identifiers_used:
1164
+ if identifier.parent.type == "method_invocation":
1165
+ continue
1166
+ add_entry(parser, rda_table, parent_id, used=identifier)
1167
+ elif root_node.type in assignment:
1168
+ parent_statement = return_first_parent_of_types(
1169
+ root_node, statement_types["node_list_type"]
1170
+ )
1171
+ parent_id = get_index(parent_statement, index)
1172
+ # print(parent_id)
1173
+ # print(st(parent_statement))
1174
+ left_nodes = root_node.child_by_field_name("left")
1175
+ right_node = root_node.child_by_field_name("right")
1176
+ operator_text = (
1177
+ root_node.text.split(left_nodes.text, 1)[-1]
1178
+ .rsplit(right_node.text, 1)[0]
1179
+ .strip()
1180
+ .decode()
1181
+ )
1182
+ right_nodes = [right_node]
1183
+ # JRef
1184
+ if parent_id not in CFG_results.graph.nodes:
1185
+ if parent_statement and parent_statement.type in inner_types:
1186
+ parent_statement = return_first_parent_of_types(
1187
+ parent_statement, statement_types["node_list_type"]
1188
+ )
1189
+ parent_id = get_index(parent_statement, index)
1190
+ elif parent_statement.type in handled_cases:
1191
+ continue
1192
+ else:
1193
+ raise NotImplementedError
1194
+ # operator = root_node.child()
1195
+ # operator_text = operator.text.decode('utf-8')
1196
+ if operator_text != "=":
1197
+ right_nodes.append(left_nodes)
1198
+ # TODO triage
1199
+ add_entry(parser, rda_table, parent_id, defined=left_nodes)
1200
+ for node in right_nodes:
1201
+ if node.type in variable_type:
1202
+ add_entry(parser, rda_table, parent_id, used=node)
1203
+ else:
1204
+ identifiers_used = recursively_get_children_of_types(
1205
+ node,
1206
+ variable_type,
1207
+ index=parser.index,
1208
+ stop_types=statement_types["statement_holders"],
1209
+ check_list=parser.symbol_table["scope_map"],
1210
+ )
1211
+ for identifier in identifiers_used:
1212
+ if identifier.parent.type == "method_invocation":
1213
+ continue
1214
+ add_entry(parser, rda_table, parent_id, used=identifier)
1215
+ elif root_node.type in increment_statement:
1216
+ parent_statement = return_first_parent_of_types(
1217
+ root_node, statement_types["node_list_type"]
1218
+ )
1219
+ parent_id = get_index(parent_statement, index)
1220
+ if parent_id not in CFG_results.graph.nodes:
1221
+ if parent_statement and parent_statement.type in inner_types:
1222
+ parent_statement = return_first_parent_of_types(
1223
+ parent_statement, statement_types["node_list_type"]
1224
+ )
1225
+ parent_id = get_index(parent_statement, index)
1226
+ elif parent_statement.type in handled_cases:
1227
+ continue
1228
+ else:
1229
+ raise NotImplementedError
1230
+ # print(parent_id)
1231
+ # print(st(parent_statement))
1232
+ if root_node.type in variable_type:
1233
+ add_entry(parser, rda_table, parent_id, used=root_node)
1234
+ else:
1235
+ identifiers_used = recursively_get_children_of_types(
1236
+ root_node,
1237
+ variable_type,
1238
+ index=parser.index,
1239
+ stop_types=statement_types["statement_holders"],
1240
+ check_list=parser.symbol_table["scope_map"],
1241
+ )
1242
+ for identifier in identifiers_used:
1243
+ if identifier.parent.type == "method_invocation":
1244
+ continue
1245
+ add_entry(parser, rda_table, parent_id, used=identifier)
1246
+ add_entry(parser, rda_table, parent_id, defined=identifier)
1247
+ elif root_node.type in method_calls:
1248
+ parent_statement = return_first_parent_of_types(
1249
+ root_node, statement_types["node_list_type"]
1250
+ )
1251
+ parent_id = get_index(parent_statement, index)
1252
+ if parent_id not in CFG_results.graph.nodes:
1253
+ if parent_statement is None:
1254
+ continue
1255
+ if parent_statement and parent_statement.type in inner_types:
1256
+ parent_statement = return_first_parent_of_types(
1257
+ parent_statement, statement_types["node_list_type"]
1258
+ )
1259
+ parent_id = get_index(parent_statement, index)
1260
+ elif parent_statement.type in handled_cases:
1261
+ continue
1262
+ else:
1263
+ raise NotImplementedError
1264
+ add_entry(
1265
+ parser,
1266
+ rda_table,
1267
+ parent_id,
1268
+ used=root_node.children[0],
1269
+ method_call=True,
1270
+ )
1271
+ for node in root_node.children[1:]:
1272
+ if node.type in variable_type:
1273
+ if return_first_parent_of_types(node, "method_invocation") is None:
1274
+ add_entry(parser, rda_table, parent_id, used=node)
1275
+ else:
1276
+ identifiers_used = recursively_get_children_of_types(
1277
+ node,
1278
+ variable_type,
1279
+ index=parser.index,
1280
+ stop_types=statement_types["statement_holders"],
1281
+ check_list=parser.symbol_table["scope_map"],
1282
+ )
1283
+ for identifier in identifiers_used:
1284
+ if identifier.parent.type == "method_invocation":
1285
+ continue
1286
+ add_entry(parser, rda_table, parent_id, used=identifier)
1287
+ elif root_node.type in method_declaration:
1288
+ parent_id = get_index(root_node, index)
1289
+ for child in root_node.named_children:
1290
+ # if root_node.type == "constructor_declaration":
1291
+ # if child.type == "identifier":
1292
+
1293
+ if child.type == "formal_parameters":
1294
+ for parameter in child.named_children:
1295
+ if parameter.type == "formal_parameter":
1296
+ identifier = parameter.child_by_field_name("name")
1297
+ add_entry(parser, rda_table, parent_id, defined=identifier)
1298
+ break
1299
+ elif root_node.type in switch_type:
1300
+ parent_statement = root_node
1301
+ parent_id = get_index(root_node, index)
1302
+ if parent_id not in CFG_results.graph.nodes:
1303
+ if parent_statement and parent_statement.type in inner_types:
1304
+ parent_statement = return_first_parent_of_types(
1305
+ parent_statement, statement_types["node_list_type"]
1306
+ )
1307
+ parent_id = get_index(parent_statement, index)
1308
+ elif parent_statement.type in handled_cases:
1309
+ continue
1310
+ else:
1311
+ raise NotImplementedError
1312
+ if parent_statement.type == "switch_expression":
1313
+ add_entry(parser, rda_table, parent_id, used=root_node.children[0])
1314
+ elif parent_statement.type == "switch_statement":
1315
+ case_node = parent_statement.child_by_field_name("value")
1316
+ add_entry(parser, rda_table, parent_id, used=case_node)
1317
+ elif root_node.type == "throw_statement":
1318
+ parent_statement = root_node
1319
+ parent_id = get_index(root_node, index)
1320
+ identifiers_used = recursively_get_children_of_types(
1321
+ parent_statement,
1322
+ variable_type,
1323
+ index=parser.index,
1324
+ stop_types=statement_types["statement_holders"],
1325
+ check_list=parser.symbol_table["scope_map"],
1326
+ )
1327
+ for identifier in identifiers_used:
1328
+ if identifier.parent.type == "method_invocation":
1329
+ continue
1330
+ add_entry(parser, rda_table, parent_id, used=identifier)
1331
+ elif root_node.type == "enhanced_for_statement":
1332
+ parent_statement = root_node
1333
+ parent_id = get_index(root_node, index)
1334
+ for i, child in enumerate(parent_statement.children):
1335
+ if child.parent.field_name_for_child(i) == "dimensions":
1336
+ defined_node = child
1337
+ add_entry(
1338
+ parser,
1339
+ rda_table,
1340
+ parent_id,
1341
+ defined=defined_node,
1342
+ declaration=True,
1343
+ )
1344
+ elif child.parent.field_name_for_child(i) == "value":
1345
+ used_node = child
1346
+ add_entry(parser, rda_table, parent_id, used=used_node)
1347
+ elif root_node.type == "for_statement":
1348
+ parent_statement = root_node
1349
+ parent_id = get_index(root_node, index)
1350
+ for i, child in enumerate(parent_statement.children):
1351
+ if child.parent.field_name_for_child(i) == "dimensions":
1352
+ defined_node = child
1353
+ add_entry(
1354
+ parser,
1355
+ rda_table,
1356
+ parent_id,
1357
+ defined=defined_node,
1358
+ declaration=True,
1359
+ )
1360
+ elif child.parent.field_name_for_child(i) == "value":
1361
+ used_node = child
1362
+ add_entry(parser, rda_table, parent_id, used=used_node)
1363
+ elif root_node.type == "object_creation_expression":
1364
+ parent_statement = return_first_parent_of_types(
1365
+ root_node, statement_types["node_list_type"]
1366
+ )
1367
+ parent_id = get_index(parent_statement, index)
1368
+ identifiers_used = recursively_get_children_of_types(
1369
+ root_node,
1370
+ variable_type,
1371
+ index=parser.index,
1372
+ check_list=parser.symbol_table["scope_map"],
1373
+ )
1374
+ for identifier in identifiers_used:
1375
+ if identifier.parent.type == "method_invocation":
1376
+ continue
1377
+ add_entry(parser, rda_table, parent_id, used=identifier)
1378
+ elif root_node.type == "lambda_expression":
1379
+ parent_statement = root_node
1380
+ parent_id = get_index(root_node, index)
1381
+ defined_nodes = parent_statement.child_by_field_name("parameters")
1382
+ if defined_nodes:
1383
+ for defined_node in defined_nodes.named_children:
1384
+ add_entry(
1385
+ parser,
1386
+ rda_table,
1387
+ parent_id,
1388
+ defined=defined_node,
1389
+ declaration=True,
1390
+ )
1391
+ else:
1392
+ # THIS ELSE IS VERY INEFFICIENT
1393
+ # Essentially considers all variable references as use
1394
+ # if return_first_parent_of_types(root_node, handled_types) is None:
1395
+ parent_statement = return_first_parent_of_types(
1396
+ root_node,
1397
+ # statement_types["node_list_type"],
1398
+ # [x for x in statement_types["node_list_type"] if x not in block_types],
1399
+ statement_types["non_control_statement"]
1400
+ + statement_types["control_statement"],
1401
+ stop_types=statement_types["statement_holders"] + handled_types,
1402
+ remap=False,
1403
+ )
1404
+ parent_id = get_index(parent_statement, index)
1405
+ if parent_id is None:
1406
+ continue
1407
+ if parent_id not in CFG_results.graph.nodes:
1408
+ if parent_statement and parent_statement.type in inner_types:
1409
+ parent_statement = return_first_parent_of_types(
1410
+ parent_statement, statement_types["node_list_type"]
1411
+ )
1412
+ parent_id = get_index(parent_statement, index)
1413
+ elif parent_statement.type in handled_cases:
1414
+ continue
1415
+ else:
1416
+ raise NotImplementedError
1417
+ # print(root_node.type)
1418
+ # print(parent_statement.type)
1419
+
1420
+ # print("...")
1421
+
1422
+ # print(parent_id)
1423
+ # print(st(parent_statement))
1424
+
1425
+ # if parent_statement and parent_statement.type in block_types:
1426
+ # continue
1427
+
1428
+ # if root_node.type in variable_type:
1429
+ # add_entry(parser, rda_table, parent_id, used=root_node)
1430
+ # else:
1431
+ identifiers_used = recursively_get_children_of_types(
1432
+ root_node,
1433
+ variable_type,
1434
+ stop_types=statement_types["statement_holders"] + handled_types,
1435
+ index=parser.index,
1436
+ check_list=parser.symbol_table["scope_map"],
1437
+ )
1438
+ for identifier in identifiers_used:
1439
+ if identifier.parent.type == "method_invocation":
1440
+ continue
1441
+ add_entry(parser, rda_table, parent_id, used=identifier)
1442
+ end_rda_init_time = time.time()
1443
+ end_rda_presolve_time = 0
1444
+ start_rda_presolve_time = 0
1445
+ end_alias_analysis_time = 0
1446
+ start_alias_analysis_time = 0
1447
+ if properties.get("alex_algo", True):
1448
+ start_rda_presolve_time = time.time()
1449
+ rda_solution = start_rda(index, rda_table, cfg_graph, pre_solve=True)
1450
+ # pp.pprint(rda_solution)
1451
+ final_graph = get_required_edges_from_def_to_use(
1452
+ index,
1453
+ cfg_graph,
1454
+ rda_solution,
1455
+ rda_table,
1456
+ cfg_graph.nodes,
1457
+ all_classes,
1458
+ additional_edges,
1459
+ processed_edges,
1460
+ pre_solve=True,
1461
+ properties=properties,
1462
+ )
1463
+ used_classes_or_methods = set()
1464
+ for edge in cfg_graph.edges:
1465
+ if "label" in cfg_graph.edges[edge] and cfg_graph.edges[edge]["label"] in [
1466
+ "method_call",
1467
+ "constructor_call",
1468
+ ]:
1469
+ final_graph.nodes[edge[0]][cfg_graph.edges[edge]["label"]] = edge[1]
1470
+ used_classes_or_methods.add(edge[1])
1471
+ end_rda_presolve_time = time.time()
1472
+ start_alias_analysis_time = time.time()
1473
+ al_analysis = set()
1474
+ proc_analysis = set()
1475
+
1476
+ for node in final_graph.nodes:
1477
+ if node not in used_classes_or_methods:
1478
+ continue
1479
+ if final_graph.nodes[node]["type_label"] == "method_declaration":
1480
+ if "main" in final_graph.nodes[node]["label"]:
1481
+ continue
1482
+ handled_node_leaf_pair = set()
1483
+ for leaf in nx.algorithms.dag.descendants(final_graph, node):
1484
+ if len([x for x in final_graph.edges(leaf) if x[0] != x[1]]) == 0:
1485
+ # print("Leaf: ", leaf)
1486
+ # final_graph.add_edge(leaf, "exit")
1487
+ # used_names = [n.name for n in rda_table[leaf]['def']]
1488
+ # if len(used_names) != 1:
1489
+ # logger.error("Multiple used names: %s", used_names)
1490
+ # get shortest path from node to leaf
1491
+ paths = nx.all_simple_paths(final_graph, node, leaf)
1492
+ # print("All_Simple: ", node, leaf)
1493
+ for path in paths:
1494
+ # get first edge in path
1495
+ first_edge = (path[0], path[1], 0)
1496
+ # get last edge in path
1497
+ last_edge = (path[-2], path[-1], 0)
1498
+ # get data for edge
1499
+ edge_for = final_graph.edges[first_edge]["used_def"]
1500
+ # get data for last edge
1501
+ edge_for_last = final_graph.edges[last_edge]["used_def"]
1502
+ defined_cores = [d.core for d in rda_table[leaf]["def"]]
1503
+ call_node = None
1504
+ # print("java:" + edge_for_last)
1505
+ if edge_for_last not in defined_cores:
1506
+ # "method_return", "class_return"
1507
+ if any(
1508
+ [
1509
+ x in final_graph.nodes[leaf]
1510
+ for x in ["method_call", "constructor_call"]
1511
+ ]
1512
+ ):
1513
+ if "method_call" in final_graph.nodes[leaf]:
1514
+ call_node = final_graph.nodes[leaf][
1515
+ "method_call"
1516
+ ]
1517
+ elif "constructor_call" in final_graph.nodes[leaf]:
1518
+ call_node = final_graph.nodes[leaf][
1519
+ "constructor_call"
1520
+ ]
1521
+ node_leaf_key = str(leaf) + "_" + str(edge_for)
1522
+ if node_leaf_key in handled_node_leaf_pair:
1523
+ continue
1524
+ handled_node_leaf_pair.add(node_leaf_key)
1525
+ if node in call_variable_map:
1526
+ if call_node:
1527
+ proc_analysis.add((node, leaf, edge_for, call_node))
1528
+ # al_analysis.append((node, leaf, edge_for, call_node))
1529
+ if edge_for_last not in defined_cores:
1530
+ n = -1
1531
+ while edge_for_last not in defined_cores:
1532
+ n = n - 1
1533
+ if abs(n - 1) > len(path):
1534
+ break
1535
+ last_edge = (path[n - 1], path[n], 0)
1536
+ edge_for_last = final_graph.edges[last_edge][
1537
+ "used_def"
1538
+ ]
1539
+ defined_cores = [
1540
+ d.core for d in rda_table[path[n]]["def"]
1541
+ ]
1542
+ if edge_for_last in defined_cores:
1543
+ al_analysis.add(
1544
+ (node, path[n], edge_for, None)
1545
+ )
1546
+ else:
1547
+ al_analysis.add((node, leaf, edge_for, call_node))
1548
+
1549
+ while proc_analysis:
1550
+ temp_proc_analysis = set()
1551
+ for node, leaf, edge_for, call_node in proc_analysis:
1552
+ completed_analysis = set()
1553
+ for al_entry in al_analysis:
1554
+ if al_entry[0] == call_node:
1555
+ mapped_node = call_variable(
1556
+ call_variable_map, call_node, edge_for, check_virtual=False
1557
+ )
1558
+ if al_entry[2] != st(mapped_node):
1559
+ continue
1560
+ leaf = al_entry[1]
1561
+ completed_analysis.add((node, leaf, edge_for, al_entry[3]))
1562
+ if al_entry[3] is not None:
1563
+ temp_proc_analysis.add((node, leaf, edge_for, al_entry[3]))
1564
+ al_analysis.update(completed_analysis)
1565
+ proc_analysis = temp_proc_analysis
1566
+
1567
+ for node, leaf, edge_for, call_node in al_analysis:
1568
+ mapped_node = call_variable(call_variable_map, node, edge_for)
1569
+ # print(st(mapped_node))
1570
+ if mapped_node:
1571
+ if mapped_node.type == "method_invocation":
1572
+ # if a reference is passed back it is ignored in alias analysis
1573
+ # to handle turn this into a while loop and trace the return chain
1574
+ # track_leaf = leaf
1575
+ # leaf_node = node_list[read_index(index, track_leaf)]
1576
+ # if leaf_node.type == "return_statement":
1577
+ # print("skipped")
1578
+ continue
1579
+ # [(st(a),st(b)) for a,b in call_variable_map[100]]
1580
+ # print(edge_for, final_graph.nodes[leaf]["label"])
1581
+ set_add(
1582
+ rda_table[leaf]["def"],
1583
+ Identifier(
1584
+ parser,
1585
+ mapped_node,
1586
+ leaf,
1587
+ full_ref=mapped_node,
1588
+ declaration=True,
1589
+ method_call=True,
1590
+ ),
1591
+ )
1592
+ end_alias_analysis_time = time.time()
1593
+ # print_table(index, rda_table)
1594
+ start_rda_time = time.time()
1595
+ rda_solution = start_rda(index, rda_table, cfg_graph)
1596
+ final_graph = get_required_edges_from_def_to_use(
1597
+ index,
1598
+ cfg_graph,
1599
+ rda_solution,
1600
+ rda_table,
1601
+ cfg_graph.nodes,
1602
+ all_classes,
1603
+ additional_edges,
1604
+ processed_edges,
1605
+ pre_solve=False,
1606
+ properties=properties,
1607
+ )
1608
+ end_rda_time = time.time()
1609
+ if debug:
1610
+ logger.warning(
1611
+ "RDA init, presolve, alias, rda: {}, {}, {}, {}",
1612
+ end_rda_init_time - start_rda_init_time,
1613
+ end_rda_presolve_time - start_rda_presolve_time,
1614
+ end_alias_analysis_time - start_alias_analysis_time,
1615
+ end_rda_time - start_rda_time,
1616
+ )
1617
+ debug_graph = rda_cfg_map(rda_solution, CFG_results)
1618
+ return final_graph, debug_graph, rda_table, rda_solution