Changeset View
Changeset View
Standalone View
Standalone View
src/indexer/katehighlightingindexer.cpp
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | 50 | while (!xml.atEnd()) { | |||
---|---|---|---|---|---|
54 | if (xml.isCharacters() && xml.text().toString().contains(QLatin1String(".xml"))) { | 54 | if (xml.isCharacters() && xml.text().toString().contains(QLatin1String(".xml"))) { | ||
55 | listing.append(xml.text().toString()); | 55 | listing.append(xml.text().toString()); | ||
56 | } | 56 | } | ||
57 | } | 57 | } | ||
58 | 58 | | |||
59 | if (xml.hasError()) { | 59 | if (xml.hasError()) { | ||
60 | qWarning() << "XML error while reading" << fileName << " - " | 60 | qWarning() << "XML error while reading" << fileName << " - " | ||
61 | << qPrintable(xml.errorString()) << "@ offset" << xml.characterOffset(); | 61 | << qPrintable(xml.errorString()) << "@ offset" << xml.characterOffset(); | ||
62 | listing.clear(); | ||||
62 | } | 63 | } | ||
63 | 64 | | |||
64 | return listing; | 65 | return listing; | ||
65 | } | 66 | } | ||
66 | 67 | | |||
67 | /** | 68 | /** | ||
68 | * check if the "extensions" attribute have valid wildcards | 69 | * check if the "extensions" attribute have valid wildcards | ||
69 | * @param extensions extensions string to check | 70 | * @param extensions extensions string to check | ||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Line(s) | |||||
158 | { | 159 | { | ||
159 | const bool testChar1 = xml.name() == QLatin1String("Detect2Chars"); | 160 | const bool testChar1 = xml.name() == QLatin1String("Detect2Chars"); | ||
160 | const bool testChar = testChar1 || xml.name() == QLatin1String("DetectChar"); | 161 | const bool testChar = testChar1 || xml.name() == QLatin1String("DetectChar"); | ||
161 | 162 | | |||
162 | if (testChar) { | 163 | if (testChar) { | ||
163 | const QString c = xml.attributes().value(QLatin1String("char")).toString(); | 164 | const QString c = xml.attributes().value(QLatin1String("char")).toString(); | ||
164 | if (c.size() != 1) { | 165 | if (c.size() != 1) { | ||
165 | qWarning() << hlFilename << "line" << xml.lineNumber() << "'char' must contain exactly one char:" << c; | 166 | qWarning() << hlFilename << "line" << xml.lineNumber() << "'char' must contain exactly one char:" << c; | ||
167 | return false; | ||||
166 | } | 168 | } | ||
167 | } | 169 | } | ||
168 | 170 | | |||
169 | if (testChar1) { | 171 | if (testChar1) { | ||
170 | const QString c = xml.attributes().value(QLatin1String("char1")).toString(); | 172 | const QString c = xml.attributes().value(QLatin1String("char1")).toString(); | ||
171 | if (c.size() != 1) { | 173 | if (c.size() != 1) { | ||
172 | qWarning() << hlFilename << "line" << xml.lineNumber() << "'char1' must contain exactly one char:" << c; | 174 | qWarning() << hlFilename << "line" << xml.lineNumber() << "'char1' must contain exactly one char:" << c; | ||
175 | return false; | ||||
173 | } | 176 | } | ||
174 | } | 177 | } | ||
175 | 178 | | |||
176 | return true; | 179 | return true; | ||
177 | } | 180 | } | ||
178 | 181 | | |||
179 | //! Search for rules with lookAhead="true" and context="#stay". | 182 | //! Search for rules with lookAhead="true" and context="#stay". | ||
180 | //! This would cause an infinite loop. | 183 | //! This would cause an infinite loop. | ||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Line(s) | 280 | public: | |||
280 | {} | 283 | {} | ||
281 | 284 | | |||
282 | void processElement(QXmlStreamReader &xml) | 285 | void processElement(QXmlStreamReader &xml) | ||
283 | { | 286 | { | ||
284 | if (xml.name() == QLatin1String("list")) { | 287 | if (xml.name() == QLatin1String("list")) { | ||
285 | const QString name = xml.attributes().value(QLatin1String("name")).toString(); | 288 | const QString name = xml.attributes().value(QLatin1String("name")).toString(); | ||
286 | if (m_existingNames.contains(name)) { | 289 | if (m_existingNames.contains(name)) { | ||
287 | qWarning() << m_filename << "list duplicate:" << name; | 290 | qWarning() << m_filename << "list duplicate:" << name; | ||
291 | m_success = false; | ||||
288 | } | 292 | } | ||
289 | m_existingNames.insert(name); | 293 | m_existingNames.insert(name); | ||
290 | } else if (xml.name() == QLatin1String("keyword")) { | 294 | } else if (xml.name() == QLatin1String("keyword")) { | ||
291 | const QString context = xml.attributes().value(QLatin1String("String")).toString(); | 295 | const QString context = xml.attributes().value(QLatin1String("String")).toString(); | ||
292 | if (!context.isEmpty()) | 296 | if (!context.isEmpty()) | ||
293 | m_usedNames.insert(context); | 297 | m_usedNames.insert(context); | ||
294 | } | 298 | } | ||
295 | } | 299 | } | ||
296 | 300 | | |||
297 | bool check() const | 301 | bool check() const | ||
298 | { | 302 | { | ||
299 | bool success = true; | 303 | bool success = m_success; | ||
300 | const auto invalidNames = m_usedNames - m_existingNames; | 304 | const auto invalidNames = m_usedNames - m_existingNames; | ||
301 | if (!invalidNames.isEmpty()) { | 305 | if (!invalidNames.isEmpty()) { | ||
302 | qWarning() << m_filename << "Reference of non-existing keyword list:" << invalidNames; | 306 | qWarning() << m_filename << "Reference of non-existing keyword list:" << invalidNames; | ||
303 | success = false; | 307 | success = false; | ||
304 | } | 308 | } | ||
305 | 309 | | |||
306 | const auto unusedNames = m_existingNames - m_usedNames; | 310 | const auto unusedNames = m_existingNames - m_usedNames; | ||
307 | if (!unusedNames.isEmpty()) { | 311 | if (!unusedNames.isEmpty()) { | ||
308 | qWarning() << m_filename << "Unused keyword lists:" << unusedNames; | 312 | qWarning() << m_filename << "Unused keyword lists:" << unusedNames; | ||
313 | success = false; | ||||
309 | } | 314 | } | ||
310 | 315 | | |||
311 | return success; | 316 | return success; | ||
312 | } | 317 | } | ||
313 | 318 | | |||
314 | private: | 319 | private: | ||
315 | QString m_filename; | 320 | QString m_filename; | ||
316 | QSet<QString> m_usedNames; | 321 | QSet<QString> m_usedNames; | ||
317 | QSet<QString> m_existingNames; | 322 | QSet<QString> m_existingNames; | ||
323 | bool m_success = true; | ||||
318 | }; | 324 | }; | ||
319 | 325 | | |||
320 | /** | 326 | /** | ||
321 | * Helper class to search for non-existing contexts | 327 | * Helper class to search for non-existing contexts | ||
322 | */ | 328 | */ | ||
323 | class ContextChecker | 329 | class ContextChecker | ||
324 | { | 330 | { | ||
325 | public: | 331 | public: | ||
326 | void processElement(const QString &hlFilename, const QString &hlName, QXmlStreamReader &xml) | 332 | void processElement(const QString &hlFilename, const QString &hlName, QXmlStreamReader &xml) | ||
327 | { | 333 | { | ||
328 | if (xml.name() == QLatin1String("context")) { | 334 | if (xml.name() == QLatin1String("context")) { | ||
329 | auto & language = m_contextMap[hlName]; | 335 | auto & language = m_contextMap[hlName]; | ||
330 | language.hlFilename = hlFilename; | 336 | language.hlFilename = hlFilename; | ||
331 | const QString name = xml.attributes().value(QLatin1String("name")).toString(); | 337 | const QString name = xml.attributes().value(QLatin1String("name")).toString(); | ||
332 | if (language.isFirstContext) { | 338 | if (language.isFirstContext) { | ||
333 | language.isFirstContext = false; | 339 | language.isFirstContext = false; | ||
334 | language.usedContextNames.insert(name); | 340 | language.usedContextNames.insert(name); | ||
335 | } | 341 | } | ||
336 | 342 | | |||
337 | if (language.existingContextNames.contains(name)) { | 343 | if (language.existingContextNames.contains(name)) { | ||
338 | qWarning() << hlFilename << "Duplicate context:" << name; | 344 | qWarning() << hlFilename << "Duplicate context:" << name; | ||
345 | m_success = false; | ||||
339 | } else { | 346 | } else { | ||
340 | language.existingContextNames.insert(name); | 347 | language.existingContextNames.insert(name); | ||
341 | } | 348 | } | ||
342 | 349 | | |||
343 | if (xml.attributes().value(QLatin1String("fallthroughContext")).toString() == QLatin1String("#stay")) { | 350 | if (xml.attributes().value(QLatin1String("fallthroughContext")).toString() == QLatin1String("#stay")) { | ||
344 | qWarning() << hlFilename << "possible infinite loop due to fallthroughContext=\"#stay\" in context " << name; | 351 | qWarning() << hlFilename << "possible infinite loop due to fallthroughContext=\"#stay\" in context " << name; | ||
352 | m_success = false; | ||||
345 | } | 353 | } | ||
346 | 354 | | |||
347 | processContext(hlName, xml.attributes().value(QLatin1String("lineEndContext")).toString()); | 355 | processContext(hlName, xml.attributes().value(QLatin1String("lineEndContext")).toString()); | ||
348 | processContext(hlName, xml.attributes().value(QLatin1String("lineEmptyContext")).toString()); | 356 | processContext(hlName, xml.attributes().value(QLatin1String("lineEmptyContext")).toString()); | ||
349 | processContext(hlName, xml.attributes().value(QLatin1String("fallthroughContext")).toString()); | 357 | processContext(hlName, xml.attributes().value(QLatin1String("fallthroughContext")).toString()); | ||
350 | } else { | 358 | } else { | ||
351 | if (xml.attributes().hasAttribute(QLatin1String("context"))) { | 359 | if (xml.attributes().hasAttribute(QLatin1String("context"))) { | ||
352 | const QString context = xml.attributes().value(QLatin1String("context")).toString(); | 360 | const QString context = xml.attributes().value(QLatin1String("context")).toString(); | ||
353 | if (context.isEmpty()) { | 361 | if (context.isEmpty()) { | ||
354 | qWarning() << hlFilename << "Missing context name in line" << xml.lineNumber(); | 362 | qWarning() << hlFilename << "Missing context name in line" << xml.lineNumber(); | ||
363 | m_success = false; | ||||
355 | } else { | 364 | } else { | ||
356 | processContext(hlName, context); | 365 | processContext(hlName, context); | ||
357 | } | 366 | } | ||
358 | } | 367 | } | ||
359 | } | 368 | } | ||
360 | } | 369 | } | ||
361 | 370 | | |||
362 | bool check() const | 371 | bool check() const | ||
363 | { | 372 | { | ||
364 | bool success = true; | 373 | bool success = m_success; | ||
365 | for (auto &language : m_contextMap) { | 374 | for (auto &language : m_contextMap) { | ||
366 | const auto invalidContextNames = language.usedContextNames - language.existingContextNames; | 375 | const auto invalidContextNames = language.usedContextNames - language.existingContextNames; | ||
367 | if (!invalidContextNames.isEmpty()) { | 376 | if (!invalidContextNames.isEmpty()) { | ||
368 | qWarning() << language.hlFilename << "Reference of non-existing contexts:" << invalidContextNames; | 377 | qWarning() << language.hlFilename << "Reference of non-existing contexts:" << invalidContextNames; | ||
369 | success = false; | 378 | success = false; | ||
370 | } | 379 | } | ||
371 | 380 | | |||
372 | const auto unusedNames = language.existingContextNames - language.usedContextNames; | 381 | const auto unusedNames = language.existingContextNames - language.usedContextNames; | ||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Line(s) | 432 | public: | |||
437 | QSet<QString> existingContextNames; | 446 | QSet<QString> existingContextNames; | ||
438 | }; | 447 | }; | ||
439 | 448 | | |||
440 | /** | 449 | /** | ||
441 | * "Language name" to "Language" map. | 450 | * "Language name" to "Language" map. | ||
442 | * Example key: "Doxygen" | 451 | * Example key: "Doxygen" | ||
443 | */ | 452 | */ | ||
444 | QHash<QString, Language> m_contextMap; | 453 | QHash<QString, Language> m_contextMap; | ||
454 | bool m_success = true; | ||||
445 | }; | 455 | }; | ||
446 | 456 | | |||
447 | /** | 457 | /** | ||
448 | * Helper class to search for non-existing itemDatas. | 458 | * Helper class to search for non-existing itemDatas. | ||
449 | */ | 459 | */ | ||
450 | class AttributeChecker | 460 | class AttributeChecker | ||
451 | { | 461 | { | ||
452 | public: | 462 | public: | ||
453 | AttributeChecker(const QString &filename) | 463 | AttributeChecker(const QString &filename) | ||
454 | : m_filename(filename) | 464 | : m_filename(filename) | ||
455 | {} | 465 | {} | ||
456 | 466 | | |||
457 | void processElement(QXmlStreamReader &xml) | 467 | void processElement(QXmlStreamReader &xml) | ||
458 | { | 468 | { | ||
459 | if (xml.name() == QLatin1String("itemData")) { | 469 | if (xml.name() == QLatin1String("itemData")) { | ||
460 | const QString name = xml.attributes().value(QLatin1String("name")).toString(); | 470 | const QString name = xml.attributes().value(QLatin1String("name")).toString(); | ||
461 | if (!name.isEmpty()) { | 471 | if (!name.isEmpty()) { | ||
462 | if (m_existingAttributeNames.contains(name)) { | 472 | if (m_existingAttributeNames.contains(name)) { | ||
463 | qWarning() << m_filename << "itemData duplicate:" << name; | 473 | qWarning() << m_filename << "itemData duplicate:" << name; | ||
474 | m_success = false; | ||||
464 | } else { | 475 | } else { | ||
465 | m_existingAttributeNames.insert(name); | 476 | m_existingAttributeNames.insert(name); | ||
466 | } | 477 | } | ||
467 | } | 478 | } | ||
468 | } else if (xml.attributes().hasAttribute(QLatin1String("attribute"))) { | 479 | } else if (xml.attributes().hasAttribute(QLatin1String("attribute"))) { | ||
469 | const QString name = xml.attributes().value(QLatin1String("attribute")).toString(); | 480 | const QString name = xml.attributes().value(QLatin1String("attribute")).toString(); | ||
470 | if (name.isEmpty()) { | 481 | if (name.isEmpty()) { | ||
471 | qWarning() << m_filename << "specified attribute is empty:" << xml.name(); | 482 | qWarning() << m_filename << "specified attribute is empty:" << xml.name(); | ||
483 | m_success = false; | ||||
472 | } else { | 484 | } else { | ||
473 | m_usedAttributeNames.insert(name); | 485 | m_usedAttributeNames.insert(name); | ||
474 | } | 486 | } | ||
475 | } | 487 | } | ||
476 | } | 488 | } | ||
477 | 489 | | |||
478 | bool check() const | 490 | bool check() const | ||
479 | { | 491 | { | ||
480 | bool success = true; | 492 | bool success = m_success; | ||
481 | const auto invalidNames = m_usedAttributeNames - m_existingAttributeNames; | 493 | const auto invalidNames = m_usedAttributeNames - m_existingAttributeNames; | ||
482 | if (!invalidNames.isEmpty()) { | 494 | if (!invalidNames.isEmpty()) { | ||
483 | qWarning() << m_filename << "Reference of non-existing itemData attributes:" << invalidNames; | 495 | qWarning() << m_filename << "Reference of non-existing itemData attributes:" << invalidNames; | ||
484 | success = false; | 496 | success = false; | ||
485 | } | 497 | } | ||
486 | 498 | | |||
487 | auto unusedNames = m_existingAttributeNames - m_usedAttributeNames; | 499 | auto unusedNames = m_existingAttributeNames - m_usedAttributeNames; | ||
488 | if (!unusedNames.isEmpty()) { | 500 | if (!unusedNames.isEmpty()) { | ||
489 | qWarning() << m_filename << "Unused itemData:" << unusedNames; | 501 | qWarning() << m_filename << "Unused itemData:" << unusedNames; | ||
502 | success = false; | ||||
490 | } | 503 | } | ||
491 | 504 | | |||
492 | return success; | 505 | return success; | ||
493 | } | 506 | } | ||
494 | 507 | | |||
495 | private: | 508 | private: | ||
496 | QString m_filename; | 509 | QString m_filename; | ||
497 | QSet<QString> m_usedAttributeNames; | 510 | QSet<QString> m_usedAttributeNames; | ||
498 | QSet<QString> m_existingAttributeNames; | 511 | QSet<QString> m_existingAttributeNames; | ||
512 | bool m_success = true; | ||||
499 | }; | 513 | }; | ||
500 | 514 | | |||
501 | } | 515 | } | ||
502 | 516 | | |||
503 | int main(int argc, char *argv[]) | 517 | int main(int argc, char *argv[]) | ||
504 | { | 518 | { | ||
505 | // get app instance | 519 | // get app instance | ||
506 | QCoreApplication app(argc, argv); | 520 | QCoreApplication app(argc, argv); | ||
▲ Show 20 Lines • Show All 167 Lines • Show Last 20 Lines |