Add missing support for "type-checks" and "smart-pointer" configuration. (#3039)
This commit is contained in:
parent
fde5994cc3
commit
ab7d728831
|
@ -94,6 +94,11 @@ jobs:
|
|||
qmake
|
||||
make -j$(nproc)
|
||||
./test-projectfile
|
||||
popd
|
||||
pushd gui/test/cppchecklibrarydata
|
||||
qmake
|
||||
make -j$(nproc)
|
||||
./test-cppchecklibrarydata
|
||||
|
||||
- name: Generate Qt help file on ubuntu
|
||||
if: contains(matrix.os, 'ubuntu')
|
||||
|
|
|
@ -106,6 +106,28 @@ static QString loadUndefine(const QXmlStreamReader &xmlReader)
|
|||
return xmlReader.attributes().value("name").toString();
|
||||
}
|
||||
|
||||
static QString loadSmartPointer(const QXmlStreamReader &xmlReader)
|
||||
{
|
||||
return xmlReader.attributes().value("class-name").toString();
|
||||
}
|
||||
|
||||
static CppcheckLibraryData::TypeChecks loadTypeChecks(QXmlStreamReader &xmlReader)
|
||||
{
|
||||
CppcheckLibraryData::TypeChecks typeChecks;
|
||||
QXmlStreamReader::TokenType type;
|
||||
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
|
||||
xmlReader.name().toString() != "type-checks") {
|
||||
if (type != QXmlStreamReader::StartElement)
|
||||
continue;
|
||||
const QString elementName = xmlReader.name().toString();
|
||||
if (elementName == "suppress" || elementName == "check") {
|
||||
QPair<QString, QString> entry(elementName, xmlReader.readElementText());
|
||||
typeChecks.append(entry);
|
||||
}
|
||||
}
|
||||
return typeChecks;
|
||||
}
|
||||
|
||||
static CppcheckLibraryData::Function::Arg loadFunctionArg(QXmlStreamReader &xmlReader)
|
||||
{
|
||||
CppcheckLibraryData::Function::Arg arg;
|
||||
|
@ -279,6 +301,10 @@ QString CppcheckLibraryData::open(QIODevice &file)
|
|||
memoryresource.append(loadMemoryResource(xmlReader));
|
||||
else if (elementName == "podtype")
|
||||
podtypes.append(loadPodType(xmlReader));
|
||||
else if (elementName == "smart-pointer")
|
||||
smartPointers.append(loadSmartPointer(xmlReader));
|
||||
else if (elementName == "type-checks")
|
||||
typeChecks.append(loadTypeChecks(xmlReader));
|
||||
else
|
||||
unhandledElement(xmlReader);
|
||||
} catch (std::runtime_error &e) {
|
||||
|
@ -501,6 +527,24 @@ static void writeMemoryResource(QXmlStreamWriter &xmlWriter, const CppcheckLibra
|
|||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
static void writeTypeChecks(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::TypeChecks &typeChecks)
|
||||
{
|
||||
QPair<QString, QString> check;
|
||||
xmlWriter.writeStartElement("type-checks");
|
||||
if (!typeChecks.isEmpty()) {
|
||||
xmlWriter.writeStartElement("unusedvar");
|
||||
}
|
||||
foreach (check, typeChecks) {
|
||||
xmlWriter.writeStartElement(check.first);
|
||||
xmlWriter.writeCharacters(check.second);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
if (!typeChecks.isEmpty()) {
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
QString CppcheckLibraryData::toString() const
|
||||
{
|
||||
QString outputString;
|
||||
|
@ -548,6 +592,16 @@ QString CppcheckLibraryData::toString() const
|
|||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
foreach (const TypeChecks check, typeChecks) {
|
||||
writeTypeChecks(xmlWriter, check);
|
||||
}
|
||||
|
||||
foreach (const QString &smartPtr, smartPointers) {
|
||||
xmlWriter.writeStartElement("smart-pointer");
|
||||
xmlWriter.writeAttribute("class-name", smartPtr);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
|
||||
return outputString;
|
||||
|
|
|
@ -171,6 +171,8 @@ public:
|
|||
QString sign;
|
||||
};
|
||||
|
||||
using TypeChecks = QList<QPair<QString, QString>>;
|
||||
|
||||
void clear() {
|
||||
containers.clear();
|
||||
defines.clear();
|
||||
|
@ -178,9 +180,10 @@ public:
|
|||
functions.clear();
|
||||
memoryresource.clear();
|
||||
podtypes.clear();
|
||||
smartPointers.clear();
|
||||
typeChecks.clear();
|
||||
}
|
||||
|
||||
|
||||
void swap(CppcheckLibraryData &other) {
|
||||
containers.swap(other.containers);
|
||||
defines.swap(other.defines);
|
||||
|
@ -188,6 +191,8 @@ public:
|
|||
functions.swap(other.functions);
|
||||
memoryresource.swap(other.memoryresource);
|
||||
podtypes.swap(other.podtypes);
|
||||
smartPointers.swap(other.smartPointers);
|
||||
typeChecks.swap(other.typeChecks);
|
||||
}
|
||||
|
||||
QString open(QIODevice &file);
|
||||
|
@ -198,7 +203,9 @@ public:
|
|||
QList<struct Function> functions;
|
||||
QList<struct MemoryResource> memoryresource;
|
||||
QList<struct PodType> podtypes;
|
||||
QList<TypeChecks> typeChecks;
|
||||
QStringList undefines;
|
||||
QStringList smartPointers;
|
||||
};
|
||||
|
||||
#endif // CPPCHECKLIBRARYDATA_H
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
TEMPLATE = app
|
||||
TARGET = test-cppchecklibrarydata
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
OBJECTS_DIR = ../build
|
||||
MOC_DIR = ../build
|
||||
|
||||
QT -= gui
|
||||
QT += core
|
||||
CONFIG += console
|
||||
|
||||
include(../common.pri)
|
||||
|
||||
DEFINES += SRCDIR=\\\"$$PWD\\\"
|
||||
|
||||
SOURCES += testcppchecklibrarydata.cpp \
|
||||
../../cppchecklibrarydata.cpp
|
||||
|
||||
HEADERS += testcppchecklibrarydata.h \
|
||||
../../cppchecklibrarydata.h \
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0"?>
|
||||
<def format="2">
|
||||
<podtype sign="u" size="4" stdtype="uint32_t"/>
|
||||
</def>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<def format="2">
|
||||
<podtype name="bool"/>
|
||||
<podtype name="ulong" sign="u" size="4" stdtype="uint32_t"/>
|
||||
</def>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<def format="2">
|
||||
<smart-pointer class-name="wxObjectDataPtr"/>
|
||||
<smart-pointer class-name="wxScopedArray"/>
|
||||
<smart-pointer class-name="wxScopedPtr"/>
|
||||
</def>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0"?>
|
||||
<def format="2">
|
||||
<type-checks>
|
||||
<unusedvar>
|
||||
<suppress>std::insert_iterator</suppress>
|
||||
<check>std::pair</check>
|
||||
</unusedvar>
|
||||
</type-checks>
|
||||
<type-checks/>
|
||||
<type-checks>
|
||||
<unusedvar>
|
||||
<check>std::tuple</check>
|
||||
</unusedvar>
|
||||
</type-checks>
|
||||
</def>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<def format="2">
|
||||
<!-- error: typo which should trigger unhandled element handler -->
|
||||
<podtyp sign="u" size="4" stdtype="uint32_t"/>
|
||||
</def>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<def format="2">
|
||||
<!-- error: redefinition of size attribute -->
|
||||
<podtype name="ulong" sign="u" size="4" size="4"/>
|
||||
</def>
|
|
@ -0,0 +1,10 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>files/xml_reader_error.cfg</file>
|
||||
<file>files/mandatory_attribute_missing.cfg</file>
|
||||
<file>files/unhandled_element.cfg</file>
|
||||
<file>files/typechecks_valid.cfg</file>
|
||||
<file>files/podtype_valid.cfg</file>
|
||||
<file>files/smartptr_valid.cfg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2021 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testcppchecklibrarydata.h"
|
||||
|
||||
const QString TestCppcheckLibraryData::TempCfgFile = "./tmp.cfg";
|
||||
|
||||
void TestCppcheckLibraryData::init()
|
||||
{
|
||||
result.clear();
|
||||
libraryData.clear();
|
||||
fileLibraryData.clear();
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::xmlReaderError()
|
||||
{
|
||||
loadCfgFile(":/files/xml_reader_error.cfg", fileLibraryData, result);
|
||||
QCOMPARE(result.isNull(), false);
|
||||
qDebug() << result;
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::unhandledElement()
|
||||
{
|
||||
loadCfgFile(":/files/unhandled_element.cfg", fileLibraryData, result);
|
||||
QCOMPARE(result.isNull(), false);
|
||||
qDebug() << result;
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::mandatoryAttributeMissing()
|
||||
{
|
||||
loadCfgFile(":/files/mandatory_attribute_missing.cfg", fileLibraryData, result);
|
||||
QCOMPARE(result.isNull(), false);
|
||||
qDebug() << result;
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::podtypeValid()
|
||||
{
|
||||
// Load library data from file
|
||||
loadCfgFile(":/files/podtype_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.podtypes.size(), 2);
|
||||
|
||||
QCOMPARE(libraryData.podtypes[0].name, "bool");
|
||||
QCOMPARE(libraryData.podtypes[0].stdtype.isEmpty(), true);
|
||||
QCOMPARE(libraryData.podtypes[0].sign.isEmpty(), true);
|
||||
QCOMPARE(libraryData.podtypes[0].size.isEmpty(), true);
|
||||
|
||||
QCOMPARE(libraryData.podtypes[1].name, "ulong");
|
||||
QCOMPARE(libraryData.podtypes[1].stdtype, "uint32_t");
|
||||
QCOMPARE(libraryData.podtypes[1].sign, "u");
|
||||
QCOMPARE(libraryData.podtypes[1].size, "4");
|
||||
|
||||
// Save library data to file
|
||||
saveCfgFile(TempCfgFile, libraryData);
|
||||
|
||||
fileLibraryData.clear();
|
||||
QCOMPARE(fileLibraryData.podtypes.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.podtypes.size(), fileLibraryData.podtypes.size());
|
||||
QCOMPARE(libraryData.podtypes.size(), 2);
|
||||
for (int i=0; i < libraryData.podtypes.size(); i++) {
|
||||
QCOMPARE(libraryData.podtypes[i].name, fileLibraryData.podtypes[i].name);
|
||||
QCOMPARE(libraryData.podtypes[i].stdtype, fileLibraryData.podtypes[i].stdtype);
|
||||
QCOMPARE(libraryData.podtypes[i].sign, fileLibraryData.podtypes[i].sign);
|
||||
QCOMPARE(libraryData.podtypes[i].size, fileLibraryData.podtypes[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::typechecksValid()
|
||||
{
|
||||
// Load library data from file
|
||||
loadCfgFile(":/files/typechecks_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.typeChecks.size(), 3);
|
||||
|
||||
CppcheckLibraryData::TypeChecks check = libraryData.typeChecks[0];
|
||||
QCOMPARE(check.size(), 2);
|
||||
QCOMPARE(check[0].first, "suppress");
|
||||
QCOMPARE(check[0].second, "std::insert_iterator");
|
||||
QCOMPARE(check[1].first, "check");
|
||||
QCOMPARE(check[1].second, "std::pair");
|
||||
|
||||
check = libraryData.typeChecks[1];
|
||||
QCOMPARE(check.isEmpty(), true);
|
||||
|
||||
check = libraryData.typeChecks[2];
|
||||
QCOMPARE(check.size(), 1);
|
||||
QCOMPARE(check[0].first, "check");
|
||||
QCOMPARE(check[0].second, "std::tuple");
|
||||
|
||||
// Save library data to file
|
||||
saveCfgFile(TempCfgFile, libraryData);
|
||||
|
||||
fileLibraryData.clear();
|
||||
QCOMPARE(fileLibraryData.typeChecks.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.typeChecks.size(), fileLibraryData.typeChecks.size());
|
||||
QCOMPARE(libraryData.typeChecks.size(), 3);
|
||||
for (int idx=0; idx < libraryData.typeChecks.size(); idx++) {
|
||||
CppcheckLibraryData::TypeChecks lhs = libraryData.typeChecks[idx];
|
||||
CppcheckLibraryData::TypeChecks rhs = fileLibraryData.typeChecks[idx];
|
||||
QCOMPARE(lhs.size(), lhs.size());
|
||||
for (int num=0; num < lhs.size(); num++) {
|
||||
QCOMPARE(lhs[num].first, rhs[num].first);
|
||||
QCOMPARE(lhs[num].second, rhs[num].second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::smartPointerValid()
|
||||
{
|
||||
// Load library data from file
|
||||
loadCfgFile(":/files/smartptr_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.smartPointers.size(), 3);
|
||||
|
||||
QCOMPARE(libraryData.smartPointers[0], "wxObjectDataPtr");
|
||||
QCOMPARE(libraryData.smartPointers[1], "wxScopedArray");
|
||||
QCOMPARE(libraryData.smartPointers[2], "wxScopedPtr");
|
||||
|
||||
// Save library data to file
|
||||
saveCfgFile(TempCfgFile, libraryData);
|
||||
|
||||
fileLibraryData.clear();
|
||||
QCOMPARE(fileLibraryData.smartPointers.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.smartPointers.size(), fileLibraryData.smartPointers.size());
|
||||
QCOMPARE(libraryData.smartPointers.size(), 3);
|
||||
for (int i=0; i < libraryData.smartPointers.size(); i++) {
|
||||
QCOMPARE(libraryData.smartPointers[i], fileLibraryData.smartPointers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::loadCfgFile(QString filename, CppcheckLibraryData &data, QString &result, bool removeFile)
|
||||
{
|
||||
QFile file(filename);
|
||||
QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
|
||||
result = data.open(file);
|
||||
file.close();
|
||||
if (removeFile) {
|
||||
file.remove();
|
||||
}
|
||||
}
|
||||
|
||||
void TestCppcheckLibraryData::saveCfgFile(QString filename, CppcheckLibraryData &data)
|
||||
{
|
||||
QFile file(filename);
|
||||
QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
|
||||
QTextStream textStream(&file);
|
||||
textStream << data.toString() << '\n';
|
||||
file.close();
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestCppcheckLibraryData)
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2021 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include "cppchecklibrarydata.h"
|
||||
|
||||
class TestCppcheckLibraryData: public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
|
||||
void xmlReaderError();
|
||||
void unhandledElement();
|
||||
void mandatoryAttributeMissing();
|
||||
|
||||
void podtypeValid();
|
||||
void typechecksValid();
|
||||
void smartPointerValid();
|
||||
|
||||
private:
|
||||
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &result, bool removeFile = false);
|
||||
void saveCfgFile(QString filename, CppcheckLibraryData &data);
|
||||
|
||||
CppcheckLibraryData libraryData;
|
||||
CppcheckLibraryData fileLibraryData;
|
||||
QString result;
|
||||
|
||||
static const QString TempCfgFile;
|
||||
};
|
Loading…
Reference in New Issue