• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/main/src/main/java/mockit/coverage/reporting/parsing/LineElement.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.coverage.reporting.parsing;
7

8
import static java.util.Arrays.asList;
9

10
import edu.umd.cs.findbugs.annotations.NonNull;
11
import edu.umd.cs.findbugs.annotations.Nullable;
12

13
import java.util.Iterator;
14
import java.util.List;
15
import java.util.NoSuchElementException;
16
import java.util.regex.Pattern;
17

18
public final class LineElement implements Iterable<LineElement> {
19
    private static final List<String> CONDITIONAL_OPERATORS = asList("||", "&&", ":", "else", "?");
×
20
    private static final Pattern OPEN_TAG = Pattern.compile("<");
×
21
    private static final NoSuchElementException LAST_ELEMENT_REACHED = new NoSuchElementException();
×
22

23
    enum ElementType {
×
24
        CODE, COMMENT, SEPARATOR
×
25
    }
26

27
    enum ConditionalStatement {
×
28
        IF("if"), FOR("for"), WHILE("while");
×
29

30
        @NonNull
31
        private final String keyword;
32

33
        ConditionalStatement(@NonNull String keyword) {
×
34
            this.keyword = keyword;
×
35
        }
×
36

37
        @Nullable
38
        static ConditionalStatement find(@NonNull String keyword) {
39
            for (ConditionalStatement statement : values()) {
×
40
                if (statement.keyword.equals(keyword)) {
×
41
                    return statement;
×
42
                }
43
            }
44

45
            return null;
×
46
        }
47
    }
48

49
    @NonNull
50
    private final ElementType type;
51
    @NonNull
52
    private final String text;
53
    @Nullable
54
    private String openingTag;
55
    @Nullable
56
    private String closingTag;
57
    @Nullable
58
    private LineElement next;
59

60
    @Nullable
61
    private ConditionalStatement conditionalStatement;
62
    private int parenthesesBalance;
63

64
    LineElement(@NonNull ElementType type, @NonNull String text) {
×
65
        this.type = type;
×
66
        this.text = OPEN_TAG.matcher(text).replaceAll("&lt;");
×
67
    }
×
68

69
    public boolean isCode() {
70
        return type == ElementType.CODE;
×
71
    }
72

73
    public boolean isComment() {
74
        return type == ElementType.COMMENT;
×
75
    }
76

77
    public boolean isKeyword(@NonNull String keyword) {
78
        return isCode() && text.equals(keyword);
×
79
    }
80

81
    boolean isDotSeparator() {
82
        return type == ElementType.SEPARATOR && text.charAt(0) == '.';
×
83
    }
84

85
    @NonNull
86
    public String getText() {
87
        return text;
×
88
    }
89

90
    @Nullable
91
    public LineElement getNext() {
92
        return next;
×
93
    }
94

95
    void setNext(@Nullable LineElement next) {
96
        this.next = next;
×
97
    }
×
98

99
    @Nullable
100
    public LineElement getNextCodeElement() {
101
        if (next != null) {
×
102
            for (LineElement element : next) {
×
103
                if (element.isCode()) {
×
104
                    return element;
×
105
                }
106
            }
×
107
        }
108

109
        return null;
×
110
    }
111

112
    public void wrapText(@NonNull String desiredOpeningTag, @NonNull String desiredClosingTag) {
113
        openingTag = desiredOpeningTag;
×
114
        closingTag = desiredClosingTag;
×
115
    }
×
116

117
    @Nullable
118
    public LineElement appendUntilNextCodeElement(@NonNull StringBuilder line) {
119
        LineElement element = this;
×
120

121
        while (!element.isCode()) {
×
122
            element.appendText(line);
×
123
            element = element.next;
×
124

125
            if (element == null) {
×
126
                break;
×
127
            }
128

129
            copyConditionalTrackingState(element);
×
130
        }
131

132
        return element;
×
133
    }
134

135
    private void copyConditionalTrackingState(@NonNull LineElement destination) {
136
        destination.conditionalStatement = conditionalStatement;
×
137
        destination.parenthesesBalance = parenthesesBalance;
×
138
    }
×
139

140
    private void appendText(@NonNull StringBuilder line) {
141
        if (openingTag == null) {
×
142
            line.append(text);
×
143
        } else {
144
            line.append(openingTag).append(text).append(closingTag);
×
145
        }
146
    }
×
147

148
    @Nullable
149
    public LineElement findNextBranchingPoint() {
150
        if (conditionalStatement == null) {
×
151
            conditionalStatement = ConditionalStatement.find(text);
×
152
        }
153

154
        if (isBranchingElement()) {
×
155
            if (next != null) {
×
156
                copyConditionalTrackingState(next);
×
157
            }
158

159
            return this;
×
160
        }
161

162
        if (conditionalStatement != null) {
×
163
            int balance = getParenthesisBalance();
×
164
            parenthesesBalance += balance;
×
165

166
            if (balance != 0 && parenthesesBalance == 0) {
×
167
                return next;
×
168
            }
169
        }
170

171
        if (next == null) {
×
172
            return null;
×
173
        }
174

175
        copyConditionalTrackingState(next);
×
176

177
        // noinspection TailRecursion
178
        return next.findNextBranchingPoint();
×
179
    }
180

181
    public boolean isBranchingElement() {
182
        if (conditionalStatement == ConditionalStatement.FOR) {
×
183
            int p = text.indexOf(':');
×
184

185
            if (p < 0) {
×
186
                p = text.indexOf(';');
×
187
            }
188

189
            return p >= 0 && text.trim().length() == 1;
×
190
        }
191

192
        return CONDITIONAL_OPERATORS.contains(text);
×
193
    }
194

195
    private int getParenthesisBalance() {
196
        int balance = 0;
×
197
        int p = text.indexOf('(');
×
198

199
        while (p >= 0) {
×
200
            balance++;
×
201
            p = text.indexOf('(', p + 1);
×
202
        }
203

204
        int q = text.indexOf(')');
×
205

206
        while (q >= 0) {
×
207
            balance--;
×
208
            q = text.indexOf(')', q + 1);
×
209
        }
210

211
        return balance;
×
212
    }
213

214
    @Nullable
215
    public LineElement findWord(@NonNull String word) {
216
        for (LineElement element : this) {
×
217
            if (element.isCode() && word.equals(element.text)) {
×
218
                return element;
×
219
            }
220
        }
×
221

222
        return null;
×
223
    }
224

225
    int getBraceBalanceUntilEndOfLine() {
226
        int balance = 0;
×
227

228
        for (LineElement element : this) {
×
229
            balance += element.getBraceBalance();
×
230
        }
×
231

232
        return balance;
×
233
    }
234

235
    private int getBraceBalance() {
236
        if (isCode() && text.length() == 1) {
×
237
            char c = text.charAt(0);
×
238

239
            if (c == '{') {
×
240
                return 1;
×
241
            }
242
            if (c == '}') {
×
243
                return -1;
×
244
            }
245
        }
246

247
        return 0;
×
248
    }
249

250
    public void appendAllBefore(@NonNull StringBuilder line, @Nullable LineElement elementToStopBefore) {
251
        LineElement elementToPrint = this;
×
252

253
        do {
254
            elementToPrint.appendText(line);
×
255
            elementToPrint = elementToPrint.next;
×
256
        } while (elementToPrint != null && elementToPrint != elementToStopBefore);
×
257
    }
×
258

259
    @NonNull
260
    @Override
261
    public Iterator<LineElement> iterator() {
262
        return new Iterator<>() {
×
263
            @Nullable
×
264
            private LineElement current = LineElement.this;
265

266
            @Override
267
            public boolean hasNext() {
268
                return current != null;
×
269
            }
270

271
            @NonNull
272
            @Override
273
            public LineElement next() {
274
                if (current == null) {
×
275
                    throw LAST_ELEMENT_REACHED;
×
276
                }
277

278
                LineElement nextElement = current;
×
279
                current = current.next;
×
280

281
                return nextElement;
×
282
            }
283

284
            @Override
285
            public void remove() {
286
            }
×
287
        };
288
    }
289

290
    @Override
291
    public String toString() {
292
        StringBuilder line = new StringBuilder(200);
×
293

294
        for (LineElement element : this) {
×
295
            element.appendText(line);
×
296
        }
×
297

298
        return line.toString();
×
299
    }
300
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc