From 0dd2395fd0c2f3def0beb88d9bf98b64d57e0be1 Mon Sep 17 00:00:00 2001 From: firewave Date: Thu, 12 Feb 2026 17:38:05 +0100 Subject: [PATCH] improved `--debug-analyzerinfo` output --- lib/analyzerinfo.cpp | 48 +++++++++++++------------------- lib/analyzerinfo.h | 2 +- test/cli/other_test.py | 17 +++++------ test/testanalyzerinformation.cpp | 44 ++++++++++++++++++++++++----- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/lib/analyzerinfo.cpp b/lib/analyzerinfo.cpp index d484f7d50a9..30a6910eef4 100644 --- a/lib/analyzerinfo.cpp +++ b/lib/analyzerinfo.cpp @@ -83,32 +83,20 @@ void AnalyzerInformation::close() } } -bool AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list &errors, bool debug) +std::string AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list &errors) { const tinyxml2::XMLElement * const rootNode = analyzerInfoDoc.FirstChildElement(); - if (rootNode == nullptr) { - if (debug) - std::cout << "discarding cached result - no root node found" << std::endl; - return false; - } + if (rootNode == nullptr) + return "no root node found"; - if (strcmp(rootNode->Name(), "analyzerinfo") != 0) { - if (debug) - std::cout << "discarding cached result - unexpected root node" << std::endl; - return false; - } + if (strcmp(rootNode->Name(), "analyzerinfo") != 0) + return "unexpected root node"; const char * const attr = rootNode->Attribute("hash"); - if (!attr) { - if (debug) - std::cout << "discarding cached result - no 'hash' attribute found" << std::endl; - return false; - } - if (attr != std::to_string(hash)) { - if (debug) - std::cout << "discarding cached result - hash mismatch" << std::endl; - return false; - } + if (!attr) + return "no 'hash' attribute found"; + if (attr != std::to_string(hash)) + return "hash mismatch"; for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) { if (std::strcmp(e->Name(), "error") != 0) @@ -125,17 +113,15 @@ bool AnalyzerInformation::skipAnalysis(const tinyxml2::XMLDocument &analyzerInfo { // cppcheck-suppress useStlAlgorithm if (e->Attribute("id", id)) { - if (debug) - std::cout << "discarding cached result - '" << id << "' encountered" << std::endl; errors.clear(); - return false; + return std::string("'") + id + "' encountered"; } } errors.emplace_back(e); } - return true; + return ""; } std::string AnalyzerInformation::getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fsFileId) @@ -184,18 +170,22 @@ bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::st tinyxml2::XMLDocument analyzerInfoDoc; const tinyxml2::XMLError xmlError = analyzerInfoDoc.LoadFile(analyzerInfoFile.c_str()); if (xmlError == tinyxml2::XML_SUCCESS) { - if (skipAnalysis(analyzerInfoDoc, hash, errors, debug)) { + const std::string err = skipAnalysis(analyzerInfoDoc, hash, errors); + if (err.empty()) { if (debug) - std::cout << "skipping analysis - loaded " << errors.size() << " cached finding(s) from '" << analyzerInfoFile << "'" << std::endl; + std::cout << "skipping analysis - loaded " << errors.size() << " cached finding(s) from '" << analyzerInfoFile << "' for '" << sourcefile << "'" << std::endl; return false; } + if (debug) { + std::cout << "discarding cached result from '" << analyzerInfoFile << "' for '" << sourcefile << "' - " << err << std::endl; + } } else if (xmlError != tinyxml2::XML_ERROR_FILE_NOT_FOUND) { if (debug) - std::cout << "discarding cached result - failed to load '" << analyzerInfoFile << "' (" << tinyxml2::XMLDocument::ErrorIDToName(xmlError) << ")" << std::endl; + std::cout << "discarding cached result - failed to load '" << analyzerInfoFile << "' for '" << sourcefile << "' (" << tinyxml2::XMLDocument::ErrorIDToName(xmlError) << ")" << std::endl; } else if (debug) - std::cout << "no cached result '" << analyzerInfoFile << "' found" << std::endl; + std::cout << "no cached result '" << analyzerInfoFile << "' for '" << sourcefile << "' found" << std::endl; } mOutputStream.open(analyzerInfoFile); diff --git a/lib/analyzerinfo.h b/lib/analyzerinfo.h index 5435be62560..e2830bfbcb1 100644 --- a/lib/analyzerinfo.h +++ b/lib/analyzerinfo.h @@ -87,7 +87,7 @@ class CPPCHECKLIB AnalyzerInformation { static std::string getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fsFileId); - static bool skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list &errors, bool debug = false); + static std::string skipAnalysis(const tinyxml2::XMLDocument &analyzerInfoDoc, std::size_t hash, std::list &errors); private: std::ofstream mOutputStream; diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 5a6662faf56..1a80b06d929 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -4176,16 +4176,17 @@ def run_and_assert_cppcheck(stdout_exp): assert stdout.splitlines() == stdout_exp assert stderr.splitlines() == stderr_exp + test_file_s = str(test_file).replace('\\', '/') test_a1_file_s = str(test_a1_file).replace('\\', '/') # no cached results run_and_assert_cppcheck([ - "no cached result '{}' found".format(test_a1_file_s) + "no cached result '{}' for '{}' found".format(test_a1_file_s, test_file_s) ]) # cached results run_and_assert_cppcheck([ - "skipping analysis - loaded 1 cached finding(s) from '{}'".format(test_a1_file_s) + "skipping analysis - loaded 1 cached finding(s) from '{}' for '{}'".format(test_a1_file_s, test_file_s) ]) # modified file @@ -4193,7 +4194,7 @@ def run_and_assert_cppcheck(stdout_exp): f.write('\n#define DEF') run_and_assert_cppcheck([ - "discarding cached result - hash mismatch" # TODO: add filename + "discarding cached result from '{}' for '{}' - hash mismatch".format(test_a1_file_s, test_file_s) ]) # invalid XML @@ -4201,7 +4202,7 @@ def run_and_assert_cppcheck(stdout_exp): f.write('.') run_and_assert_cppcheck([ - "discarding cached result - failed to load '{}' (XML_ERROR_PARSING_TEXT)".format(test_a1_file_s) + "discarding cached result - failed to load '{}' for '{}' (XML_ERROR_PARSING_TEXT)".format(test_a1_file_s, test_file_s) ]) # missing root node @@ -4209,7 +4210,7 @@ def run_and_assert_cppcheck(stdout_exp): f.write('') run_and_assert_cppcheck([ - "discarding cached result - no root node found" # TODO: add filename + "discarding cached result from '{}' for '{}' - no root node found".format(test_a1_file_s, test_file_s) ]) # mismatched root node @@ -4217,7 +4218,7 @@ def run_and_assert_cppcheck(stdout_exp): f.write('') run_and_assert_cppcheck([ - "discarding cached result - unexpected root node" # TODO: add filename + "discarding cached result from '{}' for '{}' - unexpected root node".format(test_a1_file_s, test_file_s) ]) # missing 'hash' attribute @@ -4225,7 +4226,7 @@ def run_and_assert_cppcheck(stdout_exp): f.write('') run_and_assert_cppcheck([ - "discarding cached result - no 'hash' attribute found" # TODO: add filename + "discarding cached result from '{}' for '{}' - no 'hash' attribute found".format(test_a1_file_s, test_file_s) ]) # invalid 'hash' attribute @@ -4233,7 +4234,7 @@ def run_and_assert_cppcheck(stdout_exp): f.write('') run_and_assert_cppcheck([ - "discarding cached result - hash mismatch" # TODO: add filename + "discarding cached result from '{}' for '{}' - hash mismatch".format(test_a1_file_s, test_file_s) ]) # TODO: diff --git a/test/testanalyzerinformation.cpp b/test/testanalyzerinformation.cpp index a92a8c37b1a..22f868ffb1d 100644 --- a/test/testanalyzerinformation.cpp +++ b/test/testanalyzerinformation.cpp @@ -126,7 +126,7 @@ class TestAnalyzerInformation : public TestFixture { ); ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); - ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS("'premium-invalidLicense' encountered", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); ASSERT_EQUALS(0, errorList.size()); } @@ -145,7 +145,7 @@ class TestAnalyzerInformation : public TestFixture { ); ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); - ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS("'premium-internalError' encountered", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); ASSERT_EQUALS(0, errorList.size()); } @@ -164,7 +164,7 @@ class TestAnalyzerInformation : public TestFixture { ); ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); - ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS("'internalError' encountered", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); ASSERT_EQUALS(0, errorList.size()); } @@ -185,7 +185,7 @@ class TestAnalyzerInformation : public TestFixture { ); ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); - ASSERT_EQUALS(true, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS("", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); ASSERT_EQUALS(1, errorList.size()); } @@ -201,7 +201,7 @@ class TestAnalyzerInformation : public TestFixture { ); ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); - ASSERT_EQUALS(true, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS("", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); ASSERT_EQUALS(0, errorList.size()); } @@ -222,7 +222,7 @@ class TestAnalyzerInformation : public TestFixture { ); ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); - ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 99, errorList)); + ASSERT_EQUALS("hash mismatch", AnalyzerInformationTest::skipAnalysis(doc, 99, errorList)); ASSERT_EQUALS(0, errorList.size()); } @@ -234,7 +234,37 @@ class TestAnalyzerInformation : public TestFixture { const tinyxml2::XMLError xmlError = doc.Parse(""); ASSERT_EQUALS(tinyxml2::XML_ERROR_EMPTY_DOCUMENT, xmlError); - ASSERT_EQUALS(false, AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS("no root node found", AnalyzerInformationTest::skipAnalysis(doc, 100, errorList)); + ASSERT_EQUALS(0, errorList.size()); + } + + // Unexpected root node + { + std::list errorList; + tinyxml2::XMLDocument doc; + + const tinyxml2::XMLError xmlError = doc.Parse( + "" + "" + ); + ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); + + ASSERT_EQUALS("unexpected root node", AnalyzerInformationTest::skipAnalysis(doc, 99, errorList)); + ASSERT_EQUALS(0, errorList.size()); + } + + // No 'hash' attribute found + { + std::list errorList; + tinyxml2::XMLDocument doc; + + const tinyxml2::XMLError xmlError = doc.Parse( + "" + "" + ); + ASSERT_EQUALS(tinyxml2::XML_SUCCESS, xmlError); + + ASSERT_EQUALS("no 'hash' attribute found", AnalyzerInformationTest::skipAnalysis(doc, 99, errorList)); ASSERT_EQUALS(0, errorList.size()); } }