-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcg.py
94 lines (81 loc) · 3.52 KB
/
cg.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#
# Copyright (c) 2018-2021 FASTEN.
#
# This file is part of FASTEN
# (see https://www.fasten-project.eu/).
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
from stitcher.node import Node
class CallGraph:
def __init__(self, cg):
self.cg = cg
self.internal_calls = []
self.external_calls = []
self.nodes = {}
self.id_to_node = {}
self.product = self.cg["product"]
self.version = self.cg["version"]
self._parse_cg()
def get_node(self, modname, name):
if not self.nodes.get(modname, None):
return None
return self.nodes[modname].get(name, None)
def get_internal_calls(self):
return self.internal_calls
def get_external_calls(self):
return self.external_calls
def _parse_cg(self):
def iterate_mods(d, internal):
for mod_id, data in d.items():
if internal:
mod_node = Node(mod_id, product=self.product,
version=self.version)
modname = mod_node.get_modname()
else:
modname = mod_id
self.nodes[modname] = {}
for id, info in data["namespaces"].items():
super_cls = None
if info["metadata"].get("superClasses", None) != None:
super_cls = []
for cls in info["metadata"]["superClasses"]:
super_cls.append(Node(cls, product=self.product,
version=self.version))
first = None
last = None
if info["metadata"].get("first", None) != None:
first = info["metadata"].get("first")
last = info["metadata"].get("last")
node = Node(info["namespace"], product=self.product,
super_cls=super_cls, version=self.version, first=first, last=last)
self.id_to_node[id] = node
if node.get_modname():
self.nodes[node.get_modname()][node.get_callable()] = node
def iterate_calls(calls):
res = []
for src, dst, metadata in calls:
if self.id_to_node.get(src, None) and self.id_to_node.get(dst, None):
res.append([
self.id_to_node.get(src),
self.id_to_node.get(dst)])
return res
iterate_mods(self.cg["modules"]["internal"], True)
iterate_mods(self.cg["modules"]["external"], False)
self.internal_calls = iterate_calls(self.cg["graph"]["internalCalls"])
self.external_calls = iterate_calls(self.cg["graph"]["externalCalls"])