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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java
===================================================================
--- compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java (revision 0)
+++ compiler/java/com/google/dart/compiler/ast/CoverageInstrumenter.java (revision 0)
@@ -0,0 +1,711 @@
+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.CompilerConfiguration;
+import com.google.dart.compiler.CommandLineOptions.CompilerOptions;
pdr 2011/12/16 17:00:50 Alphabetize
shauvik 2011/12/16 17:57:06 Done.
+import com.google.dart.compiler.common.SourceInfo;
+
+/**
+ * CoverageInstrumenter contains specialized instrumenters to perform specific
+ * instrumentation for obtaining coverage of different program entities
+ */
pdr 2011/12/16 17:00:50 This file is formatted with 8-space tabs, can you
shauvik 2011/12/16 17:57:06 Done.
+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" };
+
+ // 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 ("all".equals(covType)) {
+ instrumenters.add(new StatementInstrumenter());
+ instrumenters.add(new FunctionInstrumenter());
+ instrumenters.add(new BranchInstrumenter());
+ }
+ if ("statement".equals(covType)) {
+ instrumenters.add(new StatementInstrumenter());
+ }
+ if ("function".equals(covType)) {
+ instrumenters.add(new FunctionInstrumenter());
+ }
+ if ("branch".equals(covType)) {
+ instrumenters.add(new BranchInstrumenter());
+ }
+ }
+ }
+ }
+
+ /**
+ * The Base Instrumenter class that provides some common functionalities to
+ * all Instrumenters
+ */
+ private static class BaseInstrumenter extends DartModVisitor {
+ 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>(),
pdr 2011/12/16 17:00:50 Line > 100 cols (here, and below).
shauvik 2011/12/16 17:57:06 Done.
+ numStatementsMap = new HashMap<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; ... }
+ */
+ @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);
+ }
+
+ @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);
+ }
+
+ // TODO: visit all types of branches - control statements (if, switch,
+ // try) and loops (for, while, do-while)
+
+ /**
+ * 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.
+ *
+ * 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(); }
+ *
+ */
+ @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);
+ }
+
+ @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
+ */
+ @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;
+ }
+ }
+
+}

Powered by Google App Engine
This is Rietveld 408576698