Fix library data reflection (#3107)
This commit is contained in:
parent
0ecac8e23b
commit
7658aa86bd
|
@ -294,6 +294,33 @@ static CppcheckLibraryData::PlatformType loadPlatformType(QXmlStreamReader &xmlR
|
||||||
return platformType;
|
return platformType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CppcheckLibraryData::Reflection loadReflection(QXmlStreamReader &xmlReader)
|
||||||
|
{
|
||||||
|
CppcheckLibraryData::Reflection reflection;
|
||||||
|
|
||||||
|
QXmlStreamReader::TokenType type;
|
||||||
|
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
|
||||||
|
xmlReader.name().toString() != "reflection") {
|
||||||
|
if (type != QXmlStreamReader::StartElement)
|
||||||
|
continue;
|
||||||
|
const QString elementName = xmlReader.name().toString();
|
||||||
|
if (elementName == "call") {
|
||||||
|
CppcheckLibraryData::Reflection::Call call;
|
||||||
|
if (xmlReader.attributes().hasAttribute("arg")) {
|
||||||
|
call.arg = xmlReader.attributes().value("arg").toInt();
|
||||||
|
} else {
|
||||||
|
mandatoryAttibuteMissing(xmlReader, "arg");
|
||||||
|
}
|
||||||
|
call.name = xmlReader.readElementText();
|
||||||
|
reflection.calls.append(call);
|
||||||
|
} else {
|
||||||
|
unhandledElement(xmlReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflection;
|
||||||
|
}
|
||||||
|
|
||||||
QString CppcheckLibraryData::open(QIODevice &file)
|
QString CppcheckLibraryData::open(QIODevice &file)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
@ -330,6 +357,8 @@ QString CppcheckLibraryData::open(QIODevice &file)
|
||||||
typeChecks.append(loadTypeChecks(xmlReader));
|
typeChecks.append(loadTypeChecks(xmlReader));
|
||||||
else if (elementName == "platformtype")
|
else if (elementName == "platformtype")
|
||||||
platformTypes.append(loadPlatformType(xmlReader));
|
platformTypes.append(loadPlatformType(xmlReader));
|
||||||
|
else if (elementName == "reflection")
|
||||||
|
reflections.append(loadReflection(xmlReader));
|
||||||
else
|
else
|
||||||
unhandledElement(xmlReader);
|
unhandledElement(xmlReader);
|
||||||
} catch (std::runtime_error &e) {
|
} catch (std::runtime_error &e) {
|
||||||
|
@ -589,6 +618,18 @@ static void writePlatformType(QXmlStreamWriter &xmlWriter, const CppcheckLibrary
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void writeReflection (QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Reflection &refl)
|
||||||
|
{
|
||||||
|
xmlWriter.writeStartElement("reflection");
|
||||||
|
foreach (const CppcheckLibraryData::Reflection::Call &call, refl.calls) {
|
||||||
|
xmlWriter.writeStartElement("call");
|
||||||
|
xmlWriter.writeAttribute("arg", QString("%1").arg(call.arg));
|
||||||
|
xmlWriter.writeCharacters(call.name);
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
QString CppcheckLibraryData::toString() const
|
QString CppcheckLibraryData::toString() const
|
||||||
{
|
{
|
||||||
QString outputString;
|
QString outputString;
|
||||||
|
@ -650,6 +691,10 @@ QString CppcheckLibraryData::toString() const
|
||||||
writePlatformType(xmlWriter, pt);
|
writePlatformType(xmlWriter, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (const Reflection &refl, reflections) {
|
||||||
|
writeReflection(xmlWriter, refl);
|
||||||
|
}
|
||||||
|
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
|
|
||||||
return outputString;
|
return outputString;
|
||||||
|
|
|
@ -180,6 +180,19 @@ public:
|
||||||
|
|
||||||
using TypeChecks = QList<QPair<QString, QString>>;
|
using TypeChecks = QList<QPair<QString, QString>>;
|
||||||
|
|
||||||
|
struct Reflection {
|
||||||
|
struct Call {
|
||||||
|
Call() :
|
||||||
|
arg {-1} // -1: Mandatory "arg" attribute not available
|
||||||
|
{}
|
||||||
|
|
||||||
|
int arg;
|
||||||
|
QString name;
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<struct Call> calls;
|
||||||
|
};
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
containers.clear();
|
containers.clear();
|
||||||
defines.clear();
|
defines.clear();
|
||||||
|
@ -190,6 +203,7 @@ public:
|
||||||
smartPointers.clear();
|
smartPointers.clear();
|
||||||
typeChecks.clear();
|
typeChecks.clear();
|
||||||
platformTypes.clear();
|
platformTypes.clear();
|
||||||
|
reflections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(CppcheckLibraryData &other) {
|
void swap(CppcheckLibraryData &other) {
|
||||||
|
@ -202,6 +216,7 @@ public:
|
||||||
smartPointers.swap(other.smartPointers);
|
smartPointers.swap(other.smartPointers);
|
||||||
typeChecks.swap(other.typeChecks);
|
typeChecks.swap(other.typeChecks);
|
||||||
platformTypes.swap(other.platformTypes);
|
platformTypes.swap(other.platformTypes);
|
||||||
|
reflections.swap(other.reflections);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString open(QIODevice &file);
|
QString open(QIODevice &file);
|
||||||
|
@ -216,6 +231,7 @@ public:
|
||||||
QList<struct PlatformType> platformTypes;
|
QList<struct PlatformType> platformTypes;
|
||||||
QStringList undefines;
|
QStringList undefines;
|
||||||
QStringList smartPointers;
|
QStringList smartPointers;
|
||||||
|
QList<struct Reflection> reflections;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPPCHECKLIBRARYDATA_H
|
#endif // CPPCHECKLIBRARYDATA_H
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<container id="stdStack" startPattern="std :: stack <" inherits="stdContainer">
|
||||||
|
<!-- error: invalid element acess -->
|
||||||
|
<acess>
|
||||||
|
<function name="push" action="push"/>
|
||||||
|
<function name="pop" action="pop"/>
|
||||||
|
<function name="top" yields="item"/>
|
||||||
|
</access>
|
||||||
|
</container>
|
||||||
|
</def>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<define name="INT8_MIN" value="-128"/>
|
||||||
|
<define/>
|
||||||
|
</def>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<reflection>
|
||||||
|
<call>invokeMethod</call>
|
||||||
|
</reflection>
|
||||||
|
</def>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<reflection>
|
||||||
|
<!-- error: invalid element calls -->
|
||||||
|
<calls arg="2">invokeMethod</call>
|
||||||
|
</reflection>
|
||||||
|
</def>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<reflection>
|
||||||
|
<call arg="2">invokeMethod</call>
|
||||||
|
<call arg="1">callFunction</call>
|
||||||
|
</reflection>
|
||||||
|
<reflection/>
|
||||||
|
</def>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<undefine name="INT8_MIN"/>
|
||||||
|
<undefine/>
|
||||||
|
</def>
|
|
@ -10,5 +10,11 @@
|
||||||
<file>files/platform_type_unhandled_element.cfg</file>
|
<file>files/platform_type_unhandled_element.cfg</file>
|
||||||
<file>files/memory_resource_unhandled_element.cfg</file>
|
<file>files/memory_resource_unhandled_element.cfg</file>
|
||||||
<file>files/memory_resource_valid.cfg</file>
|
<file>files/memory_resource_valid.cfg</file>
|
||||||
|
<file>files/define_valid.cfg</file>
|
||||||
|
<file>files/undefine_valid.cfg</file>
|
||||||
|
<file>files/container_unhandled_element.cfg</file>
|
||||||
|
<file>files/reflection_unhandled_element.cfg</file>
|
||||||
|
<file>files/reflection_valid.cfg</file>
|
||||||
|
<file>files/reflection_mandatory_attribute_missing.cfg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -47,6 +47,14 @@ void TestCppcheckLibraryData::unhandledElement()
|
||||||
loadCfgFile(":/files/memory_resource_unhandled_element.cfg", fileLibraryData, result);
|
loadCfgFile(":/files/memory_resource_unhandled_element.cfg", fileLibraryData, result);
|
||||||
QCOMPARE(result.isNull(), false);
|
QCOMPARE(result.isNull(), false);
|
||||||
qDebug() << result;
|
qDebug() << result;
|
||||||
|
|
||||||
|
loadCfgFile(":/files/container_unhandled_element.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), false);
|
||||||
|
qDebug() << result;
|
||||||
|
|
||||||
|
loadCfgFile(":/files/reflection_unhandled_element.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), false);
|
||||||
|
qDebug() << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCppcheckLibraryData::mandatoryAttributeMissing()
|
void TestCppcheckLibraryData::mandatoryAttributeMissing()
|
||||||
|
@ -54,6 +62,10 @@ void TestCppcheckLibraryData::mandatoryAttributeMissing()
|
||||||
loadCfgFile(":/files/mandatory_attribute_missing.cfg", fileLibraryData, result);
|
loadCfgFile(":/files/mandatory_attribute_missing.cfg", fileLibraryData, result);
|
||||||
QCOMPARE(result.isNull(), false);
|
QCOMPARE(result.isNull(), false);
|
||||||
qDebug() << result;
|
qDebug() << result;
|
||||||
|
|
||||||
|
loadCfgFile(":/files/reflection_mandatory_attribute_missing.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), false);
|
||||||
|
qDebug() << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCppcheckLibraryData::podtypeValid()
|
void TestCppcheckLibraryData::podtypeValid()
|
||||||
|
@ -337,6 +349,114 @@ void TestCppcheckLibraryData::memoryResourceValid()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestCppcheckLibraryData::defineValid()
|
||||||
|
{
|
||||||
|
// Load library data from file
|
||||||
|
loadCfgFile(":/files/define_valid.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Swap libray data read from file to other object
|
||||||
|
libraryData.swap(fileLibraryData);
|
||||||
|
|
||||||
|
// Do size and content checks against swapped data.
|
||||||
|
QCOMPARE(libraryData.defines.size(), 2);
|
||||||
|
QCOMPARE(libraryData.defines[0].name, "INT8_MIN");
|
||||||
|
QCOMPARE(libraryData.defines[0].value, "-128");
|
||||||
|
QCOMPARE(libraryData.defines[1].name.isEmpty(), true);
|
||||||
|
QCOMPARE(libraryData.defines[1].value.isEmpty(), true);
|
||||||
|
|
||||||
|
// Save library data to file
|
||||||
|
saveCfgFile(TempCfgFile, libraryData);
|
||||||
|
|
||||||
|
fileLibraryData.clear();
|
||||||
|
QCOMPARE(fileLibraryData.defines.size(), 0);
|
||||||
|
|
||||||
|
// Reload library data from file
|
||||||
|
loadCfgFile(TempCfgFile, fileLibraryData, result, true);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Verify no data got lost or modified
|
||||||
|
QCOMPARE(libraryData.defines.size(), fileLibraryData.defines.size());
|
||||||
|
QCOMPARE(libraryData.defines.size(), 2);
|
||||||
|
for (int idx=0; idx < libraryData.defines.size(); idx++) {
|
||||||
|
QCOMPARE(libraryData.defines[idx].name, fileLibraryData.defines[idx].name);
|
||||||
|
QCOMPARE(libraryData.defines[idx].value, fileLibraryData.defines[idx].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCppcheckLibraryData::undefineValid()
|
||||||
|
{
|
||||||
|
// Load library data from file
|
||||||
|
loadCfgFile(":/files/undefine_valid.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Swap libray data read from file to other object
|
||||||
|
libraryData.swap(fileLibraryData);
|
||||||
|
|
||||||
|
// Do size and content checks against swapped data.
|
||||||
|
QCOMPARE(libraryData.undefines.size(), 2);
|
||||||
|
QCOMPARE(libraryData.undefines[0], "INT8_MIN");
|
||||||
|
QCOMPARE(libraryData.undefines[1].isEmpty(), true);
|
||||||
|
|
||||||
|
// Save library data to file
|
||||||
|
saveCfgFile(TempCfgFile, libraryData);
|
||||||
|
|
||||||
|
fileLibraryData.clear();
|
||||||
|
QCOMPARE(fileLibraryData.undefines.size(), 0);
|
||||||
|
|
||||||
|
// Reload library data from file
|
||||||
|
loadCfgFile(TempCfgFile, fileLibraryData, result, true);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Verify no data got lost or modified
|
||||||
|
QCOMPARE(libraryData.undefines.size(), fileLibraryData.undefines.size());
|
||||||
|
QCOMPARE(libraryData.undefines.size(), 2);
|
||||||
|
QCOMPARE(libraryData.undefines, fileLibraryData.undefines);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCppcheckLibraryData::reflectionValid()
|
||||||
|
{
|
||||||
|
// Load library data from file
|
||||||
|
loadCfgFile(":/files/reflection_valid.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Swap libray data read from file to other object
|
||||||
|
libraryData.swap(fileLibraryData);
|
||||||
|
|
||||||
|
// Do size and content checks against swapped data.
|
||||||
|
QCOMPARE(libraryData.reflections.size(), 2);
|
||||||
|
QCOMPARE(libraryData.reflections[0].calls.size(), 2);
|
||||||
|
QCOMPARE(libraryData.reflections[0].calls[0].arg, 2);
|
||||||
|
QCOMPARE(libraryData.reflections[0].calls[0].name, "invokeMethod");
|
||||||
|
QCOMPARE(libraryData.reflections[0].calls[1].arg, 1);
|
||||||
|
QCOMPARE(libraryData.reflections[0].calls[1].name, "callFunction");
|
||||||
|
QCOMPARE(libraryData.reflections[1].calls.isEmpty(), true);
|
||||||
|
|
||||||
|
// Save library data to file
|
||||||
|
saveCfgFile(TempCfgFile, libraryData);
|
||||||
|
|
||||||
|
fileLibraryData.clear();
|
||||||
|
QCOMPARE(fileLibraryData.reflections.size(), 0);
|
||||||
|
|
||||||
|
// Reload library data from file
|
||||||
|
loadCfgFile(TempCfgFile, fileLibraryData, result, true);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Verify no data got lost or modified
|
||||||
|
QCOMPARE(libraryData.reflections.size(), fileLibraryData.reflections.size());
|
||||||
|
QCOMPARE(libraryData.reflections.size(), 2);
|
||||||
|
for (int idx=0; idx < libraryData.reflections.size(); idx++) {
|
||||||
|
CppcheckLibraryData::Reflection lhs = libraryData.reflections[idx];
|
||||||
|
CppcheckLibraryData::Reflection rhs = fileLibraryData.reflections[idx];
|
||||||
|
|
||||||
|
QCOMPARE(lhs.calls.size(), rhs.calls.size());
|
||||||
|
for (int num=0; num < lhs.calls.size(); num++) {
|
||||||
|
QCOMPARE(lhs.calls[num].arg, rhs.calls[num].arg);
|
||||||
|
QCOMPARE(lhs.calls[num].name, rhs.calls[num].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TestCppcheckLibraryData::loadCfgFile(QString filename, CppcheckLibraryData &data, QString &result, bool removeFile)
|
void TestCppcheckLibraryData::loadCfgFile(QString filename, CppcheckLibraryData &data, QString &result, bool removeFile)
|
||||||
{
|
{
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
|
|
|
@ -34,6 +34,9 @@ private slots:
|
||||||
void smartPointerValid();
|
void smartPointerValid();
|
||||||
void platformTypeValid();
|
void platformTypeValid();
|
||||||
void memoryResourceValid();
|
void memoryResourceValid();
|
||||||
|
void defineValid();
|
||||||
|
void undefineValid();
|
||||||
|
void reflectionValid();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &result, bool removeFile = false);
|
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &result, bool removeFile = false);
|
||||||
|
|
Loading…
Reference in New Issue