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