mockit.coverage.paths.Node Maven / Gradle / Ivy
/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.coverage.paths;
import java.util.*;
import java.io.*;
import javax.annotation.*;
@SuppressWarnings("ClassReferencesSubclass")
public class Node implements Serializable
{
private static final long serialVersionUID = 7521062699264845946L;
@Nonnull private final transient ThreadLocal reached = new ThreadLocal();
public final int line;
protected int segment;
private Node(int line) { this.line = line; }
void setSegmentAccordingToPrecedingNode(@Nonnull Node precedingNode)
{
int currentSegment = precedingNode.segment;
segment = precedingNode instanceof Fork ? currentSegment + 1 : currentSegment;
}
public final int getSegment() { return segment; }
final void setReached(@Nullable Boolean reached) { this.reached.set(reached); }
final boolean wasReached() { return reached.get() != null; }
@Override
public final String toString() { return getClass().getSimpleName() + ':' + line + '-' + segment; }
static final class Entry extends Node
{
private static final long serialVersionUID = -3065417917872259568L;
@Nullable Fork nextNode;
Entry(int entryLine) { super(entryLine); }
}
interface ConditionalSuccessor extends Serializable
{
void addToPath(@Nonnull Path path);
}
interface GotoSuccessor extends Serializable
{
void setNextNodeAfterGoto(@Nonnull Join newJoin);
}
static final class Exit extends Node implements ConditionalSuccessor
{
private static final long serialVersionUID = -4801498566218642509L;
@Nonnull final List paths = new ArrayList(4);
Exit(int exitLine) { super(exitLine); }
@Override
public void addToPath(@Nonnull Path path)
{
path.addNode(this);
paths.add(path);
}
}
static final class BasicBlock extends Node implements ConditionalSuccessor, GotoSuccessor
{
private static final long serialVersionUID = 2637678937923952603L;
@Nullable ConditionalSuccessor nextConsecutiveNode;
@Nullable private Join nextNodeAfterGoto;
BasicBlock(int startingLine) { super(startingLine); }
@Override @SuppressWarnings("NullableProblems")
public void setNextNodeAfterGoto(@Nonnull Join newJoin) { nextNodeAfterGoto = newJoin; }
@Override
public void addToPath(@Nonnull Path path)
{
path.addNode(this);
if (nextNodeAfterGoto != null) {
assert nextConsecutiveNode == null;
nextNodeAfterGoto.addToPath(path);
}
else if (nextConsecutiveNode != null) {
nextConsecutiveNode.addToPath(path);
}
}
}
public abstract static class Fork extends Node implements ConditionalSuccessor
{
private static final long serialVersionUID = -4995089238476806249L;
Fork(int line) { super(line); }
abstract void addNextNode(@Nonnull Join nextNode);
static void createAlternatePath(@Nonnull Path parentPath, @Nonnull Join targetJoin)
{
Path alternatePath = new Path(parentPath, targetJoin.fromTrivialFork);
targetJoin.addToPath(alternatePath);
}
}
static final class SimpleFork extends Fork
{
private static final long serialVersionUID = -521666665272332763L;
@Nullable ConditionalSuccessor nextConsecutiveNode;
@Nullable private Join nextNodeAfterJump;
SimpleFork(int line) { super(line); }
@Override
void addNextNode(@Nonnull Join nextNode) { nextNodeAfterJump = nextNode; }
@Override
public void addToPath(@Nonnull Path path)
{
path.addNode(this);
if (nextNodeAfterJump != null) {
createAlternatePath(path, nextNodeAfterJump);
}
if (nextConsecutiveNode != null) {
nextConsecutiveNode.addToPath(path);
}
}
}
static final class MultiFork extends Fork
{
private static final long serialVersionUID = 1220318686622690670L;
@Nonnull private final List caseNodes = new ArrayList();
MultiFork(int line) { super(line); }
@Override
void addNextNode(@Nonnull Join nextNode) { caseNodes.add(nextNode); }
@Override
public void addToPath(@Nonnull Path path)
{
path.addNode(this);
for (Join caseJoin : caseNodes) {
createAlternatePath(path, caseJoin);
}
}
}
static final class Join extends Node implements ConditionalSuccessor, GotoSuccessor
{
private static final long serialVersionUID = -1983522899831071765L;
@Nullable ConditionalSuccessor nextNode;
transient boolean fromTrivialFork;
Join(int joiningLine) { super(joiningLine); }
@Override
public void setNextNodeAfterGoto(@Nonnull Join newJoin) { nextNode = newJoin; }
@Override
public void addToPath(@Nonnull Path path)
{
path.addNode(this);
// TODO: can be null when there is a try..finally block; see WhileStatements#whileTrueContainingTryFinally
if (nextNode != null) {
nextNode.addToPath(path);
}
}
@Override
void setSegmentAccordingToPrecedingNode(@Nonnull Node precedingNode)
{
segment = precedingNode.segment + 1;
}
}
static final class Goto extends Node implements ConditionalSuccessor, GotoSuccessor
{
private static final long serialVersionUID = -4715451134432419220L;
private Join nextNodeAfterGoto;
Goto(int line) { super(line); }
@Override
public void setNextNodeAfterGoto(@Nonnull Join newJoin) { nextNodeAfterGoto = newJoin; }
@Override
public void addToPath(@Nonnull Path path)
{
path.addNode(this);
nextNodeAfterGoto.addToPath(path);
}
}
}