aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.core/src/org/jacoco/core/internal/analysis
diff options
context:
space:
mode:
authorMarc R. Hoffmann <hoffmann@mountainminds.com>2011-01-06 21:09:13 +0000
committerMarc R. Hoffmann <hoffmann@mountainminds.com>2011-01-06 21:09:13 +0000
commit70448db630444bda2e3122cf2045a88f84fd25c6 (patch)
treea769cfc4047cc087665735236db4d7e2f7dcf29a /org.jacoco.core/src/org/jacoco/core/internal/analysis
parent96324be1ba54d882364bd02b1d47fb298569e215 (diff)
downloadjacoco-70448db630444bda2e3122cf2045a88f84fd25c6.tar.gz
Track #130: New interfaces and implementations.
Diffstat (limited to 'org.jacoco.core/src/org/jacoco/core/internal/analysis')
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java162
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java178
2 files changed, 340 insertions, 0 deletions
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java
new file mode 100644
index 00000000..fe9f549a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import org.jacoco.core.analysis.CounterImpl;
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.analysis.ILine;
+import org.jacoco.core.analysis.ILines;
+
+/**
+ * {@link ILines} implementation.
+ *
+ * @author Marc R. Hoffmann
+ * @version $qualified.bundle.version$
+ */
+public abstract class LineImpl implements ILine {
+
+ /** Max instruction counter value for which singletons are created */
+ private static final int SINGLETON_INS_LIMIT = 8;
+
+ /** Max branch counter value for which singletons are created */
+ private static final int SINGLETON_BRA_LIMIT = 4;
+
+ private static final LineImpl[][][][] SINGLETONS = new LineImpl[SINGLETON_INS_LIMIT + 1][][][];
+
+ static {
+ for (int i = 0; i <= SINGLETON_INS_LIMIT; i++) {
+ SINGLETONS[i] = new LineImpl[SINGLETON_INS_LIMIT + 1][][];
+ for (int j = 0; j <= SINGLETON_INS_LIMIT; j++) {
+ SINGLETONS[i][j] = new LineImpl[SINGLETON_BRA_LIMIT + 1][];
+ for (int k = 0; k <= SINGLETON_BRA_LIMIT; k++) {
+ SINGLETONS[i][j][k] = new LineImpl[SINGLETON_BRA_LIMIT + 1];
+ for (int l = 0; l <= SINGLETON_BRA_LIMIT; l++) {
+ SINGLETONS[i][j][k][l] = new Fix(i, j, k, l);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Empty line without instructions or branches.
+ */
+ public static final LineImpl EMPTY = SINGLETONS[0][0][0][0];
+
+ private static LineImpl getInstance(final CounterImpl instructions,
+ final CounterImpl branches) {
+ final int im = instructions.getMissedCount();
+ final int ic = instructions.getCoveredCount();
+ final int bm = branches.getMissedCount();
+ final int bc = branches.getCoveredCount();
+ if (im <= SINGLETON_INS_LIMIT && ic <= SINGLETON_INS_LIMIT
+ && bm <= SINGLETON_BRA_LIMIT && bc <= SINGLETON_BRA_LIMIT) {
+ return SINGLETONS[im][ic][bm][bc];
+ }
+ return new Var(instructions, branches);
+ }
+
+ /**
+ * Mutable version.
+ */
+ private static final class Var extends LineImpl {
+ Var(final CounterImpl instructions, final CounterImpl branches) {
+ super(instructions, branches);
+ }
+
+ @Override
+ public LineImpl increment(final ICounter instructions,
+ final ICounter branches) {
+ this.instructions = this.instructions.increment(instructions);
+ this.branches = this.branches.increment(branches);
+ return this;
+ }
+ }
+
+ /**
+ * Immutable version.
+ */
+ private static final class Fix extends LineImpl {
+ public Fix(final int im, final int ic, final int bm, final int bc) {
+ super(CounterImpl.getInstance(im, ic), CounterImpl.getInstance(bm,
+ bc));
+ }
+
+ @Override
+ public LineImpl increment(final ICounter instructions,
+ final ICounter branches) {
+ return getInstance(this.instructions.increment(instructions),
+ this.branches.increment(branches));
+ }
+ }
+
+ /** instruction counter */
+ protected CounterImpl instructions;
+
+ /** branch counter */
+ protected CounterImpl branches;
+
+ private LineImpl(final CounterImpl instructions, final CounterImpl branches) {
+ this.instructions = instructions;
+ this.branches = branches;
+ }
+
+ /**
+ * Adds the given counters to this line.
+ *
+ * @param instructions
+ * instructions to add
+ * @param branches
+ * branches to add
+ * @return instance with new counter values
+ */
+ public abstract LineImpl increment(final ICounter instructions,
+ final ICounter branches);
+
+ // === ILine ===
+
+ public byte getStatus() {
+ byte status = NO_CODE;
+ if (instructions.getMissedCount() > 0 || branches.getMissedCount() > 0) {
+ status = NOT_COVERED;
+ }
+ if (instructions.getCoveredCount() > 0
+ || branches.getCoveredCount() > 0) {
+ status |= FULLY_COVERED;
+ }
+ return status;
+ }
+
+ public ICounter getInstructionCounter() {
+ return instructions;
+ }
+
+ public ICounter getBranchCounter() {
+ return branches;
+ }
+
+ @Override
+ public int hashCode() {
+ return 23 * instructions.hashCode() ^ branches.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof ILine) {
+ final ILine that = (ILine) obj;
+ return this.instructions.equals(that.getInstructionCounter())
+ && this.branches.equals(that.getBranchCounter());
+ }
+ return false;
+ }
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
new file mode 100644
index 00000000..2656c13e
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import org.jacoco.core.analysis.CounterImpl;
+import org.jacoco.core.analysis.CoverageNodeImpl;
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.analysis.ILine;
+import org.jacoco.core.analysis.ISourceNode;
+
+/**
+ * {@link ISourceNode} implementation.
+ *
+ * @author Marc R. Hoffmann
+ * @version $qualified.bundle.version$
+ */
+public class SourceNodeImpl extends CoverageNodeImpl implements ISourceNode {
+
+ private LineImpl[] lines;
+
+ /** first line number in {@link #lines} */
+ private int offset;
+
+ /**
+ * Create a new source node implementation instance.
+ *
+ * @param elementType
+ * element type
+ * @param name
+ * name of the element
+ */
+ public SourceNodeImpl(final ElementType elementType, final String name) {
+ super(elementType, name, false);
+ lines = null;
+ offset = UNKNOWN_LINE;
+ }
+
+ /**
+ * Create a new source node implementation instance with the given line
+ * range. This is a optimization to pre-allocate the internal buffer with
+ * the correct size.
+ *
+ * @param elementType
+ * element type
+ * @param name
+ * name of the element
+ * @param firstLine
+ * first line number
+ * @param lastLine
+ * last line number
+ */
+ public SourceNodeImpl(final ElementType elementType, final String name,
+ final int firstLine, final int lastLine) {
+ this(elementType, name);
+ ensureCapacity(firstLine, lastLine);
+ }
+
+ private void ensureCapacity(final int first, final int last) {
+ if (lines == null) {
+ offset = first;
+ lines = new LineImpl[last - first + 1];
+ } else {
+ final int newFirst = Math.min(getFirstLine(), first);
+ final int newLast = Math.max(getLastLine(), last);
+ final int newLength = newLast - newFirst + 1;
+ if (newLength > lines.length) {
+ final LineImpl[] newLines = new LineImpl[newLength];
+ System.arraycopy(lines, 0, newLines, offset - newFirst,
+ lines.length);
+ offset = newFirst;
+ lines = newLines;
+ }
+ }
+ }
+
+ /**
+ * Increments all counters by the values of the given child. When
+ * incrementing the line counter is is assumed that the child refers to the
+ * same source file.
+ *
+ * @param child
+ * child node to add
+ */
+ public void increment(final ISourceNode child) {
+ instructionCounter = instructionCounter.increment(child
+ .getInstructionCounter());
+ branchCounter = branchCounter.increment(child.getBranchCounter());
+ methodCounter = methodCounter.increment(child.getMethodCounter());
+ classCounter = classCounter.increment(child.getClassCounter());
+ final int firstLine = child.getFirstLine();
+ if (firstLine != -1) {
+ final int lastLine = child.getLastLine();
+ ensureCapacity(firstLine, lastLine);
+ for (int i = firstLine; i <= lastLine; i++) {
+ final ILine line = child.getLine(i);
+ incrementLine(line.getInstructionCounter(), getBranchCounter(),
+ i);
+ }
+ }
+ }
+
+ /**
+ * Increments instructions and branches by the given counter values. If a
+ * optional line number is specified the instructions and branches are added
+ * to the given line. The line counter is incremented accordingly.
+ *
+ * @param instructions
+ * instructions to add
+ * @param branches
+ * branches to add
+ * @param line
+ * optional line number or {@link ISourceNode#UNKNOWN_LINE}
+ */
+ public void increment(final ICounter instructions, final ICounter branches,
+ final int line) {
+ if (line != UNKNOWN_LINE) {
+ incrementLine(instructions, branches, line);
+ }
+ instructionCounter = instructionCounter.increment(instructions);
+ branchCounter = branchCounter.increment(branches);
+ }
+
+ private void incrementLine(final ICounter instructions,
+ final ICounter branches, final int line) {
+ ensureCapacity(line, line);
+ final LineImpl l = getLine(line);
+ final int oldTotal = l.getInstructionCounter().getTotalCount();
+ final int oldCovered = l.getInstructionCounter().getCoveredCount();
+ lines[line - offset] = l.increment(instructions, branches);
+
+ // Increment line counter:
+ if (instructions.getTotalCount() > 0) {
+ if (instructions.getCoveredCount() == 0) {
+ if (oldTotal == 0) {
+ lineCounter = lineCounter
+ .increment(CounterImpl.COUNTER_1_0);
+ }
+ } else {
+ if (oldTotal == 0) {
+ lineCounter = lineCounter
+ .increment(CounterImpl.COUNTER_0_1);
+ } else {
+ if (oldCovered == 0) {
+ lineCounter = lineCounter.increment(-1, +1);
+ }
+ }
+ }
+ }
+ }
+
+ // === ISourceNode ===
+
+ public int getFirstLine() {
+ return offset;
+ }
+
+ public int getLastLine() {
+ return lines == null ? UNKNOWN_LINE : (offset + lines.length - 1);
+ }
+
+ public LineImpl getLine(final int nr) {
+ if (lines == null || nr < getFirstLine() || nr > getLastLine()) {
+ return LineImpl.EMPTY;
+ }
+ final LineImpl line = lines[nr - offset];
+ return line == null ? LineImpl.EMPTY : line;
+ }
+
+}