Index: compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java |
diff --git a/compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java b/compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java |
deleted file mode 100644 |
index b1ef94c1ce5db16cd59217ca5e6d70dd47997035..0000000000000000000000000000000000000000 |
--- a/compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java |
+++ /dev/null |
@@ -1,807 +0,0 @@ |
-package com.google.dart.compiler.ast; |
- |
-import java.math.BigInteger; |
-import java.net.URI; |
-import java.util.ArrayList; |
-import java.util.HashMap; |
-import java.util.HashSet; |
-import java.util.List; |
-import java.util.Map; |
-import java.util.Set; |
- |
-import com.google.dart.compiler.common.SourceInfo; |
-import com.google.dart.compiler.CommandLineOptions.CompilerOptions; |
-import com.google.dart.compiler.CompilerConfiguration; |
- |
-/** |
- * CoverageInstrumenter contains specialized instrumenters to perform specific |
- * instrumentation for obtaining coverage of different program entities |
- */ |
-public class CoverageInstrumenter { |
- private List<BaseInstrumenter> instrumenters; |
- private static final String[] ignoredLibs = { "corelib", "corelib_impl", |
- "dom", "html", "htmlimpl", "base", "touch", "view", "utilslib", |
- "observable", "layout.dart", "unittest", "dartest" }; |
- |
- private static final String functionCoverage = "function"; |
- private static final String statementCoverage = "statement"; |
- private static final String branchCoverage = "branch"; |
- private static final String allCoverage = "all"; |
- |
- // Only createInstance should be used to instantiate this class |
- private CoverageInstrumenter() { |
- } |
- |
- /** |
- * Method to instantiate a CoverageInstrumenter containing multiple |
- * instrumenters created based on command line flags. |
- * |
- * @param config |
- * @return instance of this class |
- */ |
- public static CoverageInstrumenter createInstance( |
- CompilerConfiguration config) { |
- |
- CompilerOptions compilerOptions = config.getCompilerOptions(); |
- String coverageTypes = compilerOptions.getCoverageType(); |
- |
- CoverageInstrumenter instr = new CoverageInstrumenter(); |
- if (!"".equals(coverageTypes)) { |
- String outDir = compilerOptions.getWorkDirectory() |
- .getAbsolutePath(); |
- instr.createInstrumenters(coverageTypes, outDir); |
- } |
- return instr; |
- } |
- |
- /** |
- * Performs instrumentation of all classes |
- * |
- * @param libraries |
- */ |
- public void process(Map<URI, LibraryUnit> libraries) { |
- |
- if (instrumenters == null) { |
- return; |
- } |
- |
- // Instrument all dart units |
- for (LibraryUnit lib : libraries.values()) { |
- for (DartUnit unit : lib.getUnits()) { |
- exec(unit); |
- } |
- } |
- |
- // Populate totals and initialize coverage |
- for (LibraryUnit lib : libraries.values()) { |
- for (DartUnit unit : lib.getUnits()) { |
- init(unit); |
- } |
- } |
- } |
- |
- /** |
- * Runs all instrumenters on a particular Dart unit |
- * |
- * @param unit |
- */ |
- private void exec(DartUnit unit) { |
- if (isIgnored(unit)) { |
- return; |
- } |
- System.out.println("Instrumenting " + unit.getSourceName() + ", lib:" |
- + unit.getLibrary().getName()); |
- for (BaseInstrumenter instrumenter : instrumenters) { |
- instrumenter.accept(unit); |
- } |
- } |
- |
- /** |
- * Ignores a Dart unit based on the library it belongs to |
- * |
- * @param unit |
- * @return true is the unit should be ignored |
- */ |
- private boolean isIgnored(DartUnit unit) { |
- LibraryUnit lu = unit.getLibrary(); |
- if (lu != null) { |
- String libName = lu.getName(); |
- for (String ignoredLib : ignoredLibs) { |
- if (ignoredLib.equals(libName)) { |
- return true; |
- } |
- } |
- } |
- return false; |
- } |
- |
- /** |
- * Runs the TotalSettingInstrumenter on the supplied Dart unit, which adds |
- * totals of all coverable program entities |
- * |
- * @param unit |
- */ |
- private void init(DartUnit unit) { |
- if (isIgnored(unit)) { |
- return; |
- } |
- new TotalSettingInstrumenter().accept(unit); |
- } |
- |
- /** |
- * Factory method to create instrumenters based on supplied command line |
- * configuration |
- * |
- * @param coverageTypes |
- * @param outDir |
- */ |
- private void createInstrumenters(String coverageTypes, String outDir) { |
- BaseInstrumenter.setOutDir(outDir); |
- instrumenters = new ArrayList<BaseInstrumenter>(); |
- if (coverageTypes.length() > 0) { |
- for (String covType : coverageTypes.split(",")) { |
- if (allCoverage.equals(covType)) { |
- instrumenters.add(new StatementInstrumenter()); |
- instrumenters.add(new FunctionInstrumenter()); |
- instrumenters.add(new BranchInstrumenter()); |
- } |
- if (statementCoverage.equals(covType)) { |
- instrumenters.add(new StatementInstrumenter()); |
- } |
- if (functionCoverage.equals(covType)) { |
- instrumenters.add(new FunctionInstrumenter()); |
- } |
- if (branchCoverage.equals(covType)) { |
- instrumenters.add(new BranchInstrumenter()); |
- } |
- } |
- } |
- } |
- |
- /** |
- * The Base Instrumenter class that provides some common functionalities to |
- * all Instrumenters |
- */ |
- private static class BaseInstrumenter extends DartModVisitor { |
- // TODO: Switch to DartNodeTraverser |
- private static String outputDir; |
- protected DartUnit currentUnit; |
- protected static Set<String> unitsVisited = new HashSet<String>(); |
- protected static Map<String, Integer> numFunctionsMap = |
- new HashMap<String, Integer>(); |
- protected static Map<String, Integer> numStatementsMap = |
- new HashMap<String, Integer>(); |
- protected static Map<String, Integer> numBranchesMap = |
- new HashMap<String, Integer>(); |
- |
- public static void setOutDir(String outDir) { |
- outputDir = outDir; |
- } |
- |
- @Override |
- public boolean visit(DartUnit x, DartContext ctx) { |
- currentUnit = x; |
- unitsVisited.add(x.getSourceName()); |
- return super.visit(x, ctx); |
- } |
- |
- /** |
- * Prepend a function call to a Dart block, which is a body of a |
- * function. |
- * |
- * @param oldBody |
- * @param functionStmt |
- * @return |
- */ |
- protected DartBlock prependToFnBody(DartBlock oldBody, |
- DartExprStmt functionStmt) { |
- List<DartStatement> blockStmts = new ArrayList<DartStatement>(); |
- blockStmts.add(functionStmt); |
- if (oldBody != null) { |
- List<DartStatement> stmts = oldBody.getStatements(); |
- if (stmts != null) { |
- blockStmts.addAll(stmts); |
- } |
- } |
- DartBlock newDB = new DartBlock(blockStmts); |
- if (oldBody != null) { |
- newDB.setSourceInfo(oldBody.getSourceInfo()); |
- } |
- return newDB; |
- } |
- |
- protected void replaceFunction(DartContext ctx, DartFunction x, |
- DartBlock newFnBody) { |
- DartFunction newFn = new DartFunction(x.getParams(), newFnBody, |
- x.getReturnTypeNode()); |
- newFn.setSourceInfo(x.getSourceInfo()); |
- ctx.replaceMe(newFn); |
- } |
- |
- protected DartExprStmt createFunctionCall(String functionName, |
- List<DartExpression> args, DartNode oldNode) { |
- DartIdentifier funcName = new DartIdentifier(functionName); |
- DartUnqualifiedInvocation funcInvocation = new DartUnqualifiedInvocation( |
- funcName, args); |
- DartExprStmt functionStmt = new DartExprStmt(funcInvocation); |
- if (oldNode != null) { |
- SourceInfo sourceInfo = oldNode.getSourceInfo(); |
- setInstrumentedSourceInfo(functionStmt, sourceInfo); |
- setInstrumentedSourceInfo(funcInvocation, sourceInfo); |
- setInstrumentedSourceInfo(funcName, sourceInfo); |
- for (DartExpression arg : args) { |
- setInstrumentedSourceInfo(arg, sourceInfo); |
- } |
- } |
- return functionStmt; |
- } |
- |
- void setInstrumentedSourceInfo(DartNode node, SourceInfo info) { |
- node.setInstrumentedNode(true); |
- node.setSourceInfo(info); |
- } |
- } |
- |
- /** |
- * TotalSettingInstrumenter instruments the main function to initialize |
- * coverage variables and set totals for covered entities |
- */ |
- private class TotalSettingInstrumenter extends BaseInstrumenter { |
- |
- @Override |
- public boolean visit(DartFunction x, DartContext ctx) { |
- DartNode parent = x.getParent(); |
- if (parent instanceof DartMethodDefinition) { |
- String funcName = ((DartMethodDefinition) parent).getName() |
- .toString(); |
- if ("main".equals(funcName)) { |
- DartBlock newFnBody = x.getBody(); |
- |
- for (String unitName : unitsVisited) { |
- int numFunctions = nullCheckingUnBox(numFunctionsMap |
- .get(unitName)); |
- int numStatements = nullCheckingUnBox(numStatementsMap |
- .get(unitName)); |
- int numBranches = nullCheckingUnBox(numBranchesMap |
- .get(unitName)); |
- List<DartExpression> args = new ArrayList<DartExpression>(); |
- args.add(DartStringLiteral.get(unitName)); |
- args.add(DartIntegerLiteral.get(BigInteger |
- .valueOf(numFunctions))); |
- args.add(DartIntegerLiteral.get(BigInteger |
- .valueOf(numStatements))); |
- args.add(DartIntegerLiteral.get(BigInteger |
- .valueOf(numBranches))); |
- DartExprStmt callCovTotals = createFunctionCall( |
- "setCoverageTotals", args, newFnBody); |
- callCovTotals.setInstrumentedNode(true); |
- newFnBody = prependToFnBody(newFnBody, callCovTotals); |
- } |
- |
- replaceFunction(ctx, x, newFnBody); |
- } |
- } |
- return super.visit(x, ctx); |
- } |
- |
- int nullCheckingUnBox(Integer value) { |
- int ret = 0; |
- if (value != null) { |
- ret = value.intValue(); |
- } |
- return ret; |
- } |
- } |
- |
- /** |
- * FunctionInstrumenter adds instrumentation to track function coverage |
- */ |
- private class FunctionInstrumenter extends BaseInstrumenter { |
- |
- private int numFunctions; |
- |
- /** |
- * This visitor method transforms: |
- * |
- * myFunction(){ stmts; ... } |
- * |
- * to: |
- * |
- * myFunction(){ coverFunction('unit.dart', 'myFunction'); stmts; ... } |
- * |
- * TODO: Cover closures as well |
- */ |
- @Override |
- public boolean visit(DartFunction x, DartContext ctx) { |
- DartNode parent = x.getParent(); |
- if (parent instanceof DartMethodDefinition) { |
- String funcName = ((DartMethodDefinition) parent).getName() |
- .toString(); |
- DartBlock oldBody = x.getBody(); |
- List<DartExpression> covArgs = new ArrayList<DartExpression>(); |
- covArgs.add(DartStringLiteral.get(currentUnit.getSourceName())); |
- covArgs.add(DartStringLiteral.get(funcName)); |
- DartExprStmt callCovFunc = createFunctionCall("coverFunction", |
- covArgs, oldBody); |
- DartBlock newFnBody = prependToFnBody(oldBody, callCovFunc); |
- replaceFunction(ctx, x, newFnBody); |
- numFunctions++; |
- } |
- return super.visit(x, ctx); |
- } |
- |
- /** |
- * Initialize function counter |
- */ |
- @Override |
- public boolean visit(DartUnit x, DartContext ctx) { |
- numFunctions = 0; |
- return super.visit(x, ctx); |
- } |
- |
- /** |
- * Populate number of functions for current unit |
- */ |
- @Override |
- public void endVisit(DartUnit x, DartContext ctx) { |
- numFunctionsMap.put(currentUnit.getSourceName(), numFunctions); |
- super.endVisit(x, ctx); |
- } |
- |
- } |
- |
- /** |
- * StatementInstrumenter adds instrumentation before each statement to |
- * capture runtime coverage of that statement |
- */ |
- private class StatementInstrumenter extends BaseInstrumenter { |
- private int numStatements; |
- |
- /** |
- * Initialize statement counter |
- */ |
- @Override |
- public boolean visit(DartUnit x, DartContext ctx) { |
- numStatements = 0; |
- return super.visit(x, ctx); |
- } |
- |
- /** |
- * Populate number of statements for current unit |
- */ |
- @Override |
- public void endVisit(DartUnit x, DartContext ctx) { |
- numStatementsMap.put(currentUnit.getSourceName(), numStatements); |
- super.endVisit(x, ctx); |
- } |
- |
- /** |
- * This visitor method transforms: |
- * |
- * { stmts; ... } |
- * |
- * to: |
- * |
- * { coverStatement('unit.dart', lineNum1); stmt1; |
- * coverStatement('unit.dart', lineNum2); stmt2; |
- * ... } |
- * |
- */ |
- @Override |
- public boolean visit(DartBlock x, DartContext ctx) { |
- List<DartStatement> newStmts = new ArrayList<DartStatement>(); |
- for (DartStatement stmt : x.getStatements()) { |
- if (!stmt.isInstrumentedNode()) { |
- List<DartExpression> covArgs = new ArrayList<DartExpression>(); |
- covArgs.add(DartStringLiteral.get(currentUnit |
- .getSourceName())); |
- covArgs.add(DartIntegerLiteral.get(BigInteger.valueOf(stmt |
- .getSourceLine()))); |
- DartExprStmt callCoverStmt = createFunctionCall( |
- "coverStatement", covArgs, stmt); |
- newStmts.add(callCoverStmt); |
- } |
- newStmts.add(stmt); |
- numStatements++; |
- } |
- DartBlock newBlock = new DartBlock(newStmts); |
- ctx.replaceMe(newBlock); |
- return super.visit(x, ctx); |
- } |
- |
- } |
- |
- /** |
- * BranchInstrumenter captures runtime execution of each branch in the |
- * program by adding instrumentation at each branch point |
- */ |
- private class BranchInstrumenter extends BaseInstrumenter { |
- private int numBranches; |
- |
- @Override |
- public boolean visit(DartUnit x, DartContext ctx) { |
- numBranches = 0; |
- return super.visit(x, ctx); |
- } |
- |
- @Override |
- public void endVisit(DartUnit x, DartContext ctx) { |
- numBranchesMap.put(currentUnit.getSourceName(), numBranches); |
- super.endVisit(x, ctx); |
- } |
- |
- /** |
- * |
- * This visitor method transforms: |
- * |
- * if { stmts; ... } |
- * else { ... } |
- * |
- * to: |
- * |
- * if { coverBranch('unit.dart', lineNum1, startLineNum); stmts; ... } |
- * else { coverBranch('unit.dart', lineNum1, startLineNum); ... } |
- * |
- * A synthetic else is added to track the non-if branch if there is no else |
- * |
- * Post-order instrumentation is needed to handle nested ifs and |
- * synthetic else |
- */ |
- @Override |
- public void endVisit(DartIfStatement x, DartContext ctx) { |
- DartIfStatement newIfStmt; |
- DartStatement thenStmt = x.getThenStatement(); |
- DartStatement elseStmt = x.getElseStatement(); |
- |
- List<DartStatement> newThen = doCallCoverBranch(thenStmt); |
- numBranches++; |
- if (thenStmt instanceof DartBlock) { |
- List<DartStatement> stmts = ((DartBlock) thenStmt) |
- .getStatements(); |
- if (stmts != null) { |
- newThen.addAll(stmts); |
- } |
- } else { |
- newThen.add(thenStmt); |
- } |
- |
- if (elseStmt instanceof DartIfStatement) { |
- newIfStmt = new DartIfStatement(x.getCondition(), |
- new DartBlock(newThen), elseStmt); |
- } else { |
- List<DartStatement> newElse; |
- if (elseStmt != null) { |
- newElse = doCallCoverBranch(elseStmt); |
- if (elseStmt instanceof DartBlock) { |
- List<DartStatement> stmts = ((DartBlock) elseStmt) |
- .getStatements(); |
- if (stmts != null) { |
- newElse.addAll(stmts); |
- } |
- } else { |
- newElse.add(elseStmt); |
- } |
- } else { |
- // Although else block is missing, there is a branch which |
- // doesn't cover the IfStatement |
- // So, we need to add a synthetic else block to track that |
- newElse = doCallCoverBranch(x); |
- } |
- newIfStmt = new DartIfStatement(x.getCondition(), |
- new DartBlock(newThen), new DartBlock(newElse)); |
- numBranches++; |
- } |
- newIfStmt.setSourceInfo(x.getSourceInfo()); |
- ctx.replaceMe(newIfStmt); |
- super.endVisit(x, ctx); |
- } |
- |
- /** |
- * This method instruments all non-empty switch case blocks and the |
- * default block. It inserts a synthetic default statement if one |
- * doesn't exist. |
- * This visitor method transforms: |
- * |
- * switch(var a) { |
- * case a: ...; |
- * case b: ...; |
- * } |
- * |
- * to: |
- * |
- * switch(var a) { |
- * case a: coverBranch('unit.dart', lineNum1, startLineNum1); ...; |
- * case b: coverBranch('unit.dart', lineNum2, startLineNum2); ...; |
- * default: coverBranch('unit.dart', lineNum3, startLineNum3); ...; |
- * } |
- * |
- * The existing code ignores empty switch cases. |
- * |
- * For tracking branch on empty cases, this logic won't work directly |
- * since instrumenting empty cases will throw a FallThroughError at |
- * runtime. For achieving this, the switch needs to be transformed into |
- * an if. Its slightly complicated but here is what I think the |
- * transformation should be: |
- * |
- * switch(expr) { |
- * case 'a': // empty switch case |
- * case 'b': do1(); break; |
- * case 'c': do2(); break; |
- * default: doDefault(); |
- * } |
- * |
- * should be transformed to: |
- * |
- * var tmp = expr; |
- * if( (tmp == 'a' && coverBranch(..)) || (tmp == 'b' && |
- * coverBranch(..))) { |
- * do1(); |
- * } else if (tmp == 'a' && coverBranch(..)) { |
- * do2(); |
- * } else { |
- * coverBranch(..); |
- * doDefault(); |
- * } |
- * |
- * However, I don't see much value in covering empty cases and hence |
- * this was written like described. |
- */ |
- @Override |
- public void endVisit(DartSwitchStatement x, DartContext ctx) { |
- List<DartSwitchMember> newSwitchMembers = |
- new ArrayList<DartSwitchMember>(); |
- boolean hasDefault = false; |
- for (DartSwitchMember swMember : x.getMembers()) { |
- List<DartStatement> stmts = doCallCoverBranch(swMember); |
- List<DartStatement> oldStmts = swMember.getStatements(); |
- if (oldStmts == null || oldStmts.size() == 0) { |
- newSwitchMembers.add(swMember); |
- continue; // Ignore empty cases |
- } else { |
- stmts.addAll(oldStmts); |
- } |
- |
- assert (swMember instanceof DartCase || |
- swMember instanceof DartDefault); |
- |
- DartSwitchMember newMember; |
- if (swMember instanceof DartCase) { |
- newMember = new DartCase(((DartCase) swMember).getExpr(), |
- swMember.getLabel(), stmts); |
- } else { |
- hasDefault = true; |
- newMember = new DartDefault(swMember.getLabel(), stmts); |
- } |
- setInstrumentedSourceInfo(newMember, swMember); |
- newSwitchMembers.add(newMember); |
- numBranches++; |
- } |
- |
- if (!hasDefault) { |
- List<DartStatement> statements = doCallCoverBranch(x); |
- DartSwitchMember defaultMember = new DartDefault(null, |
- statements); |
- newSwitchMembers.add(defaultMember); |
- numBranches++; |
- } |
- |
- DartSwitchStatement newSwitch = new DartSwitchStatement( |
- x.getExpression(), newSwitchMembers); |
- newSwitch.setSourceInfo(x.getSourceInfo()); |
- |
- ctx.replaceMe(newSwitch); |
- super.visit(x, ctx); |
- } |
- |
- /** |
- * The instrumentation is similar to if and switch. |
- * A synthetic finally block is inserted if not present. |
- */ |
- |
- @Override |
- public void endVisit(DartTryStatement x, DartContext ctx) { |
- DartBlock tryBlock = x.getTryBlock(), finallyBlock = x |
- .getFinallyBlock(); |
- List<DartCatchBlock> catchBlocks = x.getCatchBlocks(); |
- |
- List<DartStatement> tryStmts = doCallCoverBranch(tryBlock); |
- if (tryBlock != null && tryBlock.getStatements() != null) { |
- tryStmts.addAll(tryBlock.getStatements()); |
- } |
- DartBlock newTryBlock = new DartBlock(tryStmts); |
- setInstrumentedSourceInfo(newTryBlock, tryBlock.getSourceInfo()); |
- numBranches++; |
- |
- List<DartCatchBlock> newCatchBlocks = null; |
- if (catchBlocks != null) { |
- newCatchBlocks = new ArrayList<DartCatchBlock>(); |
- for (DartCatchBlock cBlock : catchBlocks) { |
- DartBlock oldBlock = cBlock.getBlock(); |
- |
- List<DartStatement> cBlockStmts = doCallCoverBranch(cBlock); |
- if (oldBlock != null && oldBlock.getStatements() != null) { |
- cBlockStmts.addAll(oldBlock.getStatements()); |
- } |
- DartBlock newBlock = new DartBlock(cBlockStmts); |
- setInstrumentedSourceInfo(newBlock, |
- oldBlock.getSourceInfo()); |
- |
- DartCatchBlock newCatchBlock = new DartCatchBlock(newBlock, |
- cBlock.getException(), cBlock.getStackTrace()); |
- setInstrumentedSourceInfo(newCatchBlock, |
- cBlock.getSourceInfo()); |
- |
- newCatchBlocks.add(newCatchBlock); |
- numBranches++; |
- } |
- } |
- |
- DartBlock newFinallyBlock = null; |
- if(finallyBlock != null){ |
- List<DartStatement> finallyStmts = doCallCoverBranch(finallyBlock); |
- if(finallyBlock.getStatements() != null){ |
- finallyStmts.addAll(finallyBlock.getStatements()); |
- } |
- newFinallyBlock = new DartBlock(finallyStmts); |
- setInstrumentedSourceInfo(newFinallyBlock, |
- finallyBlock.getSourceInfo()); |
- } else { |
- List<DartStatement> finallyStmts = doCallCoverBranch(x); |
- newFinallyBlock = new DartBlock(finallyStmts); |
- setInstrumentedSourceInfo(newFinallyBlock, x.getSourceInfo()); |
- } |
- numBranches++; |
- |
- DartTryStatement newTry = new DartTryStatement(tryBlock, |
- newCatchBlocks, newFinallyBlock); |
- ctx.replaceMe(newTry); |
- super.endVisit(x, ctx); |
- } |
- |
- /** |
- * Rewrite all loops in this block |
- * |
- * While loop is transformed from this: |
- * |
- * while(cond) { stmts; } |
- * |
- * to: |
- * |
- * loopBranchBefore('unit.dart', loopLine, loopStart); |
- * while(cond) { |
- * loopBranchInside('unit.dart', loopLine, loopStart); |
- * stmts; |
- * } |
- * coverLoopBranch('unit.dart', loopLine, loopStart); |
- * |
- * We track two branches for every loop - one that goes inside and one that |
- * doesn't execute the loop at all. This is tracked by resetting/setting |
- * a variable from loopBranchBefore and loopBranchInside, which is checked |
- * in coverLoopBranch to decide which branch was taken. |
- */ |
- @Override |
- public void endVisit(DartBlock x, DartContext ctx) { |
- List<DartStatement> blockStmts = new ArrayList<DartStatement>(); |
- for(DartStatement stmt : x.getStatements()) { |
- if(stmt instanceof DartForInStatement) { |
- doLoopBefore(stmt, blockStmts); |
- |
- DartForInStatement oldForIn = (DartForInStatement) stmt; |
- DartStatement setup = null; |
- if(oldForIn.introducesVariable()){ |
- setup = oldForIn.getVariableStatement(); |
- } else { |
- setup = new DartExprStmt(oldForIn.getIdentifier()); |
- } |
- DartBlock body = doLoopInside(stmt, oldForIn.getBody()); |
- DartForInStatement newForIn = |
- new DartForInStatement(setup, oldForIn.getIterable(), body); |
- setInstrumentedSourceInfo(newForIn, oldForIn.getSourceInfo()); |
- |
- doLoopAfter(stmt, blockStmts); |
- numBranches+=2; |
- } else if (stmt instanceof DartForStatement) { |
- doLoopBefore(stmt, blockStmts); |
- |
- DartForStatement oldFor = (DartForStatement) stmt; |
- DartBlock body = doLoopInside(stmt, oldFor.getBody()); |
- DartForStatement newFor = new DartForStatement(oldFor.getInit(), |
- oldFor.getCondition(), oldFor.getIncrement(), body); |
- setInstrumentedSourceInfo(newFor, oldFor.getSourceInfo()); |
- |
- doLoopAfter(stmt, blockStmts); |
- numBranches+=2; |
- } else if (stmt instanceof DartWhileStatement) { |
- doLoopBefore(stmt, blockStmts); |
- |
- DartWhileStatement oldWhile = (DartWhileStatement) stmt; |
- DartBlock body = doLoopInside(stmt, oldWhile.getBody()); |
- DartWhileStatement newWhile = |
- new DartWhileStatement(oldWhile.getCondition(), body); |
- setInstrumentedSourceInfo(newWhile, oldWhile.getSourceInfo()); |
- |
- doLoopAfter(stmt, blockStmts); |
- numBranches+=2; |
- } else if (stmt instanceof DartDoWhileStatement) { |
- doLoopBefore(stmt, blockStmts); |
- |
- DartDoWhileStatement oldDoWhile = (DartDoWhileStatement) stmt; |
- DartBlock body = doLoopInside(stmt, oldDoWhile.getBody()); |
- DartDoWhileStatement newDoWhile = |
- new DartDoWhileStatement(oldDoWhile.getCondition(), body); |
- setInstrumentedSourceInfo(newDoWhile, oldDoWhile.getSourceInfo()); |
- |
- doLoopAfter(stmt, blockStmts); |
- numBranches+=2; |
- } else { |
- blockStmts.add(stmt); |
- } |
- } |
- |
- super.visit(x, ctx); |
- } |
- |
- /** |
- * Adds function call to track coverage of a branch represented by |
- * blockNode |
- * |
- * @param blockNode |
- * @return |
- */ |
- private List<DartStatement> doCallCoverBranch(DartNode blockNode) { |
- List<DartStatement> newBlockStmts = new ArrayList<DartStatement>(); |
- List<DartExpression> covArgs = makeCoverageArgs(blockNode); |
- DartExprStmt callCoverBranch = createFunctionCall("coverBranch", |
- covArgs, blockNode); |
- newBlockStmts.add(callCoverBranch); |
- setInstrumentedSourceInfo(callCoverBranch, |
- blockNode.getSourceInfo()); |
- return newBlockStmts; |
- } |
- |
- private void doLoopBefore(DartNode loopNode, List<DartStatement> stmts) { |
- List<DartExpression> args = makeCoverageArgs(loopNode); |
- DartExprStmt callLoopBefore = |
- createFunctionCall("loopBranchBefore", args, loopNode); |
- stmts.add(callLoopBefore); |
- } |
- |
- private void doLoopAfter(DartNode loopNode, List<DartStatement> stmts) { |
- List<DartExpression> args = makeCoverageArgs(loopNode); |
- args.add(DartIntegerLiteral.get(BigInteger.valueOf( |
- loopNode.getSourceStart() + loopNode.getSourceLength()))); |
- DartExprStmt callLoopAfter = |
- createFunctionCall("coverLoopBranch", args, loopNode); |
- stmts.add(callLoopAfter); |
- } |
- |
- private DartBlock doLoopInside(DartNode loopNode, DartStatement body) { |
- List<DartStatement> newBlockStmts = new ArrayList<DartStatement>(); |
- List<DartExpression> covArgs = makeCoverageArgs(loopNode); |
- DartExprStmt callCoverBranch = createFunctionCall("loopBranchInside", |
- covArgs, loopNode); |
- newBlockStmts.add(callCoverBranch); |
- setInstrumentedSourceInfo(callCoverBranch, |
- loopNode.getSourceInfo()); |
- |
- if(body instanceof DartBlock) { |
- newBlockStmts.addAll(((DartBlock) body).getStatements()); |
- } else { |
- newBlockStmts.add(body); |
- } |
- |
- return new DartBlock(newBlockStmts); |
- } |
- |
- private List<DartExpression> makeCoverageArgs(DartNode blockNode) { |
- List<DartExpression> covArgs = new ArrayList<DartExpression>(); |
- covArgs.add(DartStringLiteral.get(currentUnit.getSourceName())); |
- covArgs.add(DartIntegerLiteral.get(BigInteger.valueOf(blockNode |
- .getSourceLine()))); |
- covArgs.add(DartIntegerLiteral.get(BigInteger.valueOf(blockNode |
- .getSourceStart()))); |
- return covArgs; |
- } |
- } |
- |
-} |