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") {
|
||||
container.type.templateParameter = xmlReader.attributes().value("templateParameter").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();
|
||||
if (elementName == "access" && indexOperator == "array-like")
|
||||
container.access_arrayLike = true;
|
||||
|
@ -82,7 +82,12 @@ static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
|
|||
container.sizeFunctions.append(function);
|
||||
else if (elementName == "access")
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
|
@ -105,9 +110,23 @@ static QString loadUndefine(const QXmlStreamReader &xmlReader)
|
|||
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)
|
||||
|
@ -210,6 +229,20 @@ static CppcheckLibraryData::Function loadFunction(QXmlStreamReader &xmlReader, c
|
|||
function.warn.reason = xmlReader.attributes().value("reason").toString();
|
||||
function.warn.alternatives = xmlReader.attributes().value("alternatives").toString();
|
||||
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 {
|
||||
unhandledElement(xmlReader);
|
||||
}
|
||||
|
@ -493,6 +526,20 @@ static void writeContainerFunctions(QXmlStreamWriter &xmlWriter, const QString &
|
|||
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)
|
||||
{
|
||||
xmlWriter.writeStartElement("container");
|
||||
|
@ -519,6 +566,7 @@ static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryDat
|
|||
writeContainerFunctions(xmlWriter, "size", container.size_templateParameter, container.sizeFunctions);
|
||||
writeContainerFunctions(xmlWriter, "access", container.access_arrayLike?1:-1, container.accessFunctions);
|
||||
writeContainerFunctions(xmlWriter, "other", -1, container.otherFunctions);
|
||||
writeContainerRangeItemRecords(xmlWriter, container.rangeItemRecordTypeList);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
|
@ -632,7 +680,20 @@ static void writeFunction(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData
|
|||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -835,9 +896,12 @@ QString CppcheckLibraryData::toString() const
|
|||
writeTypeChecks(xmlWriter, check);
|
||||
}
|
||||
|
||||
for (const QString &smartPtr : smartPointers) {
|
||||
for (const SmartPointer &smartPtr : smartPointers) {
|
||||
xmlWriter.writeStartElement("smart-pointer");
|
||||
xmlWriter.writeAttribute("class-name", smartPtr);
|
||||
xmlWriter.writeAttribute("class-name", smartPtr.name);
|
||||
if (smartPtr.unique) {
|
||||
xmlWriter.writeEmptyElement("unique");
|
||||
}
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
|
@ -47,6 +48,11 @@ public:
|
|||
QString string;
|
||||
} type;
|
||||
|
||||
struct RangeItemRecordType {
|
||||
QString name;
|
||||
QString templateParameter;
|
||||
};
|
||||
|
||||
struct Function {
|
||||
QString name;
|
||||
QString yields;
|
||||
|
@ -55,6 +61,7 @@ public:
|
|||
QList<struct Function> accessFunctions;
|
||||
QList<struct Function> otherFunctions;
|
||||
QList<struct Function> sizeFunctions;
|
||||
QList<struct RangeItemRecordType> rangeItemRecordTypeList;
|
||||
};
|
||||
|
||||
struct Define {
|
||||
|
@ -130,6 +137,9 @@ public:
|
|||
msg.isEmpty();
|
||||
}
|
||||
} warn;
|
||||
|
||||
QMap<QString, QString> notOverlappingDataArgs;
|
||||
QMap<QString, QString> containerAttributes;
|
||||
};
|
||||
|
||||
struct MemoryResource {
|
||||
|
@ -219,6 +229,15 @@ public:
|
|||
QList<Exporter> exporter;
|
||||
};
|
||||
|
||||
struct SmartPointer {
|
||||
SmartPointer() :
|
||||
unique {false}
|
||||
{}
|
||||
|
||||
QString name;
|
||||
bool unique;
|
||||
};
|
||||
|
||||
void clear() {
|
||||
containers.clear();
|
||||
defines.clear();
|
||||
|
@ -258,7 +277,7 @@ public:
|
|||
QList<TypeChecks> typeChecks;
|
||||
QList<struct PlatformType> platformTypes;
|
||||
QStringList undefines;
|
||||
QStringList smartPointers;
|
||||
QList<struct SmartPointer> smartPointers;
|
||||
QList<struct Reflection> reflections;
|
||||
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"?>
|
||||
<def format="2">
|
||||
<smart-pointer class-name="wxObjectDataPtr"/>
|
||||
<smart-pointer class-name="wxScopedArray"/>
|
||||
<smart-pointer class-name="wxScopedArray">
|
||||
<unique/>
|
||||
</smart-pointer>
|
||||
<smart-pointer class-name="wxScopedPtr"/>
|
||||
</def>
|
|
@ -19,5 +19,6 @@
|
|||
<file>files/markup_mandatory_attribute_missing.cfg</file>
|
||||
<file>files/markup_valid.cfg</file>
|
||||
<file>files/markup_unhandled_element.cfg</file>
|
||||
<file>files/container_valid.cfg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -182,9 +182,12 @@ void TestCppcheckLibraryData::smartPointerValid()
|
|||
// Do size and content checks against swapped data.
|
||||
QCOMPARE(libraryData.smartPointers.size(), 3);
|
||||
|
||||
QCOMPARE(libraryData.smartPointers[0], QString("wxObjectDataPtr"));
|
||||
QCOMPARE(libraryData.smartPointers[1], QString("wxScopedArray"));
|
||||
QCOMPARE(libraryData.smartPointers[2], QString("wxScopedPtr"));
|
||||
QCOMPARE(libraryData.smartPointers[0].name, QString("wxObjectDataPtr"));
|
||||
QCOMPARE(libraryData.smartPointers[0].unique, false);
|
||||
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
|
||||
saveCfgFile(TempCfgFile, libraryData);
|
||||
|
@ -199,7 +202,10 @@ void TestCppcheckLibraryData::smartPointerValid()
|
|||
// Verify no data got lost or modified
|
||||
QCOMPARE(libraryData.smartPointers.size(), fileLibraryData.smartPointers.size());
|
||||
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()
|
||||
|
@ -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)
|
||||
{
|
||||
QFile file(filename);
|
||||
|
|
|
@ -39,6 +39,7 @@ private slots:
|
|||
void undefineValid();
|
||||
void reflectionValid();
|
||||
void markupValid();
|
||||
void containerValid();
|
||||
|
||||
private:
|
||||
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile = false);
|
||||
|
|
Loading…
Reference in New Issue