Newer
Older
package edg;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import edg.edge.*;
import edg.graph.Node;
import edg.graph.EDG;
import edg.graph.Edge;
import edg.graph.LAST;
public class EDGFactory {
private final LAST last;
private EDG edg;
private final boolean interproceduralGraph;
public EDGFactory(LAST last) {
this(last, true);
}
public EDGFactory(LAST last, boolean interprocedural) {
this.interproceduralGraph = interprocedural;
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
}
// Required Configuration Parameters (Questions made to the users in order to decide the dependencies built on the graph)
private static boolean isOOLanguage = false;
public EDG createEDG()
{
initializeEDG();
if (isOOLanguage) {
// Only For OOPrograms With Inheritance and Types
// LASTBuilder.addInheritanceInformation(edg);
// LASTBuilder.completeFieldAccessTypes(edg);
// new DynamicTypesGenerator(edg).generate();
}
transformExpressionNodes();
generateDependencies();
return edg;
}
private void initializeEDG()
{
edg = new EDG(last);
}
private void transformExpressionNodes()
{
final List<Node> expressionNodes = edg.getNodes(node -> node.getInfo() != null &&
node.getInfo().isExpression());
for (Node expression : expressionNodes)
createNodeResultStructures(expression);
// TODO : When structural false edges are implemented, move this to LASTBuilder
edg.vertexSet().stream()
.filter(EDGFactory::isCallNode)
.forEach(node -> {
final Node parent = edg.getParent(node);
edg.removeEDGEdge(parent, node, Edge.Type.Structural);
edg.setRemovableEdge(parent, node, Edge.Type.Structural);
});
}
public static boolean isCallNode(Node node)
{
switch(node.getType())
{
case Scope:
case Name:
case Arguments:
case ArgumentIn:
return true;
default:
return false;
}
}
private void generateDependencies() {
new ControlEdgeGenerator(edg).generate();
long finalControl = System.nanoTime();
edg.getGenerationTime().setControlTime((finalControl-initialControl) / 1000000.0);
// WE ARE NOT GENERATING INTERPROCEDURAL EDGES
if (isOOLanguage)
new InterproceduralEdgeGenerator(edg).generate(); // Specially Generated for OOPrograms
else {
long initialInputOutput = System.nanoTime();
if (interproceduralGraph)
new InterproceduralEdgeGenerator(edg).generateErlang(); //
long finalInputOutput = System.nanoTime();
edg.getGenerationTime().setInterproceduralTime((finalInputOutput-initialInputOutput) / 1000000.0);
long initialFlow = System.nanoTime();
new FlowEdgeGenerator(edg).generate();
long finalFlow = System.nanoTime();
edg.getGenerationTime().setFlowTime((finalFlow-initialFlow) / 1000000.0);
new SummaryEdgeGenerator(edg).generateOnlyExternal();
// new ExceptionEdgeGenerator(edg).generate();
}
private void createNodeResultStructures(Node node)
{
// Conversion of 1 to 2 nodes & structural change
final LDASTNodeInfo nodeInfo = node.getInfo();
final LDASTNodeInfo ldNodeInfo = new LDASTNodeInfo(nodeInfo.getFile(), nodeInfo.getClassName(),
nodeInfo.getLine(), nodeInfo.getConstruction());
// Result Node
final Node result = new Node("result", edg.getNextFictitiousId(), node.getSDGId(), Node.Type.Result, "", ldNodeInfo);
final Node parent = last.getParent(node);
edg.addVertex(result);
edg.registerNodeResPair(node, result);
// Remove the Structural edges if the parent is an expression -> The hidden structural edges inside nodes remain in the graph
if (!parent.getType().isFictitious() && parent.getInfo().isExpression())
{
// THIS IS AN EXCEPTION IN ORDER TO INCLUDE ROUTINES IN THE SLICE
// WHEN CFG IS FINISHED THEY WILL BE INCLUDED BY CONTROL
if (parent.getType() != Node.Type.Routine)
{
edg.removeEDGEdge(parent, node, Edge.Type.Structural);
edg.setRemovableEdge(parent, node, Edge.Type.Structural);
}
}
// Add the structural edge parent -> result to perform tree traversal (not considered for slicing)
edg.addStructuralEdge(parent, result);
// Modify Value Arcs
if (node.getType() == Node.Type.DataConstructor && !edg.isPatternZone(node))
treatDataConstructorExpressions(node, result);
else
treatCommonNodes(node, result);
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// Value arcs between initial node and its result
edg.addEdge(node, result, Edge.Type.Value);
Set<Node.Type> specialResultTypes = Set.of(Node.Type.Routine, Node.Type.Clause);
if (specialResultTypes.contains(node.getType()))
{
createNodeResultStructuresSpecial(node, result);
return;
}
// Modify CFG Arcs to add Results to the CFG
final Set<Edge> outgoingCFGEdges = edg.outgoingEdgesOf(node);
outgoingCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge));
if (!outgoingCFGEdges.isEmpty())
edg.addEdge(node, result, Edge.Type.ControlFlow);
for (Edge cfgEdge : outgoingCFGEdges)
{
final Node to = edg.getEdgeTarget(cfgEdge);
edg.removeEdge(cfgEdge);
edg.addEdge(result, to, cfgEdge.getType());
}
}
private void createNodeResultStructuresSpecial(Node node, Node result)
{
switch(node.getType())
{
case Routine:
final Set<Edge> incomingCFGEdges = edg.incomingEdgesOf(node);
incomingCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge));
for (Edge cfgEdge : incomingCFGEdges)
{
final Node from = edg.getEdgeSource(cfgEdge);
edg.removeEdge(cfgEdge);
edg.addEdge(from,result, cfgEdge.getType());
}
break;
case Clause:
final Set<Edge> incomingClauseCFGEdges = edg.incomingEdgesOf(node);
incomingClauseCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge));
for (Edge cfgEdge : incomingClauseCFGEdges)
{
final Node from = edg.getEdgeSource(cfgEdge);
// ParameterOut type must be always connected to clause's result
if (from.getType() == Node.Type.ParameterOut)
{
edg.removeEdge(cfgEdge);
edg.addEdge(from, result, cfgEdge.getType());
}
}
final Set<Edge> outgoingClauseCFGEdges = edg.outgoingEdgesOf(node);
outgoingClauseCFGEdges.removeIf(Predicate.not(Edge::isControlFlowEdge));
for (Edge cfgEdge : outgoingClauseCFGEdges)
{
final Node finalToDestination = edg.getEdgeTarget(cfgEdge);
Node to = finalToDestination;
if (to.getType() == Node.Type.Result)
to = edg.getNodeFromRes(to);
if (to.getType() == Node.Type.Routine)
{
edg.removeEdge(cfgEdge);
edg.addEdge(result, finalToDestination, cfgEdge.getType());
}
}
break;
default:
throw new IllegalArgumentException("The node has not an allowed type: " +node.getType());
}
}
private void treatCommonNodes(Node node, Node result)
{
final Set<Edge> outgoingEdges = edg.outgoingEdgesOf(node);
outgoingEdges.removeIf(edge -> edge.getType() != Edge.Type.Value);
for (Edge valueEdge : outgoingEdges)
{
final Node to = edg.getEdgeTarget(valueEdge);
final EdgeConstraint edgeConstraint = valueEdge.getConstraint();
edg.removeEdge(valueEdge);
final Edge e = new Edge(Edge.Type.Value, edgeConstraint);
edg.addEdge(result, to, e);
}
final Set<Edge> incomingEdges = edg.incomingEdgesOf(node);
incomingEdges.removeIf(edge -> edge.getType() != Edge.Type.Value);
for (Edge valueEdge : incomingEdges)
{
final Node from = edg.getEdgeSource(valueEdge);
final EdgeConstraint edgeConstraint = valueEdge.getConstraint();
if (node.getType() != Node.Type.Clause || !(edgeConstraint instanceof LiteralConstraint))
edg.removeEdge(valueEdge);
final Edge e = new Edge(Edge.Type.Value, edgeConstraint);
edg.addEdge(from, result, e);
}
}
private void treatDataConstructorExpressions(Node dataConstructor, Node result)
{
deleteIncomingValueArcs(dataConstructor);
modifyDataConstructorArcs(dataConstructor, result);
}
private void deleteIncomingValueArcs(Node dataConstructor)
{
for (Edge edge : edg.incomingEdgesOf(dataConstructor))
if (edge.getType() == Edge.Type.Value)
edg.removeEdge(edge);
}
private void modifyDataConstructorArcs(Node dataConstructor, Node result)
{
final List<Node> dataConstructorChildren = edg.getChildrenNonResult(dataConstructor);
final int dataConstructorChildrenCount = dataConstructorChildren.size();
for (int childIndex = 0; childIndex < dataConstructorChildrenCount; childIndex++)
{
final Node dataConstructorChild = edg.getResFromNode(dataConstructorChildren.get(childIndex));
final DataConstructorConstraint constraint = new DataConstructorConstraint(
AccessConstraint.Operation.Remove, childIndex + "/" + (dataConstructorChildrenCount-1));
edg.addEdge(dataConstructorChild, result, new Edge(Edge.Type.Value, constraint));
}
final Set<Edge> outgoingEdges = edg.outgoingEdgesOf(dataConstructor);
outgoingEdges.removeIf(edge -> edge.getType() != Edge.Type.Value);
for (Edge valueEdge : outgoingEdges)
{
final Node from = edg.getEdgeSource(valueEdge);
final Node to = edg.getEdgeTarget(valueEdge);
final EdgeConstraint edgeConstraint = valueEdge.getConstraint();
edg.removeEdge(valueEdge);
final Edge e = new Edge(Edge.Type.Value, edgeConstraint);
edg.addEdge(result, to, e);
}
}
}