MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 80 / 0 / 80
Functions: 100.0% 5 / 0 / 5
Branches: 83.5% 142 / 0 / 170

data/MarkdownTyping.cpp
Line Branch Exec Source
1 #include "MarkdownTyping.h"
2
3 #include <QRegularExpression>
4
5 namespace MarkdownTyping {
6
7 namespace {
8
9 // The word around `position` looks like a URL or a mail address.
10 31 bool insideLinkLikeWord(const QString &text, int position) {
11 31 int start = position;
12
6/6
✓ Branch 4 → 5 taken 131 times.
✓ Branch 4 → 9 taken 18 times.
✓ Branch 7 → 8 taken 118 times.
✓ Branch 7 → 9 taken 13 times.
✓ Branch 10 → 3 taken 118 times.
✓ Branch 10 → 11 taken 31 times.
149 while (start > 0 && !text.at(start - 1).isSpace()) --start;
13 31 int end = position;
14
6/6
✓ Branch 14 → 15 taken 119 times.
✓ Branch 14 → 19 taken 29 times.
✓ Branch 17 → 18 taken 117 times.
✓ Branch 17 → 19 taken 2 times.
✓ Branch 20 → 12 taken 117 times.
✓ Branch 20 → 21 taken 31 times.
148 while (end < text.size() && !text.at(end).isSpace()) ++end;
15
1/1
✓ Branch 21 → 22 taken 31 times.
31 const QString word = text.mid(start, end - start);
16
5/6
✓ Branch 23 → 24 taken 31 times.
✓ Branch 24 → 25 taken 30 times.
✓ Branch 24 → 36 taken 1 time.
✓ Branch 26 → 27 taken 30 times.
✓ Branch 27 → 28 taken 30 times.
✗ Branch 27 → 36 not taken.
61 return word.contains(QLatin1String("://")) || word.startsWith(QLatin1String("www."), Qt::CaseInsensitive) ||
17
2/5
✓ Branch 30 → 31 taken 30 times.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 37 taken 30 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 37 not taken.
61 (word.contains(QLatin1Char('@')) && word.indexOf(QLatin1Char('@')) > 0);
18 31 }
19
20 26 Conversion blockStart(const QString &text, int caret, const Context &context) {
21 26 Conversion none;
22
6/8
✓ Branch 2 → 3 taken 25 times.
✓ Branch 2 → 6 taken 1 time.
✓ Branch 3 → 4 taken 25 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 23 times.
✓ Branch 4 → 6 taken 2 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 23 times.
26 if (context.inCodeBlock || context.inQuote || context.inList || context.inHeading) return none;
23
1/1
✓ Branch 7 → 8 taken 23 times.
23 const QString prefix = text.left(caret);
24 23 Conversion result;
25 23 result.prefixLength = caret;
26
6/6
✓ Branch 10 → 11 taken 21 times.
✓ Branch 10 → 14 taken 2 times.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 20 times.
✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 18 taken 20 times.
23 if (prefix == QLatin1String("- ") || prefix == QLatin1String("* ")) {
27 3 result.kind = Kind::BulletList;
28 3 return result;
29 }
30
4/7
✓ Branch 18 → 19 taken 3 times.
✓ Branch 18 → 31 taken 17 times.
✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 31 not taken.
✓ Branch 25 → 26 taken 3 times.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
23 static const QRegularExpression numbered(QStringLiteral("^[0-9]{1,3}\\. $"));
31
4/4
✓ Branch 32 → 33 taken 20 times.
✓ Branch 33 → 34 taken 20 times.
✓ Branch 35 → 36 taken 2 times.
✓ Branch 35 → 37 taken 18 times.
20 if (numbered.match(prefix).hasMatch()) {
32 2 result.kind = Kind::NumberedList;
33 2 return result;
34 }
35
2/2
✓ Branch 39 → 40 taken 1 time.
✓ Branch 39 → 41 taken 17 times.
18 if (prefix == QLatin1String("> ")) {
36 1 result.kind = Kind::Quote;
37 1 return result;
38 }
39
8/8
✓ Branch 43 → 44 taken 16 times.
✓ Branch 43 → 50 taken 1 time.
✓ Branch 46 → 47 taken 15 times.
✓ Branch 46 → 50 taken 1 time.
✓ Branch 49 → 50 taken 1 time.
✓ Branch 49 → 51 taken 14 times.
✓ Branch 52 → 53 taken 3 times.
✓ Branch 52 → 55 taken 14 times.
17 if (prefix == QLatin1String("# ") || prefix == QLatin1String("## ") || prefix == QLatin1String("### ")) {
40 3 result.kind = Kind::Heading;
41 3 result.headingLevel = int(prefix.size()) - 1;
42 3 return result;
43 }
44 14 return none;
45 23 }
46
47 26 Conversion inlineMarker(const QString &text, int caret, QChar typed, const Context &context) {
48 26 Conversion none;
49
5/6
✓ Branch 2 → 3 taken 26 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 25 times.
✓ Branch 3 → 5 taken 1 time.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 24 times.
26 if (context.inCodeBlock || context.inInlineCode || context.inQuote) return none;
50
5/6
✓ Branch 6 → 7 taken 22 times.
✓ Branch 6 → 9 taken 2 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 22 times.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 22 times.
24 if (caret < 3 || caret > text.size()) return none;
51
3/4
✓ Branch 17 → 18 taken 15 times.
✗ Branch 17 → 26 not taken.
✓ Branch 22 → 23 taken 5 times.
✓ Branch 22 → 26 taken 10 times.
37 const QString marker = (typed == QLatin1Char('*') && caret >= 2 && text.at(caret - 2) == QLatin1Char('*'))
52
4/6
✓ Branch 16 → 17 taken 15 times.
✓ Branch 16 → 26 taken 7 times.
✓ Branch 27 → 28 taken 5 times.
✓ Branch 27 → 29 taken 17 times.
✗ Branch 119 → 120 not taken.
✗ Branch 119 → 121 not taken.
44 ? QStringLiteral("**")
53
1/1
✓ Branch 26 → 27 taken 17 times.
44 : QString(typed);
54 22 const int length = int(marker.size());
55 22 const int closeStart = caret - length;
56 // The opening marker: the nearest earlier occurrence on this line.
57
1/1
✓ Branch 30 → 31 taken 22 times.
22 const int openStart = int(text.lastIndexOf(marker, closeStart - 1));
58
2/2
✓ Branch 31 → 32 taken 3 times.
✓ Branch 31 → 33 taken 19 times.
22 if (openStart < 0) return none;
59 19 const int contentStart = openStart + length;
60 19 const int contentLength = closeStart - contentStart;
61
2/2
✓ Branch 33 → 34 taken 1 time.
✓ Branch 33 → 35 taken 18 times.
19 if (contentLength <= 0) return none;
62
1/1
✓ Branch 35 → 36 taken 18 times.
18 const QString content = text.mid(contentStart, contentLength);
63
8/8
✓ Branch 36 → 37 taken 18 times.
✓ Branch 38 → 39 taken 17 times.
✓ Branch 38 → 42 taken 1 time.
✓ Branch 39 → 40 taken 17 times.
✓ Branch 41 → 42 taken 1 time.
✓ Branch 41 → 43 taken 16 times.
✓ Branch 44 → 45 taken 2 times.
✓ Branch 44 → 46 taken 16 times.
18 if (content.front().isSpace() || content.back().isSpace()) return none;
64
7/8
✓ Branch 46 → 47 taken 16 times.
✓ Branch 47 → 48 taken 15 times.
✓ Branch 47 → 50 taken 1 time.
✓ Branch 48 → 49 taken 15 times.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 51 taken 15 times.
✓ Branch 52 → 53 taken 1 time.
✓ Branch 52 → 54 taken 15 times.
16 if (insideLinkLikeWord(text, openStart) || insideLinkLikeWord(text, closeStart)) return none;
65
2/2
✓ Branch 54 → 55 taken 11 times.
✓ Branch 54 → 56 taken 4 times.
15 const QChar before = openStart > 0 ? text.at(openStart - 1) : QChar(QLatin1Char(' '));
66
2/2
✓ Branch 60 → 61 taken 2 times.
✓ Branch 60 → 66 taken 13 times.
15 if (marker == QLatin1String("`")) {
67
2/3
✓ Branch 63 → 64 taken 2 times.
✗ Branch 64 → 65 not taken.
✓ Branch 64 → 104 taken 2 times.
2 if (content.contains(QLatin1Char('`'))) return none;
68
2/2
✓ Branch 68 → 69 taken 3 times.
✓ Branch 68 → 83 taken 10 times.
13 } else if (marker == QLatin1String("**")) {
69
3/6
✓ Branch 70 → 71 taken 3 times.
✗ Branch 70 → 75 not taken.
✗ Branch 74 → 75 not taken.
✓ Branch 74 → 76 taken 3 times.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 79 taken 3 times.
3 if (before.isLetterOrNumber() || before == QLatin1Char('*')) return none;
70
2/3
✓ Branch 80 → 81 taken 3 times.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 104 taken 3 times.
3 if (content.contains(QLatin1String("**"))) return none;
71 } else {
72 // Single * or _: both markers touch letters (D-7), the opening one does
73 // not follow a word character (2*3*4, snake_case, a*b*c stay).
74
6/6
✓ Branch 84 → 85 taken 5 times.
✓ Branch 84 → 87 taken 5 times.
✓ Branch 86 → 87 taken 1 time.
✓ Branch 86 → 88 taken 4 times.
✓ Branch 89 → 90 taken 6 times.
✓ Branch 89 → 91 taken 4 times.
10 if (before.isLetterOrNumber() || before == typed) return none;
75
7/8
✓ Branch 91 → 92 taken 4 times.
✓ Branch 93 → 94 taken 3 times.
✓ Branch 93 → 97 taken 1 time.
✓ Branch 94 → 95 taken 3 times.
✗ Branch 96 → 97 not taken.
✓ Branch 96 → 98 taken 3 times.
✓ Branch 99 → 100 taken 1 time.
✓ Branch 99 → 101 taken 3 times.
4 if (!content.front().isLetter() || !content.back().isLetter()) return none;
76
2/3
✓ Branch 101 → 102 taken 3 times.
✗ Branch 102 → 103 not taken.
✓ Branch 102 → 104 taken 3 times.
3 if (content.contains(typed)) return none;
77 }
78 8 Conversion result;
79
2/2
✓ Branch 106 → 107 taken 3 times.
✓ Branch 106 → 108 taken 5 times.
13 result.kind = marker == QLatin1String("**") ? Kind::Bold
80
2/2
✓ Branch 110 → 111 taken 2 times.
✓ Branch 110 → 112 taken 3 times.
5 : marker == QLatin1String("`") ? Kind::Code
81 : Kind::Italic;
82 8 result.openStart = openStart;
83 8 result.markerLength = length;
84 8 result.contentStart = contentStart;
85 8 result.contentLength = contentLength;
86 8 result.closeStart = closeStart;
87 8 return result;
88 22 }
89
90 } // namespace
91
92 163 Conversion afterTyping(const QString &text, int caret, QChar typed, const Context &context) {
93
3/6
✓ Branch 2 → 3 taken 163 times.
✗ Branch 2 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 163 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 163 times.
163 if (caret <= 0 || caret > text.size()) return {};
94
2/2
✓ Branch 12 → 13 taken 26 times.
✓ Branch 12 → 14 taken 137 times.
163 if (typed == QLatin1Char(' ')) return blockStart(text, caret, context);
95
8/8
✓ Branch 17 → 18 taken 120 times.
✓ Branch 17 → 26 taken 17 times.
✓ Branch 21 → 22 taken 114 times.
✓ Branch 21 → 26 taken 6 times.
✓ Branch 25 → 26 taken 3 times.
✓ Branch 25 → 27 taken 111 times.
✓ Branch 28 → 29 taken 26 times.
✓ Branch 28 → 30 taken 111 times.
137 if (typed == QLatin1Char('*') || typed == QLatin1Char('_') || typed == QLatin1Char('`'))
96 26 return inlineMarker(text, caret, typed, context);
97 111 return {};
98 }
99
100 5 Conversion afterEnter(const QString &text, const Context &context) {
101
5/8
✓ Branch 2 → 3 taken 5 times.
✗ Branch 2 → 6 not taken.
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 6 taken 1 time.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 4 times.
5 if (context.inCodeBlock || context.inQuote || context.inList || context.inHeading) return {};
102
2/2
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 2 times.
4 if (text != QLatin1String("---")) return {};
103 2 Conversion result;
104 2 result.kind = Kind::Rule;
105 2 result.prefixLength = 3;
106 2 return result;
107 }
108
109 } // namespace MarkdownTyping
110