@@ -65,15 +65,9 @@ final class ProductionCoverageInstrumentationCallback
65
65
boolean visitedInstrumentCodeFile = false ;
66
66
67
67
private enum Type {
68
- FUNCTION ("Type.FUNCTION" ),
69
- BRANCH ("Type.BRANCH" ),
70
- BRANCH_DEFAULT ("Type.BRANCH_DEFAULT" );
71
-
72
- private String value ;
73
-
74
- Type (String s ){
75
- this .value = s ;
76
- }
68
+ FUNCTION (),
69
+ BRANCH (),
70
+ BRANCH_DEFAULT ();
77
71
}
78
72
79
73
/**
@@ -130,29 +124,34 @@ public void visit(NodeTraversal traversal, Node node, Node parent) {
130
124
// If the function node has been visited by visit() then we can be assured that all its
131
125
// children nodes have been visited and properly instrumented.
132
126
functionNameStack .pop ();
133
- instrumentBlockNode (node .getLastChild (), fileName , functionName , Type .FUNCTION . value );
127
+ instrumentBlockNode (node .getLastChild (), fileName , functionName , Type .FUNCTION );
134
128
break ;
135
129
case IF :
136
130
Node ifTrueNode = node .getSecondChild ();
137
- instrumentBlockNode (ifTrueNode , sourceFileName , functionName , Type .BRANCH . value );
131
+ instrumentBlockNode (ifTrueNode , sourceFileName , functionName , Type .BRANCH );
138
132
if (node .getChildCount () == 2 ) {
139
133
addElseBlock (node );
140
134
}
141
135
Node ifFalseNode = node .getLastChild ();
136
+ // The compiler converts all sets of If-Else if-Else blocks into a combination of nested
137
+ // If-Else blocks. This case checks if the else blocks first child is an If statement, and
138
+ // if it is it will not instrument. This avoids adding multiple instrumentation calls.
139
+ // Since we also make sure an Else case is added to every If statement, we are still
140
+ // assured that the else statement is being reached through a later instrumentation call.
142
141
if (NodeUtil .isEmptyBlock (ifFalseNode )
143
142
|| (ifFalseNode .getFirstChild () != null && !ifFalseNode .getFirstChild ().isIf ())) {
144
- instrumentBlockNode (ifFalseNode , sourceFileName , functionName , Type .BRANCH_DEFAULT . value );
143
+ instrumentBlockNode (ifFalseNode , sourceFileName , functionName , Type .BRANCH_DEFAULT );
145
144
}
146
145
break ;
147
146
case SWITCH :
148
147
boolean hasDefaultCase = false ;
149
148
for (Node c = node .getSecondChild (); c != null ; c = c .getNext ()) {
150
149
if (c .isDefaultCase ()) {
151
150
instrumentBlockNode (
152
- c .getLastChild (), sourceFileName , functionName , Type .BRANCH_DEFAULT . value );
151
+ c .getLastChild (), sourceFileName , functionName , Type .BRANCH_DEFAULT );
153
152
hasDefaultCase = true ;
154
153
} else {
155
- instrumentBlockNode (c .getLastChild (), sourceFileName , functionName , Type .BRANCH . value );
154
+ instrumentBlockNode (c .getLastChild (), sourceFileName , functionName , Type .BRANCH );
156
155
}
157
156
}
158
157
if (!hasDefaultCase ) {
@@ -161,17 +160,17 @@ public void visit(NodeTraversal traversal, Node node, Node parent) {
161
160
Node defaultCase = IR .defaultCase (defaultBlock ).useSourceInfoIfMissingFromForTree (node );
162
161
node .addChildToBack (defaultCase );
163
162
instrumentBlockNode (
164
- defaultBlock , sourceFileName , functionName , Type .BRANCH_DEFAULT . value );
163
+ defaultBlock , sourceFileName , functionName , Type .BRANCH_DEFAULT );
165
164
}
166
165
break ;
167
166
case HOOK :
168
167
Node ifTernaryIsTrueExpression = node .getSecondChild ();
169
168
Node ifTernaryIsFalseExpression = node .getLastChild ();
170
169
171
170
addInstrumentationNodeWithComma (
172
- ifTernaryIsTrueExpression , sourceFileName , functionName , Type .BRANCH . value );
171
+ ifTernaryIsTrueExpression , sourceFileName , functionName , Type .BRANCH );
173
172
addInstrumentationNodeWithComma (
174
- ifTernaryIsFalseExpression , sourceFileName , functionName , Type .BRANCH . value );
173
+ ifTernaryIsFalseExpression , sourceFileName , functionName , Type .BRANCH );
175
174
176
175
compiler .reportChangeToEnclosingScope (node );
177
176
break ;
@@ -183,15 +182,15 @@ public void visit(NodeTraversal traversal, Node node, Node parent) {
183
182
// already been instrumented.
184
183
Node secondExpression = node .getLastChild ();
185
184
addInstrumentationNodeWithComma (
186
- secondExpression , sourceFileName , functionName , Type .BRANCH . value );
185
+ secondExpression , sourceFileName , functionName , Type .BRANCH );
187
186
188
187
compiler .reportChangeToEnclosingScope (node );
189
188
break ;
190
189
default :
191
190
if (NodeUtil .isLoopStructure (node )) {
192
191
Node blockNode = NodeUtil .getLoopCodeBlock (node );
193
192
checkNotNull (blockNode );
194
- instrumentBlockNode (blockNode , sourceFileName , functionName , Type .BRANCH . value );
193
+ instrumentBlockNode (blockNode , sourceFileName , functionName , Type .BRANCH );
195
194
}
196
195
}
197
196
}
@@ -201,7 +200,7 @@ public void visit(NodeTraversal traversal, Node node, Node parent) {
201
200
* original node using a COMMA node.
202
201
*/
203
202
private void addInstrumentationNodeWithComma (
204
- Node originalNode , String fileName , String functionName , String type ) {
203
+ Node originalNode , String fileName , String functionName , Type type ) {
205
204
Node parentNode = originalNode .getParent ();
206
205
Node cloneOfOriginal = originalNode .cloneTree ();
207
206
Node newInstrumentationNode =
@@ -224,7 +223,7 @@ private void addInstrumentationNodeWithComma(
224
223
* @param fnName The function name of the node being instrumented.
225
224
* @param type The type of the node being instrumented.
226
225
*/
227
- private void instrumentBlockNode (Node block , String fileName , String fnName , String type ) {
226
+ private void instrumentBlockNode (Node block , String fileName , String fnName , Type type ) {
228
227
block .addChildToFront (newInstrumentationNode (block , fileName , fnName , type ));
229
228
compiler .reportChangeToEnclosingScope (block );
230
229
}
@@ -242,7 +241,7 @@ private void instrumentBlockNode(Node block, String fileName, String fnName, Str
242
241
* @param type The type of the node being instrumented.
243
242
* @return The newly constructed function call node.
244
243
*/
245
- private Node newInstrumentationNode (Node node , String fileName , String fnName , String type ) {
244
+ private Node newInstrumentationNode (Node node , String fileName , String fnName , Type type ) {
246
245
247
246
String encodedParam = parameterMapping .getEncodedParam (fileName , fnName , type );
248
247
@@ -312,18 +311,18 @@ private static final class ParameterMapping {
312
311
typeToIndex = new LinkedHashMap <>();
313
312
}
314
313
315
- private String getEncodedParam (String fileName , String functionName , String type ) {
314
+ private String getEncodedParam (String fileName , String functionName , Type type ) {
316
315
317
316
fileNameToIndex .putIfAbsent (fileName , fileNameToIndex .size ());
318
317
functionNameToIndex .putIfAbsent (functionName , functionNameToIndex .size ());
319
- typeToIndex .putIfAbsent (type , typeToIndex .size ());
318
+ typeToIndex .putIfAbsent (type . name () , typeToIndex .size ());
320
319
321
320
StringBuilder sb = new StringBuilder ();
322
321
323
322
try {
324
323
Base64VLQ .encode (sb , fileNameToIndex .get (fileName ));
325
324
Base64VLQ .encode (sb , functionNameToIndex .get (functionName ));
326
- Base64VLQ .encode (sb , typeToIndex .get (type ));
325
+ Base64VLQ .encode (sb , typeToIndex .get (type . name () ));
327
326
} catch (IOException e ) {
328
327
throw new AssertionError (e );
329
328
}
0 commit comments