Skip to content

Commit 25fa7c5

Browse files
authored
Fix library data markup (danmar#3118)
1 parent f48e195 commit 25fa7c5

8 files changed

Lines changed: 365 additions & 0 deletions

gui/cppchecklibrarydata.cpp

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include <QXmlStreamReader>
2424
#include <QXmlStreamWriter>
25+
#include <QVariant>
2526

2627
const unsigned int CppcheckLibraryData::Function::Arg::ANY = ~0U;
2728
const unsigned int CppcheckLibraryData::Function::Arg::VARIADIC = ~1U;
@@ -321,6 +322,108 @@ static CppcheckLibraryData::Reflection loadReflection(QXmlStreamReader &xmlReade
321322
return reflection;
322323
}
323324

325+
static CppcheckLibraryData::Markup loadMarkup(QXmlStreamReader &xmlReader)
326+
{
327+
CppcheckLibraryData::Markup markup;
328+
329+
QXmlStreamReader::TokenType type;
330+
if (xmlReader.attributes().hasAttribute("ext")) {
331+
markup.ext = xmlReader.attributes().value("ext").toString();
332+
}
333+
else {
334+
mandatoryAttibuteMissing(xmlReader, "ext");
335+
}
336+
if (xmlReader.attributes().hasAttribute("aftercode")) {
337+
markup.afterCode = (xmlReader.attributes().value("aftercode") == "true") ? true : false;
338+
}
339+
else {
340+
mandatoryAttibuteMissing(xmlReader, "aftercode");
341+
}
342+
if (xmlReader.attributes().hasAttribute("reporterrors")) {
343+
markup.reportErrors = (xmlReader.attributes().value("reporterrors") == "true") ? true : false;
344+
}
345+
else {
346+
mandatoryAttibuteMissing(xmlReader, "reporterrors");
347+
}
348+
349+
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
350+
xmlReader.name().toString() != "markup") {
351+
if (type != QXmlStreamReader::StartElement)
352+
continue;
353+
const QString elementName = xmlReader.name().toString();
354+
if (elementName == "keywords") {
355+
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
356+
xmlReader.name().toString() != "keywords") {
357+
if (type != QXmlStreamReader::StartElement)
358+
continue;
359+
if (xmlReader.name().toString() == "keyword") {
360+
markup.keywords.append(xmlReader.attributes().value("name").toString());
361+
}
362+
else {
363+
unhandledElement(xmlReader);
364+
}
365+
}
366+
} else if (elementName == "codeblocks") {
367+
CppcheckLibraryData::Markup::CodeBlocks codeBlock;
368+
369+
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
370+
xmlReader.name().toString() != "codeblocks") {
371+
if (type != QXmlStreamReader::StartElement)
372+
continue;
373+
if (xmlReader.name().toString() == "block") {
374+
codeBlock.blocks.append(xmlReader.attributes().value("name").toString());
375+
}
376+
else if (xmlReader.name().toString() == "structure") {
377+
codeBlock.offset = xmlReader.attributes().value("offset").toInt();
378+
codeBlock.start = xmlReader.attributes().value("start").toString();
379+
codeBlock.end = xmlReader.attributes().value("end").toString();
380+
}
381+
else {
382+
unhandledElement(xmlReader);
383+
}
384+
}
385+
markup.codeBlocks.append(codeBlock);
386+
} else if (elementName == "exported") {
387+
CppcheckLibraryData::Markup::Exporter exporter;
388+
389+
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
390+
xmlReader.name().toString() != "exported") {
391+
if (type != QXmlStreamReader::StartElement)
392+
continue;
393+
if (xmlReader.name().toString() == "exporter") {
394+
exporter.prefix = xmlReader.attributes().value("prefix").toString();
395+
}
396+
else if (xmlReader.name().toString() == "prefix") {
397+
exporter.prefixList.append(xmlReader.readElementText());
398+
}
399+
else if (xmlReader.name().toString() == "suffix") {
400+
exporter.suffixList.append(xmlReader.readElementText());
401+
}
402+
else {
403+
unhandledElement(xmlReader);
404+
}
405+
}
406+
markup.exporter.append(exporter);
407+
} else if (elementName == "imported") {
408+
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
409+
xmlReader.name().toString() != "imported") {
410+
if (type != QXmlStreamReader::StartElement)
411+
continue;
412+
if (xmlReader.name().toString() == "importer") {
413+
markup.importer.append(xmlReader.readElementText());
414+
}
415+
else {
416+
unhandledElement(xmlReader);
417+
}
418+
}
419+
} else {
420+
unhandledElement(xmlReader);
421+
}
422+
}
423+
424+
return markup;
425+
}
426+
324427
QString CppcheckLibraryData::open(QIODevice &file)
325428
{
326429
clear();
@@ -359,6 +462,8 @@ QString CppcheckLibraryData::open(QIODevice &file)
359462
platformTypes.append(loadPlatformType(xmlReader));
360463
else if (elementName == "reflection")
361464
reflections.append(loadReflection(xmlReader));
465+
else if (elementName == "markup")
466+
markups.append(loadMarkup(xmlReader));
362467
else
363468
unhandledElement(xmlReader);
364469
} catch (std::runtime_error &e) {
@@ -630,6 +735,68 @@ static void writeReflection(QXmlStreamWriter &xmlWriter, const CppcheckLibraryDa
630735
xmlWriter.writeEndElement();
631736
}
632737

738+
static void writeMarkup(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Markup &mup)
739+
{
740+
xmlWriter.writeStartElement("markup");
741+
xmlWriter.writeAttribute("ext", mup.ext);
742+
xmlWriter.writeAttribute("aftercode", QVariant(mup.afterCode).toString());
743+
xmlWriter.writeAttribute("reporterrors", QVariant(mup.reportErrors).toString());
744+
if (!mup.keywords.isEmpty()) {
745+
xmlWriter.writeStartElement("keywords");
746+
foreach (const QString &keyword, mup.keywords) {
747+
xmlWriter.writeStartElement("keyword");
748+
xmlWriter.writeAttribute("name", keyword);
749+
xmlWriter.writeEndElement();
750+
}
751+
xmlWriter.writeEndElement();
752+
}
753+
if (!mup.importer.isEmpty()) {
754+
xmlWriter.writeStartElement("imported");
755+
foreach (const QString &import, mup.importer) {
756+
xmlWriter.writeStartElement("importer");
757+
xmlWriter.writeCharacters(import);
758+
xmlWriter.writeEndElement();
759+
}
760+
xmlWriter.writeEndElement();
761+
}
762+
if (!mup.exporter.isEmpty()) {
763+
xmlWriter.writeStartElement("exported");
764+
foreach (const CppcheckLibraryData::Markup::Exporter exporter, mup.exporter) {
765+
xmlWriter.writeStartElement("exporter");
766+
xmlWriter.writeAttribute("prefix", exporter.prefix);
767+
foreach (const QString &prefix, exporter.prefixList) {
768+
xmlWriter.writeStartElement("prefix");
769+
xmlWriter.writeCharacters(prefix);
770+
xmlWriter.writeEndElement();
771+
}
772+
foreach (const QString &suffix, exporter.suffixList) {
773+
xmlWriter.writeStartElement("suffix");
774+
xmlWriter.writeCharacters(suffix);
775+
xmlWriter.writeEndElement();
776+
}
777+
xmlWriter.writeEndElement();
778+
}
779+
xmlWriter.writeEndElement();
780+
}
781+
if (!mup.codeBlocks.isEmpty()) {
782+
foreach (const CppcheckLibraryData::Markup::CodeBlocks codeblock, mup.codeBlocks) {
783+
xmlWriter.writeStartElement("codeblocks");
784+
foreach (const QString &block, codeblock.blocks) {
785+
xmlWriter.writeStartElement("block");
786+
xmlWriter.writeAttribute("name", block);
787+
xmlWriter.writeEndElement();
788+
}
789+
xmlWriter.writeStartElement("structure");
790+
xmlWriter.writeAttribute("offset", QString("%1").arg(codeblock.offset));
791+
xmlWriter.writeAttribute("start", codeblock.start);
792+
xmlWriter.writeAttribute("end", codeblock.end);
793+
xmlWriter.writeEndElement();
794+
xmlWriter.writeEndElement();
795+
}
796+
}
797+
xmlWriter.writeEndElement();
798+
}
799+
633800
QString CppcheckLibraryData::toString() const
634801
{
635802
QString outputString;
@@ -695,6 +862,10 @@ QString CppcheckLibraryData::toString() const
695862
writeReflection(xmlWriter, refl);
696863
}
697864

865+
foreach (const Markup &mup, markups) {
866+
writeMarkup(xmlWriter, mup);
867+
}
868+
698869
xmlWriter.writeEndElement();
699870

700871
return outputString;

gui/cppchecklibrarydata.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,33 @@ class CppcheckLibraryData {
193193
QList<struct Call> calls;
194194
};
195195

196+
struct Markup {
197+
struct CodeBlocks {
198+
CodeBlocks() :
199+
offset {-1}
200+
{}
201+
202+
QStringList blocks;
203+
int offset;
204+
QString start;
205+
QString end;
206+
};
207+
208+
struct Exporter {
209+
QString prefix;
210+
QStringList prefixList;
211+
QStringList suffixList;
212+
};
213+
214+
QString ext;
215+
bool afterCode;
216+
bool reportErrors;
217+
QStringList keywords;
218+
QStringList importer;
219+
QList<CodeBlocks> codeBlocks;
220+
QList<Exporter> exporter;
221+
};
222+
196223
void clear() {
197224
containers.clear();
198225
defines.clear();
@@ -204,6 +231,7 @@ class CppcheckLibraryData {
204231
typeChecks.clear();
205232
platformTypes.clear();
206233
reflections.clear();
234+
markups.clear();
207235
}
208236

209237
void swap(CppcheckLibraryData &other) {
@@ -217,6 +245,7 @@ class CppcheckLibraryData {
217245
typeChecks.swap(other.typeChecks);
218246
platformTypes.swap(other.platformTypes);
219247
reflections.swap(other.reflections);
248+
markups.swap(other.markups);
220249
}
221250

222251
QString open(QIODevice &file);
@@ -232,6 +261,7 @@ class CppcheckLibraryData {
232261
QStringList undefines;
233262
QStringList smartPointers;
234263
QList<struct Reflection> reflections;
264+
QList<struct Markup> markups;
235265
};
236266

237267
#endif // CPPCHECKLIBRARYDATA_H
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0"?>
2+
<def format="2">
3+
<!-- error: invalid attribute reporterror -->
4+
<markup ext=".qml" reporterror="false" aftercode="true">
5+
</markup>
6+
</def>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0"?>
2+
<def format="2">
3+
<!-- Test data from qt.cfg -->
4+
<markup ext=".qml" reporterrors="false" aftercode="true">
5+
<keywords>
6+
<keyword name="if"/>
7+
<keyword name="while"/>
8+
<keyword name="typeof"/>
9+
<keyword name="for"/>
10+
</keywords>
11+
<codeblocks>
12+
<block name="onClicked"/>
13+
<block name="onFinished"/>
14+
<block name="onTriggered"/>
15+
<block name="onPressed"/>
16+
<block name="onTouch"/>
17+
<structure offset="3" start="{" end="}"/>
18+
</codeblocks>
19+
<codeblocks>
20+
<block name="function"/>
21+
<structure offset="2" start="{" end="}"/>
22+
</codeblocks>
23+
<!-- error: invalid element export -->
24+
<export>
25+
<exporter prefix="Q_PROPERTY">
26+
<suffix>READ</suffix>
27+
<prefix>READ</prefix>
28+
<prefix>WRITE</prefix>
29+
<prefix>NOTIFY</prefix>
30+
</exporter>
31+
</export>
32+
<imported>
33+
<importer>connect</importer>
34+
</imported>
35+
</markup>
36+
</def>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0"?>
2+
<def format="2">
3+
<!-- Test data from qt.cfg -->
4+
<markup ext=".qml" reporterrors="false" aftercode="true">
5+
<keywords>
6+
<keyword name="if"/>
7+
<keyword name="while"/>
8+
<keyword name="typeof"/>
9+
<keyword name="for"/>
10+
</keywords>
11+
<codeblocks>
12+
<block name="onClicked"/>
13+
<block name="onFinished"/>
14+
<block name="onTriggered"/>
15+
<block name="onPressed"/>
16+
<block name="onTouch"/>
17+
<structure offset="3" start="{" end="}"/>
18+
</codeblocks>
19+
<codeblocks>
20+
<block name="function"/>
21+
<structure offset="2" start="{" end="}"/>
22+
</codeblocks>
23+
<exported>
24+
<exporter prefix="Q_PROPERTY">
25+
<suffix>READ</suffix>
26+
<prefix>READ</prefix>
27+
<prefix>WRITE</prefix>
28+
<prefix>NOTIFY</prefix>
29+
</exporter>
30+
</exported>
31+
<imported>
32+
<importer>connect</importer>
33+
</imported>
34+
</markup>
35+
</def>

gui/test/cppchecklibrarydata/resources.qrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,8 @@
1616
<file>files/reflection_unhandled_element.cfg</file>
1717
<file>files/reflection_valid.cfg</file>
1818
<file>files/reflection_mandatory_attribute_missing.cfg</file>
19+
<file>files/markup_mandatory_attribute_missing.cfg</file>
20+
<file>files/markup_valid.cfg</file>
21+
<file>files/markup_unhandled_element.cfg</file>
1922
</qresource>
2023
</RCC>

0 commit comments

Comments
 (0)