app/NamedCommandCatalogReference.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // The checks and the generated reference of the command catalog (split from | ||
| 2 | // NamedCommandCatalog.cpp, which holds the commands and the parser): the | ||
| 3 | // lint of D-14/D-15/D-15a/D-18 and docs/COMMANDS.md. | ||
| 4 | |||
| 5 | #include "NamedCommandCatalog.h" | ||
| 6 | #include <QRegularExpression> | ||
| 7 | #include <QSet> | ||
| 8 | |||
| 9 | 1 | QStringList NamedCommandCatalog::lint() { | |
| 10 |
3/7✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 15 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 15 not taken.
✓ Branch 9 → 10 taken 1 time.
✗ Branch 252 → 253 not taken.
✗ Branch 252 → 254 not taken.
|
2 | static const QRegularExpression word(QStringLiteral("^[a-z]+$")); |
| 11 | 1 | QStringList problems; | |
| 12 | 1 | QSet<QString> seen; | |
| 13 |
3/3✓ Branch 16 → 17 taken 1 time.
✓ Branch 241 → 19 taken 52 times.
✓ Branch 241 → 242 taken 1 time.
|
53 | for (const auto &command : specs()) { |
| 14 | 52 | const QString name = command.name; | |
| 15 |
3/6✓ Branch 22 → 23 taken 52 times.
✓ Branch 23 → 24 taken 52 times.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 30 taken 52 times.
✗ Branch 26 → 27 not taken.
✗ Branch 27 → 28 not taken.
|
52 | if (!word.match(name).hasMatch()) problems << name + ": a name is one lowercase English word (D-15)"; |
| 16 |
1/4✗ Branch 31 → 32 not taken.
✓ Branch 31 → 36 taken 52 times.
✗ Branch 32 → 33 not taken.
✗ Branch 33 → 34 not taken.
|
52 | if (seen.contains(name)) problems << name + ": duplicate name"; |
| 17 |
1/1✓ Branch 36 → 37 taken 52 times.
|
52 | seen.insert(name); |
| 18 |
1/4✗ Branch 38 → 39 not taken.
✓ Branch 38 → 43 taken 52 times.
✗ Branch 39 → 40 not taken.
✗ Branch 40 → 41 not taken.
|
52 | if (!command.aliases.isEmpty()) problems << name + ": aliases are not allowed (D-14)"; |
| 19 |
2/6✓ Branch 43 → 44 taken 52 times.
✗ Branch 43 → 45 not taken.
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 49 taken 52 times.
✗ Branch 45 → 46 not taken.
✗ Branch 46 → 47 not taken.
|
52 | if (!*command.description || !*command.category) problems << name + ": description and category are required"; |
| 20 |
1/4✗ Branch 49 → 50 not taken.
✓ Branch 49 → 54 taken 52 times.
✗ Branch 50 → 51 not taken.
✗ Branch 51 → 52 not taken.
|
52 | if (!*command.keywords) problems << name + ": keywords are required (D-14)"; |
| 21 |
8/12✓ Branch 54 → 55 taken 27 times.
✓ Branch 54 → 60 taken 25 times.
✓ Branch 56 → 57 taken 27 times.
✓ Branch 57 → 58 taken 27 times.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 60 taken 27 times.
✓ Branch 61 → 62 taken 27 times.
✓ Branch 61 → 63 taken 25 times.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 73 taken 52 times.
✗ Branch 275 → 276 not taken.
✗ Branch 275 → 277 not taken.
|
52 | if (command.registryId && !CommandRegistry::find(QString::fromLatin1(command.registryId))) |
| 22 | ✗ | problems << name + ": unknown registry id " + QString::fromLatin1(command.registryId); | |
| 23 |
3/6✓ Branch 73 → 74 taken 38 times.
✓ Branch 73 → 79 taken 14 times.
✗ Branch 74 → 75 not taken.
✓ Branch 74 → 79 taken 38 times.
✗ Branch 75 → 76 not taken.
✗ Branch 76 → 77 not taken.
|
52 | if (command.argument != CommandArgument::None && !*command.syntax) problems << name + ": syntax is required"; |
| 24 |
4/6✓ Branch 79 → 80 taken 17 times.
✓ Branch 79 → 83 taken 35 times.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 17 times.
✗ Branch 84 → 85 not taken.
✓ Branch 84 → 89 taken 52 times.
|
52 | if (command.argument == CommandArgument::Values && command.values.isEmpty()) |
| 25 | ✗ | problems << name + ": a value argument needs values"; | |
| 26 | // D-15a: several values or labels; the syntax shows it with "…". | ||
| 27 |
5/6✓ Branch 89 → 90 taken 5 times.
✓ Branch 89 → 96 taken 47 times.
✓ Branch 90 → 91 taken 2 times.
✓ Branch 90 → 96 taken 3 times.
✗ Branch 91 → 92 not taken.
✓ Branch 91 → 96 taken 2 times.
|
52 | if (command.several && command.argument != CommandArgument::Values && command.argument != CommandArgument::Label) |
| 28 | ✗ | problems << name + ": only values and labels can be several"; | |
| 29 |
3/4✓ Branch 97 → 98 taken 52 times.
✓ Branch 101 → 102 taken 52 times.
✗ Branch 105 → 106 not taken.
✓ Branch 105 → 110 taken 52 times.
|
104 | if (command.several != QString::fromUtf8(command.syntax).contains(QStringLiteral("…"))) |
| 30 | ✗ | problems << name + ": the syntax of a command with several values ends in \"…\" (D-15a)"; | |
| 31 | 52 | QSet<QString> values; | |
| 32 |
2/2✓ Branch 236 → 113 taken 56 times.
✓ Branch 236 → 237 taken 52 times.
|
108 | for (const auto &value : command.values) { |
| 33 |
1/1✓ Branch 115 → 116 taken 56 times.
|
56 | const QString valueWord = QString::fromLatin1(value.word); |
| 34 |
3/8✓ Branch 117 → 118 taken 56 times.
✓ Branch 118 → 119 taken 56 times.
✗ Branch 120 → 121 not taken.
✓ Branch 120 → 129 taken 56 times.
✗ Branch 121 → 122 not taken.
✗ Branch 122 → 123 not taken.
✗ Branch 123 → 124 not taken.
✗ Branch 124 → 125 not taken.
|
56 | if (!word.match(valueWord).hasMatch()) problems << name + " " + valueWord + ": a value is one lowercase word"; |
| 35 |
1/6✗ Branch 130 → 131 not taken.
✓ Branch 130 → 139 taken 56 times.
✗ Branch 131 → 132 not taken.
✗ Branch 132 → 133 not taken.
✗ Branch 133 → 134 not taken.
✗ Branch 134 → 135 not taken.
|
56 | if (values.contains(valueWord)) problems << name + " " + valueWord + ": duplicate value"; |
| 36 |
1/1✓ Branch 139 → 140 taken 56 times.
|
56 | values.insert(valueWord); |
| 37 |
2/8✓ Branch 140 → 141 taken 56 times.
✗ Branch 140 → 142 not taken.
✗ Branch 141 → 142 not taken.
✓ Branch 141 → 150 taken 56 times.
✗ Branch 142 → 143 not taken.
✗ Branch 143 → 144 not taken.
✗ Branch 144 → 145 not taken.
✗ Branch 145 → 146 not taken.
|
56 | if (!*value.description || !*value.keywords) problems << name + " " + valueWord + ": description and keywords"; |
| 38 |
8/12✓ Branch 150 → 151 taken 14 times.
✓ Branch 150 → 156 taken 42 times.
✓ Branch 152 → 153 taken 14 times.
✓ Branch 153 → 154 taken 14 times.
✗ Branch 154 → 155 not taken.
✓ Branch 154 → 156 taken 14 times.
✓ Branch 157 → 158 taken 14 times.
✓ Branch 157 → 159 taken 42 times.
✗ Branch 159 → 160 not taken.
✓ Branch 159 → 168 taken 56 times.
✗ Branch 345 → 346 not taken.
✗ Branch 345 → 347 not taken.
|
56 | if (value.registryId && !CommandRegistry::find(QString::fromLatin1(value.registryId))) |
| 39 | ✗ | problems << name + " " + valueWord + ": unknown registry id"; | |
| 40 |
3/4✓ Branch 168 → 169 taken 12 times.
✓ Branch 168 → 178 taken 44 times.
✗ Branch 169 → 170 not taken.
✓ Branch 169 → 178 taken 12 times.
|
56 | if (command.several && value.then != CommandArgument::None) |
| 41 | ✗ | problems << name + " " + valueWord + ": a value of several takes nothing after it (D-15a)"; | |
| 42 |
4/6✓ Branch 178 → 179 taken 44 times.
✓ Branch 178 → 189 taken 12 times.
✓ Branch 179 → 180 taken 44 times.
✗ Branch 179 → 181 not taken.
✗ Branch 180 → 181 not taken.
✓ Branch 180 → 189 taken 44 times.
|
56 | if (!command.several && (value.group || value.alone)) |
| 43 | ✗ | problems << name + " " + valueWord + ": groups and 'alone' only on commands with several values"; | |
| 44 | // D-15: "on" means a state and exists only on toggles; "off" on | ||
| 45 | // toggles and on the state-like "filter"/"vacation". | ||
| 46 |
4/8✓ Branch 191 → 192 taken 7 times.
✓ Branch 191 → 194 taken 49 times.
✗ Branch 192 → 193 not taken.
✓ Branch 192 → 194 taken 7 times.
✗ Branch 195 → 196 not taken.
✓ Branch 195 → 200 taken 56 times.
✗ Branch 196 → 197 not taken.
✗ Branch 197 → 198 not taken.
|
56 | if (valueWord == QLatin1String("on") && !command.stateKey) problems << name + ": 'on' only on toggles"; |
| 47 |
6/8✓ Branch 202 → 203 taken 9 times.
✓ Branch 202 → 208 taken 47 times.
✓ Branch 203 → 204 taken 1 time.
✓ Branch 203 → 208 taken 8 times.
✗ Branch 206 → 207 not taken.
✓ Branch 206 → 208 taken 1 time.
✗ Branch 209 → 210 not taken.
✓ Branch 209 → 214 taken 56 times.
|
56 | if (valueWord == QLatin1String("off") && !command.stateKey && name != QLatin1String("filter")) |
| 48 | ✗ | problems << name + ": 'off' only on toggles and filter"; | |
| 49 |
6/6✓ Branch 216 → 217 taken 3 times.
✓ Branch 216 → 227 taken 53 times.
✓ Branch 219 → 220 taken 2 times.
✓ Branch 219 → 227 taken 1 time.
✓ Branch 222 → 223 taken 1 time.
✓ Branch 222 → 227 taken 1 time.
|
57 | if (valueWord == QLatin1String("all") && name != QLatin1String("reply") && name != QLatin1String("unlabel") && |
| 50 |
2/4✗ Branch 225 → 226 not taken.
✓ Branch 225 → 227 taken 1 time.
✗ Branch 228 → 229 not taken.
✓ Branch 228 → 233 taken 56 times.
|
57 | name != QLatin1String("tasks")) |
| 51 | ✗ | problems << name + ": 'all' only where it means every recipient/label/task"; | |
| 52 | 56 | } | |
| 53 | 52 | } | |
| 54 | 1 | return problems; | |
| 55 | 1 | } | |
| 56 | |||
| 57 | 1 | QString NamedCommandCatalog::referenceSnapshot() { | |
| 58 | 1 | QString result = QStringLiteral( | |
| 59 | "# Command bar commands\n\n" | ||
| 60 | "Generated from `NamedCommandCatalog::referenceSnapshot()` (`src/app/NamedCommandCatalogReference.cpp`);\n" | ||
| 61 | "`test_named_command_catalog` fails when this file is stale. Notation (D-15): `<required>`,\n" | ||
| 62 | "`[optional]`, `a∣b` fixed values, `…` several of them in one line (D-15a: `mark read important`).\n" | ||
| 63 | "Keywords find a command in the command bar; they are never executed. Keys come from\n" | ||
| 64 | "`CommandRegistry`.\n"); | ||
| 65 | 1 | QString category; | |
| 66 |
3/3✓ Branch 6 → 7 taken 1 time.
✓ Branch 151 → 9 taken 52 times.
✓ Branch 151 → 152 taken 1 time.
|
53 | for (const auto &command : specs()) { |
| 67 |
2/2✓ Branch 12 → 13 taken 13 times.
✓ Branch 12 → 27 taken 39 times.
|
52 | if (category != QLatin1String(command.category)) { |
| 68 |
1/1✓ Branch 14 → 15 taken 13 times.
|
13 | category = QString::fromLatin1(command.category); |
| 69 |
2/2✓ Branch 21 → 22 taken 13 times.
✓ Branch 22 → 23 taken 13 times.
|
26 | result += QStringLiteral("\n## %1\n\n| Command | Description | Key | Keywords |\n|---|---|---|---|\n").arg(category); |
| 70 | } | ||
| 71 |
6/8✓ Branch 27 → 28 taken 27 times.
✓ Branch 27 → 32 taken 25 times.
✓ Branch 29 → 30 taken 27 times.
✓ Branch 30 → 31 taken 27 times.
✓ Branch 33 → 34 taken 27 times.
✓ Branch 33 → 35 taken 25 times.
✗ Branch 167 → 168 not taken.
✗ Branch 167 → 169 not taken.
|
52 | const auto *spec = command.registryId ? CommandRegistry::find(QString::fromLatin1(command.registryId)) : nullptr; |
| 72 |
3/3✓ Branch 35 → 36 taken 27 times.
✓ Branch 35 → 37 taken 25 times.
✓ Branch 36 → 38 taken 27 times.
|
52 | const QString key = spec ? CommandRegistry::keyText(*spec) : QString{}; |
| 73 |
7/9✓ Branch 41 → 42 taken 38 times.
✓ Branch 41 → 45 taken 14 times.
✓ Branch 43 → 44 taken 38 times.
✓ Branch 44 → 46 taken 38 times.
✓ Branch 46 → 47 taken 52 times.
✓ Branch 48 → 49 taken 38 times.
✓ Branch 48 → 50 taken 14 times.
✗ Branch 174 → 175 not taken.
✗ Branch 174 → 176 not taken.
|
52 | QString line = QStringLiteral("`%1%2`").arg(command.name, *command.syntax ? " " + QString::fromUtf8(command.syntax) : QString{}); |
| 74 |
1/1✓ Branch 53 → 54 taken 52 times.
|
52 | QString description = QString::fromUtf8(command.description); |
| 75 |
3/3✓ Branch 54 → 55 taken 3 times.
✓ Branch 54 → 62 taken 49 times.
✓ Branch 58 → 59 taken 3 times.
|
55 | if (command.destructive) description += QStringLiteral(" (destructive)"); |
| 76 |
5/5✓ Branch 62 → 63 taken 38 times.
✓ Branch 62 → 76 taken 14 times.
✓ Branch 68 → 69 taken 38 times.
✓ Branch 69 → 70 taken 38 times.
✓ Branch 70 → 71 taken 38 times.
|
128 | if (*command.example) description += QStringLiteral(" — e.g. `%1`").arg(QString::fromUtf8(command.example)); |
| 77 |
7/9✓ Branch 82 → 83 taken 25 times.
✓ Branch 82 → 84 taken 27 times.
✓ Branch 84 → 85 taken 27 times.
✓ Branch 85 → 86 taken 27 times.
✓ Branch 86 → 87 taken 52 times.
✓ Branch 90 → 91 taken 27 times.
✓ Branch 90 → 92 taken 25 times.
✗ Branch 211 → 212 not taken.
✗ Branch 211 → 213 not taken.
|
208 | result += QStringLiteral("| %1 | %2 | %3 | %4 |\n").arg(line, description, key.isEmpty() ? QString{} : "`" + key + "`", |
| 78 |
2/2✓ Branch 80 → 81 taken 52 times.
✓ Branch 87 → 88 taken 52 times.
|
156 | QString::fromUtf8(command.keywords)); |
| 79 |
2/2✓ Branch 145 → 97 taken 56 times.
✓ Branch 145 → 146 taken 52 times.
|
108 | for (const auto &value : command.values) { |
| 80 |
6/8✓ Branch 98 → 99 taken 14 times.
✓ Branch 98 → 103 taken 42 times.
✓ Branch 100 → 101 taken 14 times.
✓ Branch 101 → 102 taken 14 times.
✓ Branch 104 → 105 taken 14 times.
✓ Branch 104 → 106 taken 42 times.
✗ Branch 227 → 228 not taken.
✗ Branch 227 → 229 not taken.
|
56 | const auto *valueSpec = value.registryId ? CommandRegistry::find(QString::fromLatin1(value.registryId)) : nullptr; |
| 81 |
3/3✓ Branch 106 → 107 taken 14 times.
✓ Branch 106 → 108 taken 42 times.
✓ Branch 107 → 109 taken 14 times.
|
56 | const QString valueKey = valueSpec ? CommandRegistry::keyText(*valueSpec) : QString{}; |
| 82 | 112 | result += QStringLiteral("| `%1 %2%3` | %4 | %5 | %6 |\n") | |
| 83 |
2/2✓ Branch 127 → 128 taken 56 times.
✓ Branch 128 → 129 taken 56 times.
|
112 | .arg(command.name, QString::fromLatin1(value.word), |
| 84 |
6/8✓ Branch 121 → 122 taken 6 times.
✓ Branch 121 → 125 taken 50 times.
✓ Branch 123 → 124 taken 6 times.
✓ Branch 124 → 126 taken 6 times.
✓ Branch 133 → 134 taken 6 times.
✓ Branch 133 → 135 taken 50 times.
✗ Branch 240 → 241 not taken.
✗ Branch 240 → 242 not taken.
|
112 | *value.thenSyntax ? " " + QString::fromUtf8(value.thenSyntax) : QString{}, |
| 85 |
7/9✓ Branch 115 → 116 taken 42 times.
✓ Branch 115 → 117 taken 14 times.
✓ Branch 117 → 118 taken 14 times.
✓ Branch 118 → 119 taken 14 times.
✓ Branch 120 → 121 taken 56 times.
✓ Branch 137 → 138 taken 14 times.
✓ Branch 137 → 139 taken 42 times.
✗ Branch 252 → 253 not taken.
✗ Branch 252 → 254 not taken.
|
112 | QString::fromUtf8(value.description), valueKey.isEmpty() ? QString{} : "`" + valueKey + "`", |
| 86 |
2/2✓ Branch 113 → 114 taken 56 times.
✓ Branch 129 → 130 taken 56 times.
|
168 | QString::fromUtf8(value.keywords)); |
| 87 | 56 | } | |
| 88 | 52 | } | |
| 89 | 1 | return result; | |
| 90 | 1 | } | |
| 91 |