1
1
package es .upv .mist .slicing .graphs .sdg ;
2
2
3
- import com .github .javaparser .ast .Node ;
4
3
import com .github .javaparser .ast .body .CallableDeclaration ;
5
4
import com .github .javaparser .ast .expr .Expression ;
6
5
import com .github .javaparser .ast .expr .ObjectCreationExpr ;
7
6
import com .github .javaparser .ast .expr .ThisExpr ;
7
+ import com .github .javaparser .resolution .Resolvable ;
8
+ import com .github .javaparser .resolution .declarations .ResolvedMethodLikeDeclaration ;
8
9
import es .upv .mist .slicing .graphs .CallGraph ;
9
10
import es .upv .mist .slicing .graphs .ExpressionObjectTreeFinder ;
10
11
import es .upv .mist .slicing .graphs .cfg .CFG ;
11
12
import es .upv .mist .slicing .nodes .GraphNode ;
12
- import es .upv .mist .slicing .nodes .ObjectTree ;
13
13
import es .upv .mist .slicing .nodes .VariableAction ;
14
- import es .upv .mist .slicing .nodes .VariableAction .Definition ;
15
14
import es .upv .mist .slicing .nodes .VariableAction .Movable ;
16
15
import es .upv .mist .slicing .nodes .VariableAction .Usage ;
17
16
import es .upv .mist .slicing .nodes .io .ActualIONode ;
20
19
21
20
import java .util .Map ;
22
21
import java .util .Objects ;
22
+ import java .util .Set ;
23
23
import java .util .function .Predicate ;
24
+ import java .util .stream .Collectors ;
24
25
import java .util .stream .Stream ;
25
26
26
27
/** An interprocedural usage finder, which adds the associated actions to formal and actual nodes in the CFGs. */
@@ -29,6 +30,32 @@ public InterproceduralUsageFinder(CallGraph callGraph, Map<CallableDeclaration<?
29
30
super (callGraph , cfgMap );
30
31
}
31
32
33
+ @ Override
34
+ public void save () {
35
+ super .save ();
36
+ markTransferenceToRoot ();
37
+ }
38
+
39
+ /** For every variable action -scope-in- or -arg-in- in the graph,
40
+ * runs {@link ExpressionObjectTreeFinder#locateAndMarkTransferenceToRoot(Expression, VariableAction)}. */
41
+ protected void markTransferenceToRoot () {
42
+ for (CallGraph .Edge <?> edge : graph .edgeSet ()) {
43
+ for (ActualIONode actualIn : locateActualInNode (edge )) {
44
+ for (VariableAction va : edge .getGraphNode ().getVariableActions ()) {
45
+ if (va instanceof Movable && ((Movable ) va ).getRealNode ().equals (actualIn )) {
46
+ ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder (edge .getGraphNode ());
47
+ if (va .getName ().equals ("-scope-in-" )) {
48
+ Expression scope = Objects .requireNonNullElseGet (actualIn .getArgument (), ThisExpr ::new );
49
+ finder .locateAndMarkTransferenceToRoot (scope , va );
50
+ } else if (va .getName ().equals ("-arg-in-" )) {
51
+ finder .locateAndMarkTransferenceToRoot (actualIn .getArgument (), va );
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+
32
59
@ Override
33
60
protected void handleFormalAction (CallGraph .Vertex vertex , Usage use ) {
34
61
CFG cfg = cfgMap .get (vertex .getDeclaration ());
@@ -43,42 +70,62 @@ protected void handleActualAction(CallGraph.Edge<?> edge, Usage use) {
43
70
if (use .isParameter ()) {
44
71
if (!use .isPrimitive ()) {
45
72
assert use .hasObjectTree ();
46
- ActualIONode actualIn = locateActualInNode (edge , use .getName ());
47
- Definition def = new Definition (VariableAction .DeclarationType .SYNTHETIC , "-arg-in-" , graphNode , (ObjectTree ) use .getObjectTree ().clone ());
48
- Movable movDef = new Movable (def , actualIn );
49
- graphNode .addVariableActionAfterLastMatchingRealNode (movDef , actualIn );
50
- ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder (graphNode );
51
- finder .locateAndMarkTransferenceToRoot (actualIn .getArgument (), def );
73
+ int index = ASTUtils .getMatchingParameterIndex (graph .getEdgeTarget (edge ).getDeclaration (), use .getName ());
74
+ VariableAction argIn = locateArgIn (graphNode , edge .getCall (), index );
75
+ argIn .getObjectTree ().addAll (use .getObjectTree ());
52
76
}
53
77
} else if (use .isField ()) {
54
78
if (use .isStatic ()) {
55
79
// Known limitation: static fields
56
80
} else {
57
81
// An object creation expression input an existing object via actual-in because it creates it.
58
82
assert !(edge .getCall () instanceof ObjectCreationExpr );
59
- ActualIONode actualIn = locateActualInNode (edge , use .getName ());
60
- Definition def = new Definition (VariableAction .DeclarationType .SYNTHETIC , "-scope-in-" , graphNode , (ObjectTree ) use .getObjectTree ().clone ());
61
- Movable movDef = new Movable (def , actualIn );
62
- Expression scope = Objects .requireNonNullElseGet (actualIn .getArgument (), ThisExpr ::new );
63
- graphNode .addVariableActionAfterLastMatchingRealNode (movDef , actualIn );
64
- ExpressionObjectTreeFinder finder = new ExpressionObjectTreeFinder (graphNode );
65
- finder .locateAndMarkTransferenceToRoot (scope , def );
83
+ VariableAction scopeIn = locateScopeIn (graphNode , edge .getCall ());
84
+ scopeIn .getObjectTree ().addAll (use .getObjectTree ());
66
85
}
67
86
} else {
68
87
throw new IllegalStateException ("Definition must be either from a parameter or a field!" );
69
88
}
70
89
}
71
90
72
- /** Locates the actual- in node associated with the given variable name and call edge . */
73
- protected ActualIONode locateActualInNode (CallGraph .Edge <?> edge , String name ) {
91
+ /** Find all actual in nodes in the given call. */
92
+ protected Set < ActualIONode > locateActualInNode (CallGraph .Edge <?> edge ) {
74
93
return edge .getGraphNode ().getSyntheticNodesInMovables ().stream ()
75
94
.filter (ActualIONode .class ::isInstance )
76
95
.map (ActualIONode .class ::cast )
77
96
.filter (ActualIONode ::isInput )
78
- .filter (actual -> actual .getVariableName ().equals (name ))
79
- .filter (actual -> ASTUtils .equalsWithRange (actual .getAstNode (), (Node ) edge .getCall ()))
80
- .findFirst ()
81
- .orElseThrow (() -> new IllegalStateException ("can't locate actual-in node" ));
97
+ .filter (actual -> ASTUtils .equalsWithRange (actual .getAstNode (), edge .getCall ()))
98
+ .collect (Collectors .toSet ());
99
+ }
100
+
101
+ /** Find the -arg-in- variable action that corresponds to the given node, call and index. */
102
+ protected VariableAction locateArgIn (GraphNode <?> graphNode , Resolvable <? extends ResolvedMethodLikeDeclaration > call , int index ) {
103
+ return locateActionIn (graphNode , call , index , "-arg-in-" );
104
+ }
105
+
106
+ /** Find the -scope-in- variable action that corresponds to the given node and call. */
107
+ protected VariableAction locateScopeIn (GraphNode <?> graphNode , Resolvable <? extends ResolvedMethodLikeDeclaration > call ) {
108
+ return locateActionIn (graphNode , call , 0 , "-scope-in-" );
109
+ }
110
+
111
+ /** Find the nth variable action from the given node and call that matches the given name. 0 represents the first occurrence. */
112
+ protected VariableAction locateActionIn (GraphNode <?> graphNode , Resolvable <? extends ResolvedMethodLikeDeclaration > call , int index , String actionName ) {
113
+ boolean inCall = false ;
114
+ for (VariableAction va : graphNode .getVariableActions ()) {
115
+ if (va instanceof VariableAction .CallMarker && ASTUtils .equalsWithRange (((VariableAction .CallMarker ) va ).getCall (), call )) {
116
+ if (((VariableAction .CallMarker ) va ).isEnter ())
117
+ inCall = true ;
118
+ else
119
+ break ; // The call has ended, can't find the action now
120
+ }
121
+ if (inCall && va .isDefinition () && va .getName ().equals (actionName )) {
122
+ if (index == 0 )
123
+ return va ;
124
+ else
125
+ index --;
126
+ }
127
+ }
128
+ throw new IllegalStateException ("Could not locate " + actionName + " for call " + call + " in node " + graphNode );
82
129
}
83
130
84
131
@ Override
0 commit comments