Fixed #12281 (IDE plugin integration is broken by checkers report) (#5779)

This commit is contained in:
Daniel Marjamäki 2023-12-19 15:55:29 +01:00 committed by GitHub
parent 3b1c701766
commit 49da3e3821
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 28 deletions

View File

@ -116,7 +116,7 @@ public:
/** /**
* @brief Write the checkers report * @brief Write the checkers report
*/ */
void writeCheckersReport() const; void writeCheckersReport();
bool hasCriticalErrors() const { bool hasCriticalErrors() const {
return !mCriticalErrors.empty(); return !mCriticalErrors.empty();
@ -286,12 +286,13 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) const
cppcheck.tooManyConfigsError(emptyString,0U); cppcheck.tooManyConfigsError(emptyString,0U);
} }
if (settings.safety || settings.severity.isEnabled(Severity::information) || !settings.checkersReportFilename.empty())
mStdLogger->writeCheckersReport();
if (settings.xml) { if (settings.xml) {
mStdLogger->reportErr(ErrorMessage::getXMLFooter()); mStdLogger->reportErr(ErrorMessage::getXMLFooter());
} }
mStdLogger->writeCheckersReport();
if (settings.safety && mStdLogger->hasCriticalErrors()) if (settings.safety && mStdLogger->hasCriticalErrors())
return EXIT_FAILURE; return EXIT_FAILURE;
@ -300,28 +301,39 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) const
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void CppCheckExecutor::StdLogger::writeCheckersReport() const void CppCheckExecutor::StdLogger::writeCheckersReport()
{ {
CheckersReport checkersReport(mSettings, mActiveCheckers); CheckersReport checkersReport(mSettings, mActiveCheckers);
if (!mSettings.quiet) { bool suppressed = false;
for (const Suppressions::Suppression& s : mSettings.nomsg.getSuppressions()) {
if (s.errorId == "checkersReport")
suppressed = true;
}
if (!suppressed) {
ErrorMessage msg;
msg.severity = Severity::information;
msg.id = "checkersReport";
const int activeCheckers = checkersReport.getActiveCheckersCount(); const int activeCheckers = checkersReport.getActiveCheckersCount();
const int totalCheckers = checkersReport.getAllCheckersCount(); const int totalCheckers = checkersReport.getAllCheckersCount();
const std::string extra = mSettings.verbose ? " (use --checkers-report=<filename> to see details)" : ""; std::string what;
if (mCriticalErrors.empty()) if (mCriticalErrors.empty())
std::cout << "Active checkers: " << activeCheckers << "/" << totalCheckers << extra << std::endl; what = std::to_string(activeCheckers) + "/" + std::to_string(totalCheckers);
else else
std::cout << "Active checkers: There was critical errors" << extra << std::endl; what = "There was critical errors";
msg.setmsg("Active checkers: " + what + " (use --checkers-report=<filename> to see details)");
reportErr(msg);
} }
if (mSettings.checkersReportFilename.empty()) if (!mSettings.checkersReportFilename.empty()) {
return;
std::ofstream fout(mSettings.checkersReportFilename); std::ofstream fout(mSettings.checkersReportFilename);
if (fout.is_open()) if (fout.is_open())
fout << checkersReport.getReport(mCriticalErrors); fout << checkersReport.getReport(mCriticalErrors);
}
} }
#ifdef _WIN32 #ifdef _WIN32

View File

@ -35,6 +35,9 @@
#include "xml.h" #include "xml.h"
static const char ID_UNUSEDFUNCTION[] = "unusedFunction";
static const char ID_CHECKERSREPORT[] = "checkersReport";
Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg, const std::set<std::string> &macroNames) Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg, const std::set<std::string> &macroNames)
{ {
Suppressions::ErrorMessage ret; Suppressions::ErrorMessage ret;
@ -468,7 +471,9 @@ std::list<Suppressions::Suppression> Suppressions::getUnmatchedLocalSuppressions
continue; continue;
if (s.hash > 0) if (s.hash > 0)
continue; continue;
if (!unusedFunctionChecking && s.errorId == "unusedFunction") if (s.errorId == ID_CHECKERSREPORT)
continue;
if (!unusedFunctionChecking && s.errorId == ID_UNUSEDFUNCTION)
continue; continue;
if (tmpFile.empty() || !s.isLocal() || s.fileName != tmpFile) if (tmpFile.empty() || !s.isLocal() || s.fileName != tmpFile)
continue; continue;
@ -485,7 +490,9 @@ std::list<Suppressions::Suppression> Suppressions::getUnmatchedGlobalSuppression
continue; continue;
if (s.hash > 0) if (s.hash > 0)
continue; continue;
if (!unusedFunctionChecking && s.errorId == "unusedFunction") if (!unusedFunctionChecking && s.errorId == ID_UNUSEDFUNCTION)
continue;
if (s.errorId == ID_CHECKERSREPORT)
continue; continue;
if (s.isLocal()) if (s.isLocal())
continue; continue;

View File

@ -12,7 +12,7 @@ GUI:
- -
Changed interface: Changed interface:
- - Final report of active checkers is reported as a normal information message instead.
Deprecations: Deprecations:
- "--showtime=top5" has been deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead. - "--showtime=top5" has been deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead.
@ -44,6 +44,3 @@ Other:
- Markup files will now be processed after the regular source files when using multiple threads/processes (some issues remain - see Trac #12167 for details). - Markup files will now be processed after the regular source files when using multiple threads/processes (some issues remain - see Trac #12167 for details).
- Added file name to ValueFlow "--debug" output. - Added file name to ValueFlow "--debug" output.
- Fixed build when using "clang-cl" in CMake. - Fixed build when using "clang-cl" in CMake.
Safety critical fixes:
- Added "--safety" option. It makes Cppcheck more strict about critical errors.

View File

@ -14,14 +14,14 @@ def test_j2_suppress():
assert len(stderr) == 0 assert len(stderr) == 0
def test_safety_suppress_syntax_error_implicitly(tmpdir): def test_safety_suppress_syntax_error_implicitly(tmpdir):
ret, stdout, stderr = cppcheck(['--safety', '--suppress=*', 'proj-suppress-syntaxError'], remove_active_checkers=False) ret, stdout, stderr = cppcheck(['--safety', '--suppress=*', 'proj-suppress-syntaxError'], remove_checkers_report=False)
assert ret == 1 assert ret == 1
assert '[syntaxError]' in stderr assert '[syntaxError]' in stderr
assert 'Active checkers: There was critical errors' in stdout assert 'Active checkers: There was critical errors' in stderr
def test_safety_suppress_syntax_error_explicitly(): def test_safety_suppress_syntax_error_explicitly():
ret, stdout, stderr = cppcheck(['--safety', '--suppress=syntaxError', 'proj-suppress-syntaxError'], remove_active_checkers=False) ret, stdout, stderr = cppcheck(['--safety', '--suppress=syntaxError', 'proj-suppress-syntaxError'], remove_checkers_report=False)
assert ret == 1 assert ret == 1
assert '[syntaxError]' not in stderr assert '[syntaxError]' not in stderr
assert 'Active checkers: There was critical errors' in stdout assert 'Active checkers: There was critical errors' in stderr

View File

@ -71,7 +71,7 @@ def __lookup_cppcheck_exe():
# Run Cppcheck with args # Run Cppcheck with args
def cppcheck(args, env=None, remove_active_checkers=True): def cppcheck(args, env=None, remove_checkers_report=True):
exe = __lookup_cppcheck_exe() exe = __lookup_cppcheck_exe()
assert exe is not None, 'no cppcheck binary found' assert exe is not None, 'no cppcheck binary found'
@ -80,8 +80,20 @@ def cppcheck(args, env=None, remove_active_checkers=True):
comm = p.communicate() comm = p.communicate()
stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n')
stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n') stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n')
if remove_active_checkers and stdout.find('\nActive checkers:') > 0: if remove_checkers_report:
stdout = stdout[:1 + stdout.find('\nActive checkers:')] if stderr.find('[checkersReport]\n') > 0:
start_id = stderr.find('[checkersReport]\n')
start_line = stderr.rfind('\n', 0, start_id)
if start_line <= 0:
stderr = ''
else:
stderr = stderr[:start_line + 1]
elif stderr.find(': (information) Active checkers: ') >= 0:
pos = stderr.find(': (information) Active checkers: ')
if pos == 0:
stderr = ''
elif stderr[pos - 1] == '\n':
stderr = stderr[:pos]
return p.returncode, stdout, stderr return p.returncode, stdout, stderr