Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java

Issue 8905021: Dartest CL - Please review (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 package com.google.dart.compiler.ast;
2
3 import java.math.BigInteger;
4 import java.net.URI;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import com.google.dart.compiler.common.SourceInfo;
13 import com.google.dart.compiler.CommandLineOptions.CompilerOptions;
14 import com.google.dart.compiler.CompilerConfiguration;
15
16 /**
17 * CoverageInstrumenter contains specialized instrumenters to perform specific
18 * instrumentation for obtaining coverage of different program entities
19 */
20 public class CoverageInstrumenter {
21 private List<BaseInstrumenter> instrumenters;
22 private static final String[] ignoredLibs = { "corelib", "corelib_impl",
23 "dom", "html", "htmlimpl", "base", "touch", "view", "utilslib",
24 "observable", "layout.dart", "unittest", "dartest" };
25
26 // Only createInstance should be used to instantiate this class
27 private CoverageInstrumenter() {
28 }
29
30 /**
31 * Method to instantiate a CoverageInstrumenter containing multiple
32 * instrumenters created based on command line flags.
33 *
34 * @param config
35 * @return instance of this class
36 */
37 public static CoverageInstrumenter createInstance(
38 CompilerConfiguration config) {
39
40 CompilerOptions compilerOptions = config.getCompilerOptions();
41 String coverageTypes = compilerOptions.getCoverageType();
42
43 CoverageInstrumenter instr = new CoverageInstrumenter();
44 if (!"".equals(coverageTypes)) {
45 String outDir = compilerOptions.getWorkDirectory()
46 .getAbsolutePath();
47 instr.createInstrumenters(coverageTypes, outDir);
48 }
49 return instr;
50 }
51
52 /**
53 * Performs instrumentation of all classes
54 *
55 * @param libraries
56 */
57 public void process(Map<URI, LibraryUnit> libraries) {
58
59 if (instrumenters == null) {
60 return;
61 }
62
63 // Instrument all dart units
64 for (LibraryUnit lib : libraries.values()) {
65 for (DartUnit unit : lib.getUnits()) {
66 exec(unit);
67 }
68 }
69
70 // Populate totals and initialize coverage
71 for (LibraryUnit lib : libraries.values()) {
72 for (DartUnit unit : lib.getUnits()) {
73 init(unit);
74 }
75 }
76 }
77
78 /**
79 * Runs all instrumenters on a particular Dart unit
80 *
81 * @param unit
82 */
83 private void exec(DartUnit unit) {
84 if (isIgnored(unit)) {
85 return;
86 }
87 System.out.println("Instrumenting " + unit.getSourceName() + ", lib:"
zundel 2011/12/16 20:49:05 this looks like debugging... for a real dart prog
88 + unit.getLibrary().getName());
89 for (BaseInstrumenter instrumenter : instrumenters) {
90 instrumenter.accept(unit);
91 }
92 }
93
94 /**
95 * Ignores a Dart unit based on the library it belongs to
96 *
97 * @param unit
98 * @return true is the unit should be ignored
99 */
100 private boolean isIgnored(DartUnit unit) {
101 LibraryUnit lu = unit.getLibrary();
102 if (lu != null) {
103 String libName = lu.getName();
104 for (String ignoredLib : ignoredLibs) {
105 if (ignoredLib.equals(libName)) {
106 return true;
107 }
108 }
109 }
110 return false;
111 }
112
113 /**
114 * Runs the TotalSettingInstrumenter on the supplied Dart unit, which adds
115 * totals of all coverable program entities
116 *
117 * @param unit
118 */
119 private void init(DartUnit unit) {
120 if (isIgnored(unit)) {
121 return;
122 }
123 new TotalSettingInstrumenter().accept(unit);
124 }
125
126 /**
127 * Factory method to create instrumenters based on supplied command line
128 * configuration
129 *
130 * @param coverageTypes
131 * @param outDir
132 */
133 private void createInstrumenters(String coverageTypes, String outDir) {
134 BaseInstrumenter.setOutDir(outDir);
135 instrumenters = new ArrayList<BaseInstrumenter>();
136 if (coverageTypes.length() > 0) {
137 for (String covType : coverageTypes.split(",")) {
138 if ("all".equals(covType)) {
zundel 2011/12/16 20:49:05 instead of inlined strings, I'd make constants out
139 instrumenters.add(new StatementInstrumenter());
140 instrumenters.add(new FunctionInstrumenter());
141 instrumenters.add(new BranchInstrumenter());
142 }
143 if ("statement".equals(covType)) {
144 instrumenters.add(new StatementInstrumenter());
zundel 2011/12/16 20:49:05 is it going to cause problems if you add the same
145 }
146 if ("function".equals(covType)) {
147 instrumenters.add(new FunctionInstrumenter());
148 }
149 if ("branch".equals(covType)) {
150 instrumenters.add(new BranchInstrumenter());
151 }
152 }
153 }
154 }
155
156 /**
157 * The Base Instrumenter class that provides some common functionalities to
158 * all Instrumenters
159 */
160 private static class BaseInstrumenter extends DartModVisitor {
zundel 2011/12/16 20:49:05 FYI, we've been trying to replace instances of Dar
161 private static String outputDir;
162 protected DartUnit currentUnit;
163 protected static Set<String> unitsVisited = new HashSet<String>();
164 protected static Map<String, Integer> numFunctionsMap =
165 new HashMap<String, Integer>(),
zundel 2011/12/16 20:49:05 style nit: don't use the comma for followon declar
166 numStatementsMap = new HashMap<String, Integer>(),
167 numBranchesMap = new HashMap<String, Integer>();
168
169 public static void setOutDir(String outDir) {
170 outputDir = outDir;
171 }
172
173 @Override
174 public boolean visit(DartUnit x, DartContext ctx) {
175 currentUnit = x;
176 unitsVisited.add(x.getSourceName());
177 return super.visit(x, ctx);
178 }
179
180 /**
181 * Prepend a function call to a Dart block, which is a body of a
182 * function.
183 *
184 * @param oldBody
185 * @param functionStmt
186 * @return
187 */
188 protected DartBlock prependToFnBody(DartBlock oldBody,
189 DartExprStmt functionStmt) {
190 List<DartStatement> blockStmts = new ArrayList<DartStatement>();
191 blockStmts.add(functionStmt);
192 if (oldBody != null) {
193 List<DartStatement> stmts = oldBody.getStatements();
194 if (stmts != null) {
195 blockStmts.addAll(stmts);
196 }
197 }
198 DartBlock newDB = new DartBlock(blockStmts);
199 if (oldBody != null) {
200 newDB.setSourceInfo(oldBody.getSourceInfo());
201 }
202 return newDB;
203 }
204
205 protected void replaceFunction(DartContext ctx, DartFunction x,
206 DartBlock newFnBody) {
207 DartFunction newFn = new DartFunction(x.getParams(), newFnBody,
208 x.getReturnTypeNode());
209 newFn.setSourceInfo(x.getSourceInfo());
210 ctx.replaceMe(newFn);
211 }
212
213 protected DartExprStmt createFunctionCall(String functionName,
214 List<DartExpression> args, DartNode oldNode) {
215 DartIdentifier funcName = new DartIdentifier(functionName);
216 DartUnqualifiedInvocation funcInvocation = new DartUnqualifiedInvocation(
217 funcName, args);
218 DartExprStmt functionStmt = new DartExprStmt(funcInvocation);
219 if (oldNode != null) {
220 SourceInfo sourceInfo = oldNode.getSourceInfo();
221 setInstrumentedSourceInfo(functionStmt, sourceInfo);
222 setInstrumentedSourceInfo(funcInvocation, sourceInfo);
223 setInstrumentedSourceInfo(funcName, sourceInfo);
224 for (DartExpression arg : args) {
225 setInstrumentedSourceInfo(arg, sourceInfo);
226 }
227 }
228 return functionStmt;
229 }
230
231 void setInstrumentedSourceInfo(DartNode node, SourceInfo info) {
232 node.setInstrumentedNode(true);
233 node.setSourceInfo(info);
234 }
235 }
236
237 /**
238 * TotalSettingInstrumenter instruments the main function to initialize
239 * coverage variables and set totals for covered entities
240 */
241 private class TotalSettingInstrumenter extends BaseInstrumenter {
242
243 @Override
244 public boolean visit(DartFunction x, DartContext ctx) {
245 DartNode parent = x.getParent();
246 if (parent instanceof DartMethodDefinition) {
247 String funcName = ((DartMethodDefinition) parent).getName()
248 .toString();
249 if ("main".equals(funcName)) {
250 DartBlock newFnBody = x.getBody();
251
252 for (String unitName : unitsVisited) {
253 int numFunctions = nullCheckingUnBox(numFunctionsMap
254 .get(unitName));
255 int numStatements = nullCheckingUnBox(numStatementsMap
256 .get(unitName));
257 int numBranches = nullCheckingUnBox(numBranchesMap
258 .get(unitName));
259 List<DartExpression> args = new ArrayList<DartExpression>();
260 args.add(DartStringLiteral.get(unitName));
261 args.add(DartIntegerLiteral.get(BigInteger
262 .valueOf(numFunctions)));
263 args.add(DartIntegerLiteral.get(BigInteger
264 .valueOf(numStatements)));
265 args.add(DartIntegerLiteral.get(BigInteger
266 .valueOf(numBranches)));
267 DartExprStmt callCovTotals = createFunctionCall(
268 "setCoverageTotals", args, newFnBody);
269 callCovTotals.setInstrumentedNode(true);
270 newFnBody = prependToFnBody(newFnBody, callCovTotals);
271 }
272
273 replaceFunction(ctx, x, newFnBody);
274 }
275 }
276 return super.visit(x, ctx);
277 }
278
279 int nullCheckingUnBox(Integer value) {
280 int ret = 0;
281 if (value != null) {
282 ret = value.intValue();
283 }
284 return ret;
285 }
286 }
287
288 /**
289 * FunctionInstrumenter adds instrumentation to track function coverage
290 */
291 private class FunctionInstrumenter extends BaseInstrumenter {
292
293 private int numFunctions;
294
295 /**
296 * This visitor method transforms:
297 *
298 * myFunction(){ stmts; ... }
299 *
300 * to:
301 *
302 * myFunction(){ coverFunction('unit.dart', 'myFunction'); stmts; ... }
zundel 2011/12/16 20:49:05 You aren't covering closures here. Is that intenti
303 */
304 @Override
305 public boolean visit(DartFunction x, DartContext ctx) {
306 DartNode parent = x.getParent();
307 if (parent instanceof DartMethodDefinition) {
308 String funcName = ((DartMethodDefinition) parent).getName()
309 .toString();
310 DartBlock oldBody = x.getBody();
311 List<DartExpression> covArgs = new ArrayList<DartExpression>();
312 covArgs.add(DartStringLiteral.get(currentUnit.getSourceName()));
313 covArgs.add(DartStringLiteral.get(funcName));
314 DartExprStmt callCovFunc = createFunctionCall("coverFunction",
315 covArgs, oldBody);
316 DartBlock newFnBody = prependToFnBody(oldBody, callCovFunc);
317 replaceFunction(ctx, x, newFnBody);
318 numFunctions++;
319 }
320 return super.visit(x, ctx);
321 }
322
323 /**
324 * Initialize function counter
325 */
326 @Override
327 public boolean visit(DartUnit x, DartContext ctx) {
328 numFunctions = 0;
329 return super.visit(x, ctx);
330 }
331
332 /**
333 * Populate number of functions for current unit
334 */
335 @Override
336 public void endVisit(DartUnit x, DartContext ctx) {
337 numFunctionsMap.put(currentUnit.getSourceName(), numFunctions);
338 super.endVisit(x, ctx);
339 }
340
341 }
342
343 /**
344 * StatementInstrumenter adds instrumentation before each statement to
345 * capture runtime coverage of that statement
346 */
347 private class StatementInstrumenter extends BaseInstrumenter {
348 private int numStatements;
349
350 /**
351 * Initialize statement counter
352 */
353 @Override
354 public boolean visit(DartUnit x, DartContext ctx) {
355 numStatements = 0;
356 return super.visit(x, ctx);
357 }
358
359 /**
360 * Populate number of statements for current unit
361 */
362 @Override
363 public void endVisit(DartUnit x, DartContext ctx) {
364 numStatementsMap.put(currentUnit.getSourceName(), numStatements);
365 super.endVisit(x, ctx);
366 }
367
368 @Override
369 public boolean visit(DartBlock x, DartContext ctx) {
zundel 2011/12/16 20:49:05 it would be nice to add a big fat comment like you
370 List<DartStatement> newStmts = new ArrayList<DartStatement>();
371 for (DartStatement stmt : x.getStatements()) {
372 if (!stmt.isInstrumentedNode()) {
373 List<DartExpression> covArgs = new ArrayList<DartExpression>();
374 covArgs.add(DartStringLiteral.get(currentUnit
375 .getSourceName()));
376 covArgs.add(DartIntegerLiteral.get(BigInteger.valueOf(stmt
377 .getSourceLine())));
378 DartExprStmt callCoverStmt = createFunctionCall(
379 "coverStatement", covArgs, stmt);
380 newStmts.add(callCoverStmt);
381 }
382 newStmts.add(stmt);
383 numStatements++;
384 }
385 DartBlock newBlock = new DartBlock(newStmts);
386 ctx.replaceMe(newBlock);
387 return super.visit(x, ctx);
388 }
389
390 }
391
392 /**
393 * BranchInstrumenter captures runtime execution of each branch in the
394 * program by adding instrumentation at each branch point
395 */
396 private class BranchInstrumenter extends BaseInstrumenter {
397 private int numBranches;
398
399 @Override
400 public boolean visit(DartUnit x, DartContext ctx) {
401 numBranches = 0;
402 return super.visit(x, ctx);
403 }
404
405 @Override
406 public void endVisit(DartUnit x, DartContext ctx) {
407 numBranchesMap.put(currentUnit.getSourceName(), numBranches);
408 super.endVisit(x, ctx);
409 }
410
411 /**
412 * Post-order instrumentation is needed to handle nested ifs and
413 * synthetic else
414 */
415 @Override
416 public void endVisit(DartIfStatement x, DartContext ctx) {
zundel 2011/12/16 20:49:05 same comment as above - I'd appreciate seeing how
417 DartIfStatement newIfStmt;
418 DartStatement thenStmt = x.getThenStatement();
419 DartStatement elseStmt = x.getElseStatement();
420
421 List<DartStatement> newThen = doCallCoverBranch(thenStmt);
422 numBranches++;
423 if (thenStmt instanceof DartBlock) {
424 List<DartStatement> stmts = ((DartBlock) thenStmt)
425 .getStatements();
426 if (stmts != null) {
427 newThen.addAll(stmts);
428 }
429 } else {
430 newThen.add(thenStmt);
431 }
432
433 if (elseStmt instanceof DartIfStatement) {
434 newIfStmt = new DartIfStatement(x.getCondition(),
435 new DartBlock(newThen), elseStmt);
436 } else {
437 List<DartStatement> newElse;
438 if (elseStmt != null) {
439 newElse = doCallCoverBranch(elseStmt);
440 if (elseStmt instanceof DartBlock) {
441 List<DartStatement> stmts = ((DartBlock) elseStmt)
442 .getStatements();
443 if (stmts != null) {
444 newElse.addAll(stmts);
445 }
446 } else {
447 newElse.add(elseStmt);
448 }
449 } else {
450 // Although else block is missing, there is a branch which
451 // doesn't cover the IfStatement
452 // So, we need to add a synthetic else block to track that
453 newElse = doCallCoverBranch(x);
454 }
455 newIfStmt = new DartIfStatement(x.getCondition(),
456 new DartBlock(newThen), new DartBlock(newElse));
457 numBranches++;
458 }
459 newIfStmt.setSourceInfo(x.getSourceInfo());
460 ctx.replaceMe(newIfStmt);
461 super.endVisit(x, ctx);
462 }
463
464 /**
465 * This method instruments all non-empty switch case blocks and the
466 * default block. It inserts a synthetic default statement if one
467 * doesn't exist.
468 *
469 * For tracking branch on empty cases, this logic won't work directly
470 * since instrumenting empty cases will throw a FallThroughError at
471 * runtime. For achieving this, the switch needs to be transformed into
472 * an if. Its slightly complicated but here is what I think the
473 * transformation should be:
474 *
475 * switch(expr) {
476 * case 'a': // empty switch case
477 * case 'b': do1(); break;
zundel 2011/12/16 20:49:05 I didn't think you needed a break stmt in dart.
478 * case 'c': do2(); break;
479 * default: doDefault();
480 * }
481 *
482 * should be transformed to:
483 *
484 * var tmp = expr;
485 * if( (tmp == 'a' && coverBranch(..)) || (tmp == 'b' &&
486 * coverBranch(..))) {
487 * do1();
488 * } else if (tmp == 'a' && coverBranch(..)) {
489 * do2();
490 * } else {
491 * coverBranch(..);
492 * doDefault();
493 * }
494 *
495 */
496 @Override
497 public void endVisit(DartSwitchStatement x, DartContext ctx) {
498 List<DartSwitchMember> newSwitchMembers =
499 new ArrayList<DartSwitchMember>();
500 boolean hasDefault = false;
501 for (DartSwitchMember swMember : x.getMembers()) {
502 List<DartStatement> stmts = doCallCoverBranch(swMember);
503 List<DartStatement> oldStmts = swMember.getStatements();
504 if (oldStmts == null || oldStmts.size() == 0) {
505 newSwitchMembers.add(swMember);
506 continue; // Ignore empty cases
507 } else {
508 stmts.addAll(oldStmts);
509 }
510
511 assert (swMember instanceof DartCase ||
512 swMember instanceof DartDefault);
513
514 DartSwitchMember newMember;
515 if (swMember instanceof DartCase) {
516 newMember = new DartCase(((DartCase) swMember).getExpr(),
517 swMember.getLabel(), stmts);
518 } else {
519 hasDefault = true;
520 newMember = new DartDefault(swMember.getLabel(), stmts);
521 }
522 setInstrumentedSourceInfo(newMember, swMember);
523 newSwitchMembers.add(newMember);
524 numBranches++;
525 }
526
527 if (!hasDefault) {
528 List<DartStatement> statements = doCallCoverBranch(x);
529 DartSwitchMember defaultMember = new DartDefault(null,
530 statements);
531 newSwitchMembers.add(defaultMember);
532 numBranches++;
533 }
534
535 DartSwitchStatement newSwitch = new DartSwitchStatement(
536 x.getExpression(), newSwitchMembers);
537 newSwitch.setSourceInfo(x.getSourceInfo());
538
539 ctx.replaceMe(newSwitch);
540 super.visit(x, ctx);
541 }
542
543 @Override
544 public void endVisit(DartTryStatement x, DartContext ctx) {
545 DartBlock tryBlock = x.getTryBlock(), finallyBlock = x
546 .getFinallyBlock();
547 List<DartCatchBlock> catchBlocks = x.getCatchBlocks();
548
549 List<DartStatement> tryStmts = doCallCoverBranch(tryBlock);
550 if (tryBlock != null && tryBlock.getStatements() != null) {
551 tryStmts.addAll(tryBlock.getStatements());
552 }
553 DartBlock newTryBlock = new DartBlock(tryStmts);
554 setInstrumentedSourceInfo(newTryBlock, tryBlock.getSourceInfo());
555 numBranches++;
556
557 List<DartCatchBlock> newCatchBlocks = null;
558 if (catchBlocks != null) {
559 newCatchBlocks = new ArrayList<DartCatchBlock>();
560 for (DartCatchBlock cBlock : catchBlocks) {
561 DartBlock oldBlock = cBlock.getBlock();
562
563 List<DartStatement> cBlockStmts = doCallCoverBranch(cBlock);
564 if (oldBlock != null && oldBlock.getStatements() != null) {
565 cBlockStmts.addAll(oldBlock.getStatements());
566 }
567 DartBlock newBlock = new DartBlock(cBlockStmts);
568 setInstrumentedSourceInfo(newBlock,
569 oldBlock.getSourceInfo());
570
571 DartCatchBlock newCatchBlock = new DartCatchBlock(newBlock,
572 cBlock.getException(), cBlock.getStackTrace());
573 setInstrumentedSourceInfo(newCatchBlock,
574 cBlock.getSourceInfo());
575
576 newCatchBlocks.add(newCatchBlock);
577 numBranches++;
578 }
579 }
580
581 DartBlock newFinallyBlock = null;
582 if(finallyBlock != null){
583 List<DartStatement> finallyStmts = doCallCoverBranch(finallyBlock);
584 if(finallyBlock.getStatements() != null){
585 finallyStmts.addAll(finallyBlock.getStatements());
586 }
587 newFinallyBlock = new DartBlock(finallyStmts);
588 setInstrumentedSourceInfo(newFinallyBlock,
589 finallyBlock.getSourceInfo());
590 } else {
591 List<DartStatement> finallyStmts = doCallCoverBranch(x);
592 newFinallyBlock = new DartBlock(finallyStmts);
593 setInstrumentedSourceInfo(newFinallyBlock, x.getSourceInfo());
594 }
595 numBranches++;
596
597 DartTryStatement newTry = new DartTryStatement(tryBlock,
598 newCatchBlocks, newFinallyBlock);
599 ctx.replaceMe(newTry);
600 super.endVisit(x, ctx);
601 }
602
603 /**
604 * Rewrite all loops in this block
605 */
606 @Override
607 public void endVisit(DartBlock x, DartContext ctx) {
608 List<DartStatement> blockStmts = new ArrayList<DartStatement>();
609 for(DartStatement stmt : x.getStatements()) {
610 if(stmt instanceof DartForInStatement) {
611 doLoopBefore(stmt, blockStmts);
612
613 DartForInStatement oldForIn = (DartForInStatement) stmt;
614 DartStatement setup = null;
615 if(oldForIn.introducesVariable()){
616 setup = oldForIn.getVariableStatement();
617 } else {
618 setup = new DartExprStmt(oldForIn.getIdentifier());
619 }
620 DartBlock body = doLoopInside(stmt, oldForIn.getBody());
621 DartForInStatement newForIn =
622 new DartForInStatement(setup, oldForIn.getIterable(), body);
623 setInstrumentedSourceInfo(newForIn, oldForIn.getSourceInfo());
624
625 doLoopAfter(stmt, blockStmts);
626 numBranches+=2;
627 } else if (stmt instanceof DartForStatement) {
628 doLoopBefore(stmt, blockStmts);
629
630 DartForStatement oldFor = (DartForStatement) stmt;
631 DartBlock body = doLoopInside(stmt, oldFor.getBody());
632 DartForStatement newFor = new DartForStatement(oldFor.getInit(),
633 oldFor.getCondition(), oldFor.getIncrement(), body);
634 setInstrumentedSourceInfo(newFor, oldFor.getSourceInfo());
635
636 doLoopAfter(stmt, blockStmts);
637 numBranches+=2;
638 } else if (stmt instanceof DartWhileStatement) {
639 doLoopBefore(stmt, blockStmts);
640
641 DartWhileStatement oldWhile = (DartWhileStatement) stmt;
642 DartBlock body = doLoopInside(stmt, oldWhile.getBody());
643 DartWhileStatement newWhile =
644 new DartWhileStatement(oldWhile.getCondition(), body);
645 setInstrumentedSourceInfo(newWhile, oldWhile.getSourceInfo());
646
647 doLoopAfter(stmt, blockStmts);
648 numBranches+=2;
649 } else if (stmt instanceof DartDoWhileStatement) {
650 doLoopBefore(stmt, blockStmts);
651
652 DartDoWhileStatement oldDoWhile = (DartDoWhileStatement) stmt;
653 DartBlock body = doLoopInside(stmt, oldDoWhile.getBody());
654 DartDoWhileStatement newDoWhile =
655 new DartDoWhileStatement(oldDoWhile.getCondition(), body);
656 setInstrumentedSourceInfo(newDoWhile, oldDoWhile.getSourceInfo());
657
658 doLoopAfter(stmt, blockStmts);
659 numBranches+=2;
660 } else {
661 blockStmts.add(stmt);
662 }
663 }
664
665 super.visit(x, ctx);
666 }
667
668 /**
669 * Adds function call to track coverage of a branch represented by
670 * blockNode
671 *
672 * @param blockNode
673 * @return
674 */
675 private List<DartStatement> doCallCoverBranch(DartNode blockNode) {
676 List<DartStatement> newBlockStmts = new ArrayList<DartStatement>();
677 List<DartExpression> covArgs = makeCoverageArgs(blockNode);
678 DartExprStmt callCoverBranch = createFunctionCall("coverBranch",
679 covArgs, blockNode);
680 newBlockStmts.add(callCoverBranch);
681 setInstrumentedSourceInfo(callCoverBranch,
682 blockNode.getSourceInfo());
683 return newBlockStmts;
684 }
685
686 private void doLoopBefore(DartNode loopNode, List<DartStatement> stmts) {
687 List<DartExpression> args = makeCoverageArgs(loopNode);
688 DartExprStmt callLoopBefore =
689 createFunctionCall("loopBranchBefore", args, loopNode);
690 stmts.add(callLoopBefore);
691 }
692
693 private void doLoopAfter(DartNode loopNode, List<DartStatement> stmts) {
694 List<DartExpression> args = makeCoverageArgs(loopNode);
695 args.add(DartIntegerLiteral.get(BigInteger.valueOf(
696 loopNode.getSourceStart() + loopNode.getSourceLength())));
697 DartExprStmt callLoopAfter =
698 createFunctionCall("coverLoopBranch", args, loopNode);
699 stmts.add(callLoopAfter);
700 }
701
702 private DartBlock doLoopInside(DartNode loopNode, DartStatement body) {
703 List<DartStatement> newBlockStmts = new ArrayList<DartStatement>();
704 List<DartExpression> covArgs = makeCoverageArgs(loopNode);
705 DartExprStmt callCoverBranch = createFunctionCall("loopBranchInside",
706 covArgs, loopNode);
707 newBlockStmts.add(callCoverBranch);
708 setInstrumentedSourceInfo(callCoverBranch,
709 loopNode.getSourceInfo());
710
711 if(body instanceof DartBlock) {
712 newBlockStmts.addAll(((DartBlock) body).getStatements());
713 } else {
714 newBlockStmts.add(body);
715 }
716
717 return new DartBlock(newBlockStmts);
718 }
719 private List<DartExpression> makeCoverageArgs(DartNode blockNode) {
720 List<DartExpression> covArgs = new ArrayList<DartExpression>();
721 covArgs.add(DartStringLiteral.get(currentUnit.getSourceName()));
722 covArgs.add(DartIntegerLiteral.get(BigInteger.valueOf(blockNode
723 .getSourceLine())));
724 covArgs.add(DartIntegerLiteral.get(BigInteger.valueOf(blockNode
725 .getSourceStart())));
726 return covArgs;
727 }
728 }
729
730 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698