Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-19526] Branch Coverage Information
Instead of coverage based on the instruction counter, the displayed
partial and full coverage is based solely on branch information per
line of code. Lines are colored in green (full coverage), yellow
(partly covered) or red (not covered) for where coverage information
is available. Lines without coverage information are not formatted
any differently from the previous version.

Code with branch information is prefixed with a • and has a mouse-over
to display either "All X branches covered", "All X branches missed" or
"X of Y branches missed" for full, none and partial coverage
respectively.
  • Loading branch information
mabako committed Sep 10, 2013
1 parent 43443ec commit fa70710
Showing 1 changed file with 83 additions and 3 deletions.
86 changes: 83 additions & 3 deletions src/main/java/hudson/plugins/jacoco/report/SourceAnnotator.java
@@ -1,6 +1,7 @@
package hudson.plugins.jacoco.report;

import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ILine;
import org.jacoco.core.analysis.ISourceNode;

import java.io.BufferedReader;
Expand All @@ -16,6 +17,7 @@
* Parses source file and annotates that with the coverage information.
*
* @author Kohsuke Kawaguchi
* @author Marcus Bauer
*/
public class SourceAnnotator {
private final File src;
Expand Down Expand Up @@ -62,9 +64,12 @@ public void printHighlightedSrcFile(ISourceNode cov, Writer output) {
output.write("<code style=\"white-space:pre;\">");
for (int i = 1; i <= sourceLines.size(); ++i) {
buf.setLength(0);
int status = cov.getLine(i).getInstructionCounter().getStatus();
if ((status == ICounter.FULLY_COVERED) || (status == ICounter.PARTLY_COVERED)) {
buf.append(i + ": ").append("<SPAN style=\"BACKGROUND-COLOR: #32cd32\">" + sourceLines.get(i - 1)).append("</SPAN>").append("<br>");

ILine line = cov.getLine(i);
ICounter branches = line.getBranchCounter();
int status = line.getStatus();
if (status != ICounter.EMPTY) {
printHighlightedLine(buf, i, branches, sourceLines.get(i - 1), status);
} else {
buf.append(i + ": ").append(sourceLines.get(i - 1)).append("<br>");
}
Expand All @@ -79,4 +84,79 @@ public void printHighlightedSrcFile(ISourceNode cov, Writer output) {
buf.append("ERROR: Error while reading the sourcefile!");
}
}

/**
* Formats a source code line
*
* @param buf
* source to write to.
* @param lineNumber
* line number to output
* @param cov
* branch coverage data for this line
* @param sourceLine
* source code line
* @param status
* coverage status of this line
*/
private void printHighlightedLine(StringBuilder buf, int lineNumber, ICounter cov, String sourceLine, int status) {
buf.append(lineNumber + ":");

String tooltip = getTooltip(cov);
if (tooltip != null) {
buf.append("•<SPAN title=\"").append(tooltip).append("\"");
} else {
buf.append(" <SPAN");
}

buf.append(" style=\"BACKGROUND-COLOR: " + getStatusColor(status) + "\">").append(sourceLine).append("</SPAN>").append("<br>");
}

/**
* Returns a tooltip for the branch coverage data.
*
* @param cov
* branch coverage data
* @return Tooltip if branch coverage data exists for the given line,
* otherwise <code>null</code>
*/
private String getTooltip(ICounter cov) {
switch (cov.getStatus()) {
case ICounter.FULLY_COVERED:
return "All " + cov.getTotalCount() + " branches covered.";

case ICounter.PARTLY_COVERED:
return cov.getMissedCount() + " of " + cov.getTotalCount() + " branches missed.";

case ICounter.NOT_COVERED:
return "All " + cov.getTotalCount() + " branches missed.";

default:
return null;
}
}

/**
* Returns a HTML color for each line status
*
* @param status
* Status of the line
* @return HTML color code for the background of the line, "none" if none
* @see ICounter#getStatus()
*/
private String getStatusColor(int status) {
switch (status) {
case ICounter.FULLY_COVERED:
return "#ccffcc";

case ICounter.PARTLY_COVERED:
return "#ffff80";

case ICounter.NOT_COVERED:
return "#ffaaaa";

default:
return "none";
}
}
}

0 comments on commit fa70710

Please sign in to comment.