presentation/SieveSyntaxHighlighter.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "SieveSyntaxHighlighter.h" | ||
| 2 | |||
| 3 | #include <QSet> | ||
| 4 | #include <QTextDocument> | ||
| 5 | |||
| 6 | namespace { | ||
| 7 | |||
| 8 | 310 | const QSet<QString> &keywords() { | |
| 9 | static const QSet<QString> words = { | ||
| 10 | 2 | QStringLiteral("require"), QStringLiteral("if"), QStringLiteral("elsif"), | |
| 11 | 2 | QStringLiteral("else"), QStringLiteral("stop"), QStringLiteral("keep"), | |
| 12 | 2 | QStringLiteral("discard"), QStringLiteral("fileinto"), QStringLiteral("redirect"), | |
| 13 | 2 | QStringLiteral("reject"), QStringLiteral("ereject"), QStringLiteral("vacation"), | |
| 14 | 2 | QStringLiteral("addflag"), QStringLiteral("setflag"), QStringLiteral("removeflag"), | |
| 15 | 2 | QStringLiteral("header"), QStringLiteral("address"), QStringLiteral("envelope"), | |
| 16 | 2 | QStringLiteral("size"), QStringLiteral("exists"), QStringLiteral("allof"), | |
| 17 | 2 | QStringLiteral("anyof"), QStringLiteral("not"), QStringLiteral("true"), | |
| 18 | 2 | QStringLiteral("false"), QStringLiteral("body"), QStringLiteral("currentdate"), | |
| 19 | 2 | QStringLiteral("date"), QStringLiteral("set"), QStringLiteral("include"), | |
| 20 | 2 | QStringLiteral("return"), QStringLiteral("global"), QStringLiteral("addheader"), | |
| 21 | 2 | QStringLiteral("deleteheader"), QStringLiteral("notify"), QStringLiteral("hasflag"), | |
| 22 | 2 | QStringLiteral("mailboxexists"), QStringLiteral("duplicate"), QStringLiteral("foreverypart"), | |
| 23 | 2 | QStringLiteral("break"), QStringLiteral("spamtest"), QStringLiteral("virustest"), | |
| 24 |
5/10✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 192 taken 308 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 192 not taken.
✓ Branch 144 → 145 taken 90 times.
✓ Branch 144 → 146 taken 2 times.
✗ Branch 195 → 196 not taken.
✗ Branch 195 → 197 not taken.
✗ Branch 339 → 340 not taken.
✗ Branch 339 → 341 not taken.
|
404 | QStringLiteral("environment"), QStringLiteral("string"), QStringLiteral("specialuse_exists")}; |
| 25 | 310 | return words; | |
| 26 | 92 | } | |
| 27 | |||
| 28 |
3/4✓ Branch 3 → 4 taken 411 times.
✓ Branch 3 → 8 taken 2359 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 411 times.
|
2770 | bool identifierChar(QChar c) { return c.isLetterOrNumber() || c == QLatin1Char('_'); } |
| 29 | |||
| 30 | } // namespace | ||
| 31 | |||
| 32 | 9 | SieveSyntaxHighlighter::SieveSyntaxHighlighter(QTextDocument *document) : QSyntaxHighlighter(document) {} | |
| 33 | |||
| 34 | 9 | void SieveSyntaxHighlighter::setColors(const Colors &colors) { | |
| 35 | 9 | m_colors = colors; | |
| 36 | 9 | rehighlight(); | |
| 37 | 9 | } | |
| 38 | |||
| 39 | 5 | void SieveSyntaxHighlighter::setErrorLine(int line) { | |
| 40 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 4 times.
|
5 | if (m_errorLine == line) |
| 41 | 1 | return; | |
| 42 | 4 | const int previous = m_errorLine; | |
| 43 | 4 | m_errorLine = line; | |
| 44 |
2/2✓ Branch 14 → 6 taken 8 times.
✓ Branch 14 → 15 taken 4 times.
|
12 | for (const int changed : {previous, line}) |
| 45 |
2/2✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 13 taken 4 times.
|
8 | if (changed > 0) |
| 46 |
4/5✓ Branch 7 → 8 taken 4 times.
✓ Branch 8 → 9 taken 4 times.
✓ Branch 9 → 10 taken 4 times.
✓ Branch 10 → 11 taken 4 times.
✗ Branch 10 → 12 not taken.
|
4 | if (const QTextBlock block = document()->findBlockByNumber(changed - 1); block.isValid()) |
| 47 |
1/1✓ Branch 11 → 12 taken 4 times.
|
4 | rehighlightBlock(block); |
| 48 | } | ||
| 49 | |||
| 50 | 810 | QTextCharFormat SieveSyntaxHighlighter::format(const QColor &color, bool bold, bool italic) const { | |
| 51 | 810 | QTextCharFormat result; | |
| 52 |
1/2✓ Branch 4 → 5 taken 810 times.
✗ Branch 4 → 9 not taken.
|
810 | if (color.isValid()) |
| 53 |
2/2✓ Branch 5 → 6 taken 810 times.
✓ Branch 6 → 7 taken 810 times.
|
810 | result.setForeground(color); |
| 54 |
2/2✓ Branch 9 → 10 taken 309 times.
✓ Branch 9 → 11 taken 501 times.
|
810 | if (bold) |
| 55 |
1/1✓ Branch 10 → 11 taken 309 times.
|
309 | result.setFontWeight(QFont::DemiBold); |
| 56 |
1/1✓ Branch 11 → 12 taken 810 times.
|
810 | result.setFontItalic(italic); |
| 57 | 810 | return result; | |
| 58 | ✗ | } | |
| 59 | |||
| 60 | 443 | void SieveSyntaxHighlighter::highlightBlock(const QString &text) { | |
| 61 | 443 | int pos = 0; | |
| 62 |
2/2✓ Branch 3 → 4 taken 434 times.
✓ Branch 3 → 6 taken 9 times.
|
443 | int state = previousBlockState() < 0 ? Normal : previousBlockState(); |
| 63 |
2/2✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 24 taken 441 times.
|
443 | if (state == InMultiLine) { |
| 64 | // The string ends at a line that is a single "." (dot-stuffing keeps ".."). | ||
| 65 |
2/2✓ Branch 8 → 9 taken 2 times.
✓ Branch 10 → 11 taken 2 times.
|
2 | setFormat(0, text.size(), format(m_colors.string)); |
| 66 |
4/5✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 18 taken 1 time.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 1 time.
✓ Branch 20 → 21 taken 2 times.
|
2 | setCurrentBlockState(text == QLatin1String(".") || text == QLatin1String(".\r") ? Normal : InMultiLine); |
| 67 | 2 | pos = text.size(); | |
| 68 | 2 | state = currentBlockState(); | |
| 69 | } else { | ||
| 70 | 441 | setCurrentBlockState(Normal); | |
| 71 | } | ||
| 72 |
2/2✓ Branch 173 → 26 taken 1769 times.
✓ Branch 173 → 174 taken 352 times.
|
2121 | while (pos < text.size()) { |
| 73 | 1769 | const QChar c = text.at(pos); | |
| 74 |
2/2✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 38 taken 1767 times.
|
1769 | if (state == InBracketComment) { |
| 75 |
1/1✓ Branch 29 → 30 taken 2 times.
|
2 | const int close = text.indexOf(QLatin1String("*/"), pos); |
| 76 |
2/2✓ Branch 30 → 31 taken 1 time.
✓ Branch 30 → 33 taken 1 time.
|
2 | const int end = close < 0 ? text.size() : close + 2; |
| 77 |
2/2✓ Branch 34 → 35 taken 2 times.
✓ Branch 35 → 36 taken 2 times.
|
2 | setFormat(pos, end - pos, format(m_colors.comment)); |
| 78 | 2 | pos = end; | |
| 79 | 2 | state = close < 0 ? InBracketComment : Normal; | |
| 80 | 685 | continue; | |
| 81 | 2 | } | |
| 82 |
2/2✓ Branch 41 → 42 taken 88 times.
✓ Branch 41 → 47 taken 1679 times.
|
1767 | if (c == QLatin1Char('#')) { |
| 83 |
2/2✓ Branch 42 → 43 taken 88 times.
✓ Branch 44 → 45 taken 88 times.
|
88 | setFormat(pos, text.size() - pos, format(m_colors.comment)); |
| 84 | 91 | break; | |
| 85 | } | ||
| 86 |
6/8✓ Branch 50 → 51 taken 1 time.
✓ Branch 50 → 59 taken 1678 times.
✓ Branch 52 → 53 taken 1 time.
✗ Branch 52 → 59 not taken.
✓ Branch 57 → 58 taken 1 time.
✗ Branch 57 → 59 not taken.
✓ Branch 60 → 61 taken 1 time.
✓ Branch 60 → 62 taken 1678 times.
|
1679 | if (c == QLatin1Char('/') && pos + 1 < text.size() && text.at(pos + 1) == QLatin1Char('*')) { |
| 87 | 1 | state = InBracketComment; | |
| 88 | 1 | continue; | |
| 89 | } | ||
| 90 |
2/2✓ Branch 65 → 66 taken 272 times.
✓ Branch 65 → 91 taken 1406 times.
|
1678 | if (c == QLatin1Char('"')) { |
| 91 | 272 | int end = pos + 1; | |
| 92 |
5/6✓ Branch 76 → 77 taken 3628 times.
✗ Branch 76 → 83 not taken.
✓ Branch 81 → 82 taken 3356 times.
✓ Branch 81 → 83 taken 272 times.
✓ Branch 84 → 67 taken 3356 times.
✓ Branch 84 → 85 taken 272 times.
|
3628 | while (end < text.size() && text.at(end) != QLatin1Char('"')) |
| 93 |
2/2✓ Branch 71 → 72 taken 10 times.
✓ Branch 71 → 73 taken 3346 times.
|
3356 | end += text.at(end) == QLatin1Char('\\') ? 2 : 1; |
| 94 | 272 | end = qMin(end + 1, int(text.size())); | |
| 95 |
2/2✓ Branch 87 → 88 taken 272 times.
✓ Branch 88 → 89 taken 272 times.
|
272 | setFormat(pos, end - pos, format(m_colors.string)); |
| 96 | 272 | pos = end; | |
| 97 | 272 | continue; | |
| 98 | 272 | } | |
| 99 |
6/8✓ Branch 94 → 95 taken 100 times.
✓ Branch 94 → 101 taken 1306 times.
✓ Branch 96 → 97 taken 100 times.
✗ Branch 96 → 101 not taken.
✓ Branch 99 → 100 taken 100 times.
✗ Branch 99 → 101 not taken.
✓ Branch 102 → 103 taken 100 times.
✓ Branch 102 → 117 taken 1306 times.
|
1406 | if (c == QLatin1Char(':') && pos + 1 < text.size() && identifierChar(text.at(pos + 1))) { |
| 100 | 100 | int end = pos + 1; | |
| 101 |
5/6✓ Branch 106 → 107 taken 750 times.
✗ Branch 106 → 111 not taken.
✓ Branch 109 → 110 taken 650 times.
✓ Branch 109 → 111 taken 100 times.
✓ Branch 112 → 104 taken 650 times.
✓ Branch 112 → 113 taken 100 times.
|
750 | while (end < text.size() && identifierChar(text.at(end))) |
| 102 | 650 | ++end; | |
| 103 |
2/2✓ Branch 113 → 114 taken 100 times.
✓ Branch 114 → 115 taken 100 times.
|
100 | setFormat(pos, end - pos, format(m_colors.tag, false, true)); |
| 104 | 100 | pos = end; | |
| 105 | 100 | continue; | |
| 106 | 100 | } | |
| 107 |
5/6✓ Branch 118 → 119 taken 993 times.
✓ Branch 118 → 123 taken 313 times.
✗ Branch 122 → 123 not taken.
✓ Branch 122 → 124 taken 993 times.
✓ Branch 125 → 126 taken 313 times.
✓ Branch 125 → 169 taken 993 times.
|
1306 | if (c.isLetter() || c == QLatin1Char('_')) { |
| 108 | 313 | int end = pos; | |
| 109 |
6/6✓ Branch 129 → 130 taken 1920 times.
✓ Branch 129 → 134 taken 2 times.
✓ Branch 132 → 133 taken 1609 times.
✓ Branch 132 → 134 taken 311 times.
✓ Branch 135 → 127 taken 1609 times.
✓ Branch 135 → 136 taken 313 times.
|
1922 | while (end < text.size() && identifierChar(text.at(end))) |
| 110 | 1609 | ++end; | |
| 111 |
2/2✓ Branch 136 → 137 taken 313 times.
✓ Branch 137 → 138 taken 313 times.
|
313 | const QString word = text.mid(pos, end - pos).toLower(); |
| 112 |
6/8✓ Branch 141 → 142 taken 3 times.
✓ Branch 141 → 150 taken 310 times.
✓ Branch 143 → 144 taken 3 times.
✗ Branch 143 → 150 not taken.
✓ Branch 148 → 149 taken 3 times.
✗ Branch 148 → 150 not taken.
✓ Branch 151 → 152 taken 3 times.
✓ Branch 151 → 157 taken 310 times.
|
313 | if (word == QLatin1String("text") && end < text.size() && text.at(end) == QLatin1Char(':')) { |
| 113 |
2/2✓ Branch 152 → 153 taken 3 times.
✓ Branch 154 → 155 taken 3 times.
|
3 | setFormat(pos, text.size() - pos, format(m_colors.string)); |
| 114 | 3 | state = InMultiLine; | |
| 115 | 3 | break; | |
| 116 | } | ||
| 117 |
3/3✓ Branch 157 → 158 taken 310 times.
✓ Branch 159 → 160 taken 309 times.
✓ Branch 159 → 164 taken 1 time.
|
310 | if (keywords().contains(word)) |
| 118 |
2/2✓ Branch 160 → 161 taken 309 times.
✓ Branch 161 → 162 taken 309 times.
|
309 | setFormat(pos, end - pos, format(m_colors.keyword, true)); |
| 119 | 310 | pos = end; | |
| 120 | 310 | continue; | |
| 121 | 313 | } | |
| 122 | 993 | ++pos; | |
| 123 | } | ||
| 124 |
2/2✓ Branch 174 → 175 taken 5 times.
✓ Branch 174 → 176 taken 438 times.
|
443 | if (state != Normal) |
| 125 | 5 | setCurrentBlockState(state); | |
| 126 |
7/8✓ Branch 176 → 177 taken 7 times.
✓ Branch 176 → 181 taken 436 times.
✓ Branch 177 → 178 taken 7 times.
✓ Branch 178 → 179 taken 7 times.
✓ Branch 179 → 180 taken 7 times.
✗ Branch 179 → 181 not taken.
✓ Branch 182 → 183 taken 7 times.
✓ Branch 182 → 193 taken 436 times.
|
443 | if (m_errorLine > 0 && currentBlock().blockNumber() == m_errorLine - 1) { |
| 127 |
2/2✓ Branch 192 → 184 taken 34 times.
✓ Branch 192 → 193 taken 7 times.
|
41 | for (int i = 0; i < text.size(); ++i) { |
| 128 |
1/1✓ Branch 185 → 186 taken 34 times.
|
34 | QTextCharFormat underline = this->format(i); |
| 129 |
1/1✓ Branch 186 → 187 taken 34 times.
|
34 | underline.setUnderlineStyle(QTextCharFormat::WaveUnderline); |
| 130 |
1/1✓ Branch 187 → 188 taken 34 times.
|
34 | underline.setUnderlineColor(m_colors.error); |
| 131 |
1/1✓ Branch 188 → 189 taken 34 times.
|
34 | setFormat(i, 1, underline); |
| 132 | 34 | } | |
| 133 | } | ||
| 134 | 443 | } | |
| 135 |