| 1 | package pro.verron.officestamper.asciidoc; | |
| 2 | ||
| 3 | import java.util.ArrayList; | |
| 4 | import java.util.List; | |
| 5 | import java.util.Map; | |
| 6 | import java.util.function.Function; | |
| 7 | ||
| 8 | import static pro.verron.officestamper.asciidoc.AsciiDocModel.*; | |
| 9 | ||
| 10 | /// The [AsciiDocParser] class is a utility for parsing AsciiDoc-formatted text | |
| 11 | /// and transforming it into structured models. It provides both static and instance-based | |
| 12 | /// parsing capabilities and is designed to work with inline structures within the text. | |
| 13 | /// ## Superclasses | |
| 14 | /// This class extends the following superclasses: | |
| 15 | /// - [Object] | |
| 16 | /// - [Function] | |
| 17 | /// | |
| 18 | /// ## Methods | |
| 19 | /// - [#parse(String)]: A static method to parse an AsciiDoc string into an [AsciiDocModel]. | |
| 20 | /// - [#apply(String)]: An instance method implementing the [Function] interface for parsing an AsciiDoc string | |
| 21 | /// into an [AsciiDocModel]. | |
| 22 | /// | |
| 23 | /// ## Internal Behavior | |
| 24 | /// - [#parseInlines(String)]: A private static helper method to parse inline elements from a given text input. | |
| 25 | public final class AsciiDocParser | |
| 26 | implements Function<String, AsciiDocModel> { | |
| 27 | ||
| 28 | /// Parses the given AsciiDoc string and produces an [AsciiDocModel] representation. | |
| 29 | /// | |
| 30 | /// @param asciidoc the AsciiDoc content to be parsed | |
| 31 | /// @return an [AsciiDocModel] representing the parsed structure of the input AsciiDoc | |
| 32 | public static AsciiDocModel parse(String asciidoc) { | |
| 33 |
1
1. parse : replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocParser::parse → KILLED |
return new AsciiDocParser().apply(asciidoc); |
| 34 | } | |
| 35 | ||
| 36 | /// Processes an AsciiDoc-formatted string and converts it into an [AsciiDocModel] | |
| 37 | /// representation containing structured blocks such as paragraphs, headings, | |
| 38 | /// lists, tables, images, code blocks, and blockquotes. | |
| 39 | /// | |
| 40 | /// @param asciidoc the AsciiDoc-formatted input string. It may include various types of | |
| 41 | /// blocks (e.g., paragraphs, headings, lists, tables, etc.) and | |
| 42 | /// formatting constructs. | |
| 43 | /// @return an [AsciiDocModel] object representing the parsed blocks and their | |
| 44 | /// structure in the input string. Returns an empty model if the input is blank. | |
| 45 | public AsciiDocModel apply(String asciidoc) { | |
| 46 |
2
1. apply : replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocParser::apply → KILLED 2. apply : negated conditional → KILLED |
if (asciidoc.isBlank()) return AsciiDocModel.of(new ArrayList<>()); |
| 47 | ||
| 48 | String[] lines = asciidoc.split("\r?\n"); | |
| 49 | StringBuilder currentParagraph = new StringBuilder(); | |
| 50 | boolean inTable = false; | |
| 51 | boolean inBlockquote = false; | |
| 52 | boolean inCodeBlock = false; | |
| 53 | String currentLanguage = ""; | |
| 54 | List<Row> currentTableRows = new ArrayList<>(); | |
| 55 | StringBuilder currentBlockContent = new StringBuilder(); | |
| 56 | ||
| 57 | var blocks = new ArrayList<Block>(); | |
| 58 | for (String line : lines) { | |
| 59 | String trimmed = line.trim(); | |
| 60 | ||
| 61 |
1
1. apply : negated conditional → KILLED |
if (trimmed.equals("____")) { |
| 62 |
1
1. apply : negated conditional → KILLED |
if (inBlockquote) { |
| 63 | blocks.add(new Blockquote(parseInlines(currentBlockContent.toString() | |
| 64 | .trim()))); | |
| 65 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → SURVIVED |
currentBlockContent.setLength(0); |
| 66 | inBlockquote = false; | |
| 67 | } | |
| 68 | else { | |
| 69 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 70 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 71 | .trim()))); | |
| 72 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 73 | } | |
| 74 | inBlockquote = true; | |
| 75 | } | |
| 76 | continue; | |
| 77 | } | |
| 78 | ||
| 79 |
1
1. apply : negated conditional → KILLED |
if (inBlockquote) { |
| 80 |
1
1. apply : negated conditional → SURVIVED |
if (!currentBlockContent.isEmpty()) { |
| 81 | currentBlockContent.append(" "); | |
| 82 | } | |
| 83 | currentBlockContent.append(trimmed); | |
| 84 | continue; | |
| 85 | } | |
| 86 | ||
| 87 |
1
1. apply : negated conditional → KILLED |
if (trimmed.startsWith("[source")) { |
| 88 | int commaIndex = trimmed.indexOf(','); | |
| 89 |
1
1. apply : negated conditional → KILLED |
if (commaIndex != -1) { |
| 90 | int bracketIndex = trimmed.indexOf(']'); | |
| 91 |
1
1. apply : Replaced integer addition with subtraction → KILLED |
currentLanguage = trimmed.substring(commaIndex + 1, bracketIndex) |
| 92 | .trim(); | |
| 93 | } | |
| 94 | continue; | |
| 95 | } | |
| 96 | ||
| 97 |
1
1. apply : negated conditional → KILLED |
if (trimmed.equals("----")) { |
| 98 |
1
1. apply : negated conditional → KILLED |
if (inCodeBlock) { |
| 99 | blocks.add(new CodeBlock(currentLanguage, | |
| 100 | currentBlockContent.toString() | |
| 101 | .trim())); | |
| 102 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → SURVIVED |
currentBlockContent.setLength(0); |
| 103 | currentLanguage = ""; | |
| 104 | inCodeBlock = false; | |
| 105 | } | |
| 106 | else { | |
| 107 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 108 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 109 | .trim()))); | |
| 110 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 111 | } | |
| 112 | inCodeBlock = true; | |
| 113 | } | |
| 114 | continue; | |
| 115 | } | |
| 116 | ||
| 117 |
1
1. apply : negated conditional → KILLED |
if (inCodeBlock) { |
| 118 |
1
1. apply : negated conditional → SURVIVED |
if (!currentBlockContent.isEmpty()) { |
| 119 | currentBlockContent.append("\n"); | |
| 120 | } | |
| 121 | currentBlockContent.append(line); // Preserve indentation in code blocks | |
| 122 | continue; | |
| 123 | } | |
| 124 | ||
| 125 |
1
1. apply : negated conditional → KILLED |
if (trimmed.startsWith("image::")) { |
| 126 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 127 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 128 | .trim()))); | |
| 129 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 130 | } | |
| 131 | int endUrl = trimmed.indexOf('[', 7); | |
| 132 |
1
1. apply : negated conditional → KILLED |
if (endUrl != -1) { |
| 133 | int endText = trimmed.indexOf(']', endUrl); | |
| 134 |
1
1. apply : negated conditional → KILLED |
if (endText != -1) { |
| 135 | String url = trimmed.substring(7, endUrl); | |
| 136 |
1
1. apply : Replaced integer addition with subtraction → KILLED |
String altText = trimmed.substring(endUrl + 1, endText); |
| 137 | blocks.add(new ImageBlock(url, altText)); | |
| 138 | continue; | |
| 139 | } | |
| 140 | } | |
| 141 | } | |
| 142 | ||
| 143 |
1
1. apply : negated conditional → KILLED |
if (trimmed.equals("|===")) { |
| 144 |
1
1. apply : negated conditional → KILLED |
if (inTable) { |
| 145 | blocks.add(new Table(currentTableRows)); | |
| 146 | currentTableRows = new ArrayList<>(); | |
| 147 | inTable = false; | |
| 148 | } | |
| 149 | else { | |
| 150 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 151 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 152 | .trim()))); | |
| 153 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 154 | } | |
| 155 | inTable = true; | |
| 156 | } | |
| 157 | continue; | |
| 158 | } | |
| 159 | ||
| 160 |
1
1. apply : negated conditional → KILLED |
if (inTable) { |
| 161 |
1
1. apply : negated conditional → KILLED |
if (trimmed.startsWith("|")) { |
| 162 | String[] cellTexts = trimmed.substring(1) | |
| 163 | .split("\\|"); | |
| 164 | List<Cell> cells = new ArrayList<>(); | |
| 165 | for (String cellText : cellTexts) { | |
| 166 | cells.add(Cell.ofInlines(parseInlines(cellText.trim()))); | |
| 167 | } | |
| 168 | currentTableRows.add(new Row(cells)); | |
| 169 | } | |
| 170 | continue; | |
| 171 | } | |
| 172 | ||
| 173 |
1
1. apply : negated conditional → KILLED |
if (trimmed.isBlank()) { |
| 174 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 175 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 176 | .trim()))); | |
| 177 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 178 | } | |
| 179 | continue; | |
| 180 | } | |
| 181 | ||
| 182 | // Check for Headings | |
| 183 |
1
1. apply : negated conditional → KILLED |
if (trimmed.startsWith("=")) { |
| 184 | int level = 0; | |
| 185 |
3
1. apply : changed conditional boundary → SURVIVED 2. apply : negated conditional → KILLED 3. apply : negated conditional → KILLED |
while (level < trimmed.length() && trimmed.charAt(level) == '=') { |
| 186 | level++; | |
| 187 | } | |
| 188 |
6
1. apply : changed conditional boundary → SURVIVED 2. apply : changed conditional boundary → SURVIVED 3. apply : changed conditional boundary → SURVIVED 4. apply : negated conditional → KILLED 5. apply : negated conditional → KILLED 6. apply : negated conditional → KILLED |
if (level > 0 && level <= 6 && level < trimmed.length() |
| 189 |
1
1. apply : negated conditional → KILLED |
&& Character.isWhitespace(trimmed.charAt(level))) { |
| 190 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 191 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 192 | .trim()))); | |
| 193 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 194 | } | |
| 195 | String title = trimmed.substring(level) | |
| 196 | .trim(); | |
| 197 | blocks.add(new Heading(level, parseInlines(title))); | |
| 198 | continue; | |
| 199 | } | |
| 200 | } | |
| 201 | ||
| 202 | // Check for Unordered List Item | |
| 203 |
1
1. apply : negated conditional → KILLED |
if (trimmed.startsWith("* ")) { |
| 204 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 205 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 206 | .trim()))); | |
| 207 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 208 | } | |
| 209 | String itemText = trimmed.substring(2) | |
| 210 | .trim(); | |
| 211 | var item = new ListItem(parseInlines(itemText)); | |
| 212 |
2
1. apply : negated conditional → KILLED 2. apply : negated conditional → KILLED |
if (!blocks.isEmpty() && blocks.getLast() instanceof UnorderedList(List<ListItem> items1)) { |
| 213 | List<ListItem> items = new ArrayList<>(items1); | |
| 214 | items.add(item); | |
| 215 |
1
1. apply : Replaced integer subtraction with addition → KILLED |
blocks.set(blocks.size() - 1, new UnorderedList(items)); |
| 216 | } | |
| 217 | else { | |
| 218 | blocks.add(new UnorderedList(List.of(item))); | |
| 219 | } | |
| 220 | continue; | |
| 221 | } | |
| 222 | ||
| 223 | // Check for Ordered List Item | |
| 224 |
1
1. apply : negated conditional → KILLED |
if (trimmed.startsWith(". ")) { |
| 225 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 226 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 227 | .trim()))); | |
| 228 |
1
1. apply : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
currentParagraph.setLength(0); |
| 229 | } | |
| 230 | String itemText = trimmed.substring(2) | |
| 231 | .trim(); | |
| 232 | var item = new ListItem(parseInlines(itemText)); | |
| 233 |
2
1. apply : negated conditional → KILLED 2. apply : negated conditional → KILLED |
if (!blocks.isEmpty() && blocks.getLast() instanceof OrderedList(List<ListItem> items1)) { |
| 234 | List<ListItem> items = new ArrayList<>(items1); | |
| 235 | items.add(item); | |
| 236 |
1
1. apply : Replaced integer subtraction with addition → KILLED |
blocks.set(blocks.size() - 1, new OrderedList(items)); |
| 237 | } | |
| 238 | else { | |
| 239 | blocks.add(new OrderedList(List.of(item))); | |
| 240 | } | |
| 241 | continue; | |
| 242 | } | |
| 243 | ||
| 244 | // Otherwise, it's a paragraph part | |
| 245 |
1
1. apply : negated conditional → SURVIVED |
if (!currentParagraph.isEmpty()) { |
| 246 | currentParagraph.append("\n"); | |
| 247 | } | |
| 248 | currentParagraph.append(trimmed); | |
| 249 | } | |
| 250 | ||
| 251 |
1
1. apply : negated conditional → KILLED |
if (!currentParagraph.isEmpty()) { |
| 252 | blocks.add(new Paragraph(parseInlines(currentParagraph.toString() | |
| 253 | .trim()))); | |
| 254 | } | |
| 255 | ||
| 256 |
1
1. apply : replaced return value with null for pro/verron/officestamper/asciidoc/AsciiDocParser::apply → KILLED |
return AsciiDocModel.of(blocks); |
| 257 | } | |
| 258 | ||
| 259 | private static List<Inline> parseInlines(String text) { | |
| 260 | // Stack-based inline parser with simple tokens for '*', '_', text, and escapes. | |
| 261 | // Non-overlapping nesting is allowed; crossing markers are treated as plain text. | |
| 262 | var root = new Frame(FrameType.ROOT); | |
| 263 | var stack = new ArrayList<Frame>(); | |
| 264 | stack.add(root); | |
| 265 | ||
| 266 |
2
1. parseInlines : replaced return value with Collections.emptyList for pro/verron/officestamper/asciidoc/AsciiDocParser::parseInlines → NO_COVERAGE 2. parseInlines : negated conditional → KILLED |
if (text.isEmpty()) return root.children; |
| 267 | ||
| 268 |
2
1. parseInlines : negated conditional → KILLED 2. parseInlines : changed conditional boundary → KILLED |
for (int i = 0; i < text.length(); i++) { |
| 269 | char c = text.charAt(i); | |
| 270 | ||
| 271 | // Escapes for '*', '_', and '\\' | |
| 272 |
1
1. parseInlines : negated conditional → KILLED |
if (c == '\\') { |
| 273 |
3
1. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE 2. parseInlines : changed conditional boundary → NO_COVERAGE 3. parseInlines : negated conditional → NO_COVERAGE |
if (i + 1 < text.length()) { |
| 274 |
1
1. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE |
char next = text.charAt(i + 1); |
| 275 |
3
1. parseInlines : negated conditional → NO_COVERAGE 2. parseInlines : negated conditional → NO_COVERAGE 3. parseInlines : negated conditional → NO_COVERAGE |
if (next == '*' || next == '_' || next == '\\') { |
| 276 | stack.getLast().text.append(next); | |
| 277 |
1
1. parseInlines : Changed increment from 1 to -1 → NO_COVERAGE |
i++; |
| 278 | continue; | |
| 279 | } | |
| 280 | } | |
| 281 | // Lone backslash | |
| 282 | stack.getLast().text.append(c); | |
| 283 | continue; | |
| 284 | } | |
| 285 | ||
| 286 |
2
1. parseInlines : negated conditional → KILLED 2. parseInlines : negated conditional → KILLED |
if (c == '*' || c == '_') { |
| 287 |
1
1. parseInlines : negated conditional → KILLED |
FrameType type = (c == '*') ? FrameType.BOLD : FrameType.ITALIC; |
| 288 | Frame top = stack.getLast(); | |
| 289 |
1
1. parseInlines : negated conditional → KILLED |
if (top.type == type) { |
| 290 | // Close current frame | |
| 291 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → KILLED |
top.flushTextToChildren(); |
| 292 |
1
1. parseInlines : negated conditional → KILLED |
Inline node = (type == FrameType.BOLD) ? new Bold(top.children) : new Italic(top.children); |
| 293 | stack.removeLast(); | |
| 294 | Frame parent = stack.getLast(); | |
| 295 | parent.children.add(node); | |
| 296 | } | |
| 297 |
3
1. parseInlines : negated conditional → SURVIVED 2. parseInlines : negated conditional → SURVIVED 3. parseInlines : negated conditional → KILLED |
else if (top.type == FrameType.BOLD || top.type == FrameType.ITALIC || top.type == FrameType.ROOT) { |
| 298 | // Open new frame | |
| 299 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → KILLED |
top.flushTextToChildren(); |
| 300 | Frame f = new Frame(type); | |
| 301 | stack.add(f); | |
| 302 | } | |
| 303 | else { | |
| 304 | // Should not happen | |
| 305 | stack.getLast().text.append(c); | |
| 306 | } | |
| 307 | continue; | |
| 308 | } | |
| 309 | ||
| 310 | // Detect literal |TAB| token -> emit a Tab inline | |
| 311 |
9
1. parseInlines : negated conditional → NO_COVERAGE 2. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE 3. parseInlines : negated conditional → NO_COVERAGE 4. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE 5. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE 6. parseInlines : negated conditional → SURVIVED 7. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE 8. parseInlines : changed conditional boundary → NO_COVERAGE 9. parseInlines : negated conditional → NO_COVERAGE |
if (c == '|' && i + 4 < text.length() && text.charAt(i + 1) == 'T' && text.charAt(i + 2) == 'A' |
| 312 |
3
1. parseInlines : negated conditional → NO_COVERAGE 2. parseInlines : negated conditional → NO_COVERAGE 3. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE |
&& text.charAt(i + 3) == 'B' && text.charAt(i + 4) == '|') { |
| 313 | // Flush any pending text | |
| 314 | stack.getLast() | |
| 315 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → NO_COVERAGE |
.flushTextToChildren(); |
| 316 | stack.getLast().children.add(new Tab()); | |
| 317 |
1
1. parseInlines : Changed increment from 4 to -4 → NO_COVERAGE |
i += 4; |
| 318 | continue; | |
| 319 | } | |
| 320 | ||
| 321 | // Simple Link detection: https://example.com[Text] | |
| 322 |
2
1. parseInlines : negated conditional → KILLED 2. parseInlines : negated conditional → KILLED |
if (c == 'h' && text.startsWith("http", i)) { |
| 323 | int endUrl = text.indexOf('[', i); | |
| 324 |
1
1. parseInlines : negated conditional → KILLED |
if (endUrl != -1) { |
| 325 | int endText = text.indexOf(']', endUrl); | |
| 326 |
1
1. parseInlines : negated conditional → KILLED |
if (endText != -1) { |
| 327 | stack.getLast() | |
| 328 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → KILLED |
.flushTextToChildren(); |
| 329 | String url = text.substring(i, endUrl); | |
| 330 |
1
1. parseInlines : Replaced integer addition with subtraction → KILLED |
String linkText = text.substring(endUrl + 1, endText); |
| 331 | stack.getLast().children.add(new Link(url, linkText)); | |
| 332 | i = endText; | |
| 333 | continue; | |
| 334 | } | |
| 335 | } | |
| 336 | } | |
| 337 | ||
| 338 | // Simple Image detection: image:url[AltText] | |
| 339 |
2
1. parseInlines : negated conditional → SURVIVED 2. parseInlines : negated conditional → KILLED |
if (c == 'i' && text.startsWith("image:", i)) { |
| 340 |
1
1. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE |
int endUrl = text.indexOf('[', i + 6); |
| 341 |
1
1. parseInlines : negated conditional → NO_COVERAGE |
if (endUrl != -1) { |
| 342 | int endText = text.indexOf(']', endUrl); | |
| 343 |
1
1. parseInlines : negated conditional → NO_COVERAGE |
if (endText != -1) { |
| 344 | stack.getLast() | |
| 345 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → NO_COVERAGE |
.flushTextToChildren(); |
| 346 |
1
1. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE |
String url = text.substring(i + 6, endUrl); |
| 347 |
1
1. parseInlines : Replaced integer addition with subtraction → NO_COVERAGE |
String title = text.substring(endUrl + 1, endText); |
| 348 | stack.getLast().children.add(new InlineImage(url, Map.of("title", title))); | |
| 349 | i = endText; | |
| 350 | continue; | |
| 351 | } | |
| 352 | } | |
| 353 | } | |
| 354 | ||
| 355 | // Regular char | |
| 356 | stack.getLast().text.append(c); | |
| 357 | } | |
| 358 | ||
| 359 | // Unwind: any unclosed frames become literal markers + content as plain text in parent | |
| 360 |
2
1. parseInlines : changed conditional boundary → KILLED 2. parseInlines : negated conditional → KILLED |
while (stack.size() > 1) { |
| 361 | Frame unfinished = stack.removeLast(); | |
| 362 |
1
1. parseInlines : negated conditional → NO_COVERAGE |
char marker = unfinished.type == FrameType.BOLD ? '*' : '_'; |
| 363 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → NO_COVERAGE |
unfinished.flushTextToChildren(); |
| 364 | // Build literal: marker + children as text + (no closing marker since it is missing) | |
| 365 | StringBuilder literal = new StringBuilder(); | |
| 366 | literal.append(marker); | |
| 367 | for (Inline in : unfinished.children) { | |
| 368 | literal.append(in.text()); | |
| 369 | } | |
| 370 | stack.getLast().text.append(literal); | |
| 371 | } | |
| 372 | ||
| 373 | // Flush remainder text on root | |
| 374 |
1
1. parseInlines : removed call to pro/verron/officestamper/asciidoc/AsciiDocParser$Frame::flushTextToChildren → KILLED |
root.flushTextToChildren(); |
| 375 |
1
1. parseInlines : replaced return value with Collections.emptyList for pro/verron/officestamper/asciidoc/AsciiDocParser::parseInlines → KILLED |
return root.children; |
| 376 | } | |
| 377 | ||
| 378 | private enum FrameType { | |
| 379 | ROOT, | |
| 380 | BOLD, | |
| 381 | ITALIC | |
| 382 | } | |
| 383 | ||
| 384 | private static final class Frame { | |
| 385 | final FrameType type; | |
| 386 | final List<Inline> children = new ArrayList<>(); | |
| 387 | final StringBuilder text = new StringBuilder(); | |
| 388 | ||
| 389 | Frame(FrameType type) {this.type = type;} | |
| 390 | ||
| 391 | void flushTextToChildren() { | |
| 392 |
1
1. flushTextToChildren : negated conditional → KILLED |
if (!text.isEmpty()) { |
| 393 | children.add(new Text(text.toString())); | |
| 394 |
1
1. flushTextToChildren : removed call to java/lang/StringBuilder::setLength → KILLED |
text.setLength(0); |
| 395 | } | |
| 396 | } | |
| 397 | } | |
| 398 | } | |
Mutations | ||
| 33 |
1.1 |
|
| 46 |
1.1 2.2 |
|
| 61 |
1.1 |
|
| 62 |
1.1 |
|
| 65 |
1.1 |
|
| 69 |
1.1 |
|
| 72 |
1.1 |
|
| 79 |
1.1 |
|
| 80 |
1.1 |
|
| 87 |
1.1 |
|
| 89 |
1.1 |
|
| 91 |
1.1 |
|
| 97 |
1.1 |
|
| 98 |
1.1 |
|
| 102 |
1.1 |
|
| 107 |
1.1 |
|
| 110 |
1.1 |
|
| 117 |
1.1 |
|
| 118 |
1.1 |
|
| 125 |
1.1 |
|
| 126 |
1.1 |
|
| 129 |
1.1 |
|
| 132 |
1.1 |
|
| 134 |
1.1 |
|
| 136 |
1.1 |
|
| 143 |
1.1 |
|
| 144 |
1.1 |
|
| 150 |
1.1 |
|
| 153 |
1.1 |
|
| 160 |
1.1 |
|
| 161 |
1.1 |
|
| 173 |
1.1 |
|
| 174 |
1.1 |
|
| 177 |
1.1 |
|
| 183 |
1.1 |
|
| 185 |
1.1 2.2 3.3 |
|
| 188 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
| 189 |
1.1 |
|
| 190 |
1.1 |
|
| 193 |
1.1 |
|
| 203 |
1.1 |
|
| 204 |
1.1 |
|
| 207 |
1.1 |
|
| 212 |
1.1 2.2 |
|
| 215 |
1.1 |
|
| 224 |
1.1 |
|
| 225 |
1.1 |
|
| 228 |
1.1 |
|
| 233 |
1.1 2.2 |
|
| 236 |
1.1 |
|
| 245 |
1.1 |
|
| 251 |
1.1 |
|
| 256 |
1.1 |
|
| 266 |
1.1 2.2 |
|
| 268 |
1.1 2.2 |
|
| 272 |
1.1 |
|
| 273 |
1.1 2.2 3.3 |
|
| 274 |
1.1 |
|
| 275 |
1.1 2.2 3.3 |
|
| 277 |
1.1 |
|
| 286 |
1.1 2.2 |
|
| 287 |
1.1 |
|
| 289 |
1.1 |
|
| 291 |
1.1 |
|
| 292 |
1.1 |
|
| 297 |
1.1 2.2 3.3 |
|
| 299 |
1.1 |
|
| 311 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 |
|
| 312 |
1.1 2.2 3.3 |
|
| 315 |
1.1 |
|
| 317 |
1.1 |
|
| 322 |
1.1 2.2 |
|
| 324 |
1.1 |
|
| 326 |
1.1 |
|
| 328 |
1.1 |
|
| 330 |
1.1 |
|
| 339 |
1.1 2.2 |
|
| 340 |
1.1 |
|
| 341 |
1.1 |
|
| 343 |
1.1 |
|
| 345 |
1.1 |
|
| 346 |
1.1 |
|
| 347 |
1.1 |
|
| 360 |
1.1 2.2 |
|
| 362 |
1.1 |
|
| 363 |
1.1 |
|
| 374 |
1.1 |
|
| 375 |
1.1 |
|
| 392 |
1.1 |
|
| 394 |
1.1 |