mockit.coverage.reporting.parsing.FileParser Maven / Gradle / Ivy
/*
* Copyright (c) 2006 JMockit developers
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.coverage.reporting.parsing;
import java.util.*;
import javax.annotation.*;
public final class FileParser
{
private static final class PendingClass {
@Nonnull final String className;
int braceBalance;
PendingClass(@Nonnull String className) { this.className = className; }
}
@Nonnull public final LineParser lineParser = new LineParser();
@Nonnull public final List currentClasses = new ArrayList<>(2);
@Nullable private PendingClass currentClass;
private boolean openingBraceForClassFound;
private int currentBraceBalance;
public boolean parseCurrentLine(@Nonnull String line) {
if (!lineParser.parse(line)) {
return false;
}
LineElement firstElement = lineParser.getInitialElement();
LineElement classDeclaration = findClassNameInNewClassDeclaration();
if (classDeclaration != null) {
firstElement = classDeclaration;
registerStartOfClassDeclaration(classDeclaration);
}
if (currentClass != null) {
detectPotentialEndOfClassDeclaration(firstElement);
}
return true;
}
@Nullable private LineElement findClassNameInNewClassDeclaration() {
LineElement previous = null;
for (LineElement element : lineParser.getInitialElement()) {
if (element.isKeyword("class") && (previous == null || !previous.isDotSeparator())) {
return element.getNextCodeElement();
}
previous = element;
}
return null;
}
private void registerStartOfClassDeclaration(@Nonnull LineElement elementWithClassName) {
String className = elementWithClassName.getText();
if (currentClass != null) {
currentClass.braceBalance = currentBraceBalance;
}
currentClass = new PendingClass(className);
currentClasses.add(currentClass);
currentBraceBalance = 0;
}
private void detectPotentialEndOfClassDeclaration(@Nonnull LineElement firstElement) {
// TODO: how to deal with classes defined entirely in one line?
currentBraceBalance += firstElement.getBraceBalanceUntilEndOfLine();
if (!openingBraceForClassFound && currentBraceBalance > 0) {
openingBraceForClassFound = true;
}
else if (openingBraceForClassFound && currentBraceBalance == 0) {
restorePreviousPendingClassIfAny();
}
}
private void restorePreviousPendingClassIfAny() {
currentClasses.remove(currentClass);
if (currentClasses.isEmpty()) {
currentClass = null;
}
else {
currentClass = currentClasses.get(currentClasses.size() - 1);
currentBraceBalance = currentClass.braceBalance;
}
}
@Nullable
public String getCurrentlyPendingClass() {
return currentClass == null ? null : currentClass.className;
}
}