1
2
3
4
5
6 package mockit.coverage.reporting.parsing;
7
8 import edu.umd.cs.findbugs.annotations.NonNull;
9 import edu.umd.cs.findbugs.annotations.Nullable;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 public final class FileParser {
15 private static final class PendingClass {
16 @NonNull
17 final String className;
18 int braceBalance;
19
20 PendingClass(@NonNull String className) {
21 this.className = className;
22 }
23 }
24
25 @NonNull
26 public final LineParser lineParser = new LineParser();
27 @NonNull
28 public final List<PendingClass> currentClasses = new ArrayList<>(2);
29
30 @Nullable
31 private PendingClass currentClass;
32 private boolean openingBraceForClassFound;
33 private int currentBraceBalance;
34
35 public boolean parseCurrentLine(@NonNull String line) {
36 if (!lineParser.parse(line)) {
37 return false;
38 }
39
40 LineElement firstElement = lineParser.getInitialElement();
41 LineElement classDeclaration = findClassNameInNewClassDeclaration();
42
43 if (classDeclaration != null) {
44 firstElement = classDeclaration;
45 registerStartOfClassDeclaration(classDeclaration);
46 }
47
48 if (currentClass != null) {
49 detectPotentialEndOfClassDeclaration(firstElement);
50 }
51
52 return true;
53 }
54
55 @Nullable
56 private LineElement findClassNameInNewClassDeclaration() {
57 LineElement previous = null;
58
59 for (LineElement element : lineParser.getInitialElement()) {
60 if (element.isKeyword("class") && (previous == null || !previous.isDotSeparator())) {
61 return element.getNextCodeElement();
62 }
63
64 previous = element;
65 }
66
67 return null;
68 }
69
70 private void registerStartOfClassDeclaration(@NonNull LineElement elementWithClassName) {
71 String className = elementWithClassName.getText();
72
73 if (currentClass != null) {
74 currentClass.braceBalance = currentBraceBalance;
75 }
76
77 currentClass = new PendingClass(className);
78 currentClasses.add(currentClass);
79 currentBraceBalance = 0;
80 }
81
82 private void detectPotentialEndOfClassDeclaration(@NonNull LineElement firstElement) {
83
84 currentBraceBalance += firstElement.getBraceBalanceUntilEndOfLine();
85
86 if (!openingBraceForClassFound && currentBraceBalance > 0) {
87 openingBraceForClassFound = true;
88 } else if (openingBraceForClassFound && currentBraceBalance == 0) {
89 restorePreviousPendingClassIfAny();
90 }
91 }
92
93 private void restorePreviousPendingClassIfAny() {
94 currentClasses.remove(currentClass);
95
96 if (currentClasses.isEmpty()) {
97 currentClass = null;
98 } else {
99 currentClass = currentClasses.get(currentClasses.size() - 1);
100 currentBraceBalance = currentClass.braceBalance;
101 }
102 }
103
104 @Nullable
105 public String getCurrentlyPendingClass() {
106 return currentClass == null ? null : currentClass.className;
107 }
108 }