Library Data: Add support for optional smart pointer element 'unique' (#4132)
This commit is contained in:
parent
22aeeb1788
commit
c897c0474b
|
@ -61,7 +61,7 @@ static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
|
||||||
if (elementName == "type") {
|
if (elementName == "type") {
|
||||||
container.type.templateParameter = xmlReader.attributes().value("templateParameter").toString();
|
container.type.templateParameter = xmlReader.attributes().value("templateParameter").toString();
|
||||||
container.type.string = xmlReader.attributes().value("string").toString();
|
container.type.string = xmlReader.attributes().value("string").toString();
|
||||||
} else if (elementName == "size" || elementName == "access" || elementName == "other") {
|
} else if (elementName == "size" || elementName == "access" || elementName == "other" || elementName == "rangeItemRecordType") {
|
||||||
const QString indexOperator = xmlReader.attributes().value("indexOperator").toString();
|
const QString indexOperator = xmlReader.attributes().value("indexOperator").toString();
|
||||||
if (elementName == "access" && indexOperator == "array-like")
|
if (elementName == "access" && indexOperator == "array-like")
|
||||||
container.access_arrayLike = true;
|
container.access_arrayLike = true;
|
||||||
|
@ -82,7 +82,12 @@ static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
|
||||||
container.sizeFunctions.append(function);
|
container.sizeFunctions.append(function);
|
||||||
else if (elementName == "access")
|
else if (elementName == "access")
|
||||||
container.accessFunctions.append(function);
|
container.accessFunctions.append(function);
|
||||||
else
|
else if (elementName == "rangeItemRecordType") {
|
||||||
|
struct CppcheckLibraryData::Container::RangeItemRecordType rangeItemRecordType;
|
||||||
|
rangeItemRecordType.name = xmlReader.attributes().value("name").toString();
|
||||||
|
rangeItemRecordType.templateParameter = xmlReader.attributes().value("templateParameter").toString();
|
||||||
|
container.rangeItemRecordTypeList.append(rangeItemRecordType);
|
||||||
|
} else
|
||||||
container.otherFunctions.append(function);
|
container.otherFunctions.append(function);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,9 +110,23 @@ static QString loadUndefine(const QXmlStreamReader &xmlReader)
|
||||||
return xmlReader.attributes().value("name").toString();
|
return xmlReader.attributes().value("name").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString loadSmartPointer(const QXmlStreamReader &xmlReader)
|
static CppcheckLibraryData::SmartPointer loadSmartPointer(QXmlStreamReader &xmlReader)
|
||||||
{
|
{
|
||||||
return xmlReader.attributes().value("class-name").toString();
|
CppcheckLibraryData::SmartPointer smartPointer;
|
||||||
|
smartPointer.name = xmlReader.attributes().value("class-name").toString();
|
||||||
|
QXmlStreamReader::TokenType type;
|
||||||
|
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
|
||||||
|
xmlReader.name().toString() != "smart-pointer") {
|
||||||
|
if (type != QXmlStreamReader::StartElement)
|
||||||
|
continue;
|
||||||
|
const QString elementName = xmlReader.name().toString();
|
||||||
|
if (elementName == "unique") {
|
||||||
|
smartPointer.unique = true;
|
||||||
|
} else {
|
||||||
|
unhandledElement(xmlReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return smartPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CppcheckLibraryData::TypeChecks loadTypeChecks(QXmlStreamReader &xmlReader)
|
static CppcheckLibraryData::TypeChecks loadTypeChecks(QXmlStreamReader &xmlReader)
|
||||||
|
@ -210,6 +229,20 @@ static CppcheckLibraryData::Function loadFunction(QXmlStreamReader &xmlReader, c
|
||||||
function.warn.reason = xmlReader.attributes().value("reason").toString();
|
function.warn.reason = xmlReader.attributes().value("reason").toString();
|
||||||
function.warn.alternatives = xmlReader.attributes().value("alternatives").toString();
|
function.warn.alternatives = xmlReader.attributes().value("alternatives").toString();
|
||||||
function.warn.msg = xmlReader.readElementText();
|
function.warn.msg = xmlReader.readElementText();
|
||||||
|
} else if (elementName == "not-overlapping-data") {
|
||||||
|
const QStringList attributeList {"ptr1-arg", "ptr2-arg", "size-arg", "strlen-arg"};
|
||||||
|
for (const QString &attr : attributeList) {
|
||||||
|
if (xmlReader.attributes().hasAttribute(attr)) {
|
||||||
|
function.notOverlappingDataArgs[attr] = xmlReader.attributes().value(attr).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (elementName == "container") {
|
||||||
|
const QStringList attributeList {"action", "yields"};
|
||||||
|
for (const QString &attr : attributeList) {
|
||||||
|
if (xmlReader.attributes().hasAttribute(attr)) {
|
||||||
|
function.containerAttributes[attr] = xmlReader.attributes().value(attr).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unhandledElement(xmlReader);
|
unhandledElement(xmlReader);
|
||||||
}
|
}
|
||||||
|
@ -493,6 +526,20 @@ static void writeContainerFunctions(QXmlStreamWriter &xmlWriter, const QString &
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void writeContainerRangeItemRecords(QXmlStreamWriter &xmlWriter, const QList<struct CppcheckLibraryData::Container::RangeItemRecordType> &rangeItemRecords)
|
||||||
|
{
|
||||||
|
if (rangeItemRecords.isEmpty())
|
||||||
|
return;
|
||||||
|
xmlWriter.writeStartElement("rangeItemRecordType");
|
||||||
|
for (const CppcheckLibraryData::Container::RangeItemRecordType &item : rangeItemRecords) {
|
||||||
|
xmlWriter.writeStartElement("member");
|
||||||
|
xmlWriter.writeAttribute("name", item.name);
|
||||||
|
xmlWriter.writeAttribute("templateParameter", item.templateParameter);
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Container &container)
|
static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Container &container)
|
||||||
{
|
{
|
||||||
xmlWriter.writeStartElement("container");
|
xmlWriter.writeStartElement("container");
|
||||||
|
@ -519,6 +566,7 @@ static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryDat
|
||||||
writeContainerFunctions(xmlWriter, "size", container.size_templateParameter, container.sizeFunctions);
|
writeContainerFunctions(xmlWriter, "size", container.size_templateParameter, container.sizeFunctions);
|
||||||
writeContainerFunctions(xmlWriter, "access", container.access_arrayLike?1:-1, container.accessFunctions);
|
writeContainerFunctions(xmlWriter, "access", container.access_arrayLike?1:-1, container.accessFunctions);
|
||||||
writeContainerFunctions(xmlWriter, "other", -1, container.otherFunctions);
|
writeContainerFunctions(xmlWriter, "other", -1, container.otherFunctions);
|
||||||
|
writeContainerRangeItemRecords(xmlWriter, container.rangeItemRecordTypeList);
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,7 +680,20 @@ static void writeFunction(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData
|
||||||
|
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
if (!function.notOverlappingDataArgs.isEmpty()) {
|
||||||
|
xmlWriter.writeStartElement("not-overlapping-data");
|
||||||
|
foreach (const QString value, function.notOverlappingDataArgs) {
|
||||||
|
xmlWriter.writeAttribute(function.notOverlappingDataArgs.key(value), value);
|
||||||
|
}
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
if (!function.containerAttributes.isEmpty()) {
|
||||||
|
xmlWriter.writeStartElement("container");
|
||||||
|
foreach (const QString value, function.containerAttributes) {
|
||||||
|
xmlWriter.writeAttribute(function.containerAttributes.key(value), value);
|
||||||
|
}
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
}
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -835,9 +896,12 @@ QString CppcheckLibraryData::toString() const
|
||||||
writeTypeChecks(xmlWriter, check);
|
writeTypeChecks(xmlWriter, check);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString &smartPtr : smartPointers) {
|
for (const SmartPointer &smartPtr : smartPointers) {
|
||||||
xmlWriter.writeStartElement("smart-pointer");
|
xmlWriter.writeStartElement("smart-pointer");
|
||||||
xmlWriter.writeAttribute("class-name", smartPtr);
|
xmlWriter.writeAttribute("class-name", smartPtr.name);
|
||||||
|
if (smartPtr.unique) {
|
||||||
|
xmlWriter.writeEmptyElement("unique");
|
||||||
|
}
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
|
|
||||||
|
@ -47,6 +48,11 @@ public:
|
||||||
QString string;
|
QString string;
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
|
struct RangeItemRecordType {
|
||||||
|
QString name;
|
||||||
|
QString templateParameter;
|
||||||
|
};
|
||||||
|
|
||||||
struct Function {
|
struct Function {
|
||||||
QString name;
|
QString name;
|
||||||
QString yields;
|
QString yields;
|
||||||
|
@ -55,6 +61,7 @@ public:
|
||||||
QList<struct Function> accessFunctions;
|
QList<struct Function> accessFunctions;
|
||||||
QList<struct Function> otherFunctions;
|
QList<struct Function> otherFunctions;
|
||||||
QList<struct Function> sizeFunctions;
|
QList<struct Function> sizeFunctions;
|
||||||
|
QList<struct RangeItemRecordType> rangeItemRecordTypeList;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Define {
|
struct Define {
|
||||||
|
@ -130,6 +137,9 @@ public:
|
||||||
msg.isEmpty();
|
msg.isEmpty();
|
||||||
}
|
}
|
||||||
} warn;
|
} warn;
|
||||||
|
|
||||||
|
QMap<QString, QString> notOverlappingDataArgs;
|
||||||
|
QMap<QString, QString> containerAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemoryResource {
|
struct MemoryResource {
|
||||||
|
@ -219,6 +229,15 @@ public:
|
||||||
QList<Exporter> exporter;
|
QList<Exporter> exporter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SmartPointer {
|
||||||
|
SmartPointer() :
|
||||||
|
unique {false}
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
bool unique;
|
||||||
|
};
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
containers.clear();
|
containers.clear();
|
||||||
defines.clear();
|
defines.clear();
|
||||||
|
@ -258,7 +277,7 @@ public:
|
||||||
QList<TypeChecks> typeChecks;
|
QList<TypeChecks> typeChecks;
|
||||||
QList<struct PlatformType> platformTypes;
|
QList<struct PlatformType> platformTypes;
|
||||||
QStringList undefines;
|
QStringList undefines;
|
||||||
QStringList smartPointers;
|
QList<struct SmartPointer> smartPointers;
|
||||||
QList<struct Reflection> reflections;
|
QList<struct Reflection> reflections;
|
||||||
QList<struct Markup> markups;
|
QList<struct Markup> markups;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<def format="2">
|
||||||
|
<container id="stdMultiMap">
|
||||||
|
<rangeItemRecordType>
|
||||||
|
<member name="first" templateParameter="0"/>
|
||||||
|
<member name="second" templateParameter="1"/>
|
||||||
|
</rangeItemRecordType>
|
||||||
|
</container>
|
||||||
|
</def>
|
|
@ -1,6 +1,8 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<def format="2">
|
<def format="2">
|
||||||
<smart-pointer class-name="wxObjectDataPtr"/>
|
<smart-pointer class-name="wxObjectDataPtr"/>
|
||||||
<smart-pointer class-name="wxScopedArray"/>
|
<smart-pointer class-name="wxScopedArray">
|
||||||
|
<unique/>
|
||||||
|
</smart-pointer>
|
||||||
<smart-pointer class-name="wxScopedPtr"/>
|
<smart-pointer class-name="wxScopedPtr"/>
|
||||||
</def>
|
</def>
|
|
@ -19,5 +19,6 @@
|
||||||
<file>files/markup_mandatory_attribute_missing.cfg</file>
|
<file>files/markup_mandatory_attribute_missing.cfg</file>
|
||||||
<file>files/markup_valid.cfg</file>
|
<file>files/markup_valid.cfg</file>
|
||||||
<file>files/markup_unhandled_element.cfg</file>
|
<file>files/markup_unhandled_element.cfg</file>
|
||||||
|
<file>files/container_valid.cfg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -182,9 +182,12 @@ void TestCppcheckLibraryData::smartPointerValid()
|
||||||
// Do size and content checks against swapped data.
|
// Do size and content checks against swapped data.
|
||||||
QCOMPARE(libraryData.smartPointers.size(), 3);
|
QCOMPARE(libraryData.smartPointers.size(), 3);
|
||||||
|
|
||||||
QCOMPARE(libraryData.smartPointers[0], QString("wxObjectDataPtr"));
|
QCOMPARE(libraryData.smartPointers[0].name, QString("wxObjectDataPtr"));
|
||||||
QCOMPARE(libraryData.smartPointers[1], QString("wxScopedArray"));
|
QCOMPARE(libraryData.smartPointers[0].unique, false);
|
||||||
QCOMPARE(libraryData.smartPointers[2], QString("wxScopedPtr"));
|
QCOMPARE(libraryData.smartPointers[1].name, QString("wxScopedArray"));
|
||||||
|
QCOMPARE(libraryData.smartPointers[1].unique, true);
|
||||||
|
QCOMPARE(libraryData.smartPointers[2].name, QString("wxScopedPtr"));
|
||||||
|
QCOMPARE(libraryData.smartPointers[2].unique, false);
|
||||||
|
|
||||||
// Save library data to file
|
// Save library data to file
|
||||||
saveCfgFile(TempCfgFile, libraryData);
|
saveCfgFile(TempCfgFile, libraryData);
|
||||||
|
@ -199,7 +202,10 @@ void TestCppcheckLibraryData::smartPointerValid()
|
||||||
// Verify no data got lost or modified
|
// Verify no data got lost or modified
|
||||||
QCOMPARE(libraryData.smartPointers.size(), fileLibraryData.smartPointers.size());
|
QCOMPARE(libraryData.smartPointers.size(), fileLibraryData.smartPointers.size());
|
||||||
QCOMPARE(libraryData.smartPointers.size(), 3);
|
QCOMPARE(libraryData.smartPointers.size(), 3);
|
||||||
QCOMPARE(libraryData.smartPointers, fileLibraryData.smartPointers);
|
for (int idx=0; idx < libraryData.smartPointers.size(); idx++) {
|
||||||
|
QCOMPARE(libraryData.smartPointers[idx].name, fileLibraryData.smartPointers[idx].name);
|
||||||
|
QCOMPARE(libraryData.smartPointers[idx].unique, fileLibraryData.smartPointers[idx].unique);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCppcheckLibraryData::platformTypeValid()
|
void TestCppcheckLibraryData::platformTypeValid()
|
||||||
|
@ -543,6 +549,46 @@ void TestCppcheckLibraryData::markupValid()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestCppcheckLibraryData::containerValid()
|
||||||
|
{
|
||||||
|
// Load library data from file
|
||||||
|
loadCfgFile(":/files/container_valid.cfg", fileLibraryData, result);
|
||||||
|
QCOMPARE(result.isNull(), true);
|
||||||
|
|
||||||
|
// Swap library data read from file to other object
|
||||||
|
libraryData.swap(fileLibraryData);
|
||||||
|
|
||||||
|
// Do size and content checks against swapped data.
|
||||||
|
QCOMPARE(libraryData.containers.size(), 1);
|
||||||
|
|
||||||
|
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList.size(), 2);
|
||||||
|
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[0].name, QString("first"));
|
||||||
|
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[0].templateParameter, QString("0"));
|
||||||
|
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[1].name, QString("second"));
|
||||||
|
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[1].templateParameter, QString("1"));
|
||||||
|
|
||||||
|
// Save library data to file
|
||||||
|
saveCfgFile(TempCfgFile, libraryData);
|
||||||
|
|
||||||
|
fileLibraryData.clear();
|
||||||
|
QCOMPARE(fileLibraryData.containers.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.containers.size(), fileLibraryData.containers.size());
|
||||||
|
for (int idx=0; idx < libraryData.containers.size(); idx++) {
|
||||||
|
CppcheckLibraryData::Container lhs = libraryData.containers[idx];
|
||||||
|
CppcheckLibraryData::Container rhs = fileLibraryData.containers[idx];
|
||||||
|
for (int num=0; num < lhs.rangeItemRecordTypeList.size(); num++) {
|
||||||
|
QCOMPARE(lhs.rangeItemRecordTypeList[num].name, rhs.rangeItemRecordTypeList[num].name);
|
||||||
|
QCOMPARE(lhs.rangeItemRecordTypeList[num].templateParameter, rhs.rangeItemRecordTypeList[num].templateParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TestCppcheckLibraryData::loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile)
|
void TestCppcheckLibraryData::loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile)
|
||||||
{
|
{
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
|
|
|
@ -39,6 +39,7 @@ private slots:
|
||||||
void undefineValid();
|
void undefineValid();
|
||||||
void reflectionValid();
|
void reflectionValid();
|
||||||
void markupValid();
|
void markupValid();
|
||||||
|
void containerValid();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile = false);
|
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile = false);
|
||||||
|
|
Loading…
Reference in New Issue