@@ -280,3 +280,88 @@ std::string CheckersReport::getReport(const std::string& criticalErrors) const
280280
281281 return fout.str ();
282282}
283+
284+ std::string CheckersReport::getXmlReport (const std::string& criticalErrors) const
285+ {
286+ std::string ret;
287+
288+ if (!criticalErrors.empty ()) {
289+ ret += " <critical-errors>" + criticalErrors + " \n </critical-errors>\n " ;
290+ } else
291+ ret += " <critical-errors/>\n " ;
292+ ret += " <checkers-report>\n " ;
293+
294+ const bool cppcheckPremium = isCppcheckPremium (mSettings );
295+
296+ auto reportSection = [&ret, cppcheckPremium]
297+ (const std::string& title,
298+ const Settings& settings,
299+ const std::set<std::string>& activeCheckers,
300+ const std::map<std::string, std::string>& premiumCheckers,
301+ const std::string& substring) {
302+ if (!cppcheckPremium) {
303+ ret += " <" + title + " />\n " ;
304+ return ;
305+ }
306+ ret += " <" + title + " >\n " ;
307+ for (const auto & checkReq: premiumCheckers) {
308+ const std::string& checker = checkReq.first ;
309+ if (checker.find (substring) == std::string::npos)
310+ continue ;
311+ bool active = cppcheckPremium && activeCheckers.count (checker) > 0 ;
312+ if (substring == " ::" ) {
313+ if (checkReq.second == " warning" )
314+ active &= settings.severity .isEnabled (Severity::warning);
315+ else if (checkReq.second == " style" )
316+ active &= settings.severity .isEnabled (Severity::style);
317+ else if (checkReq.second == " portability" )
318+ active &= settings.severity .isEnabled (Severity::portability);
319+ else if (!checkReq.second .empty ())
320+ active = false ; // FIXME: handle req
321+ }
322+ ret += " <checker active=\" " + std::string (active ? " Yes" : " No" ) + " \" id=\" " + checker + " \" " ;
323+ ret += " />\n " ;
324+ }
325+ ret += " </" + title + " >\n " ;
326+ };
327+
328+ reportSection (" premium-checkers" , mSettings , mActiveCheckers , checkers::premiumCheckers, " ::" );
329+ reportSection (" autosar" , mSettings , mActiveCheckers , checkers::premiumCheckers, " Autosar: " );
330+ reportSection (" cert-c" , mSettings , mActiveCheckers , checkers::premiumCheckers, " Cert C: " );
331+ reportSection (" cert-cpp" , mSettings , mActiveCheckers , checkers::premiumCheckers, " Cert C++: " );
332+
333+ int misra = 0 ;
334+ if (mSettings .premiumArgs .find (" misra-c-2012" ) != std::string::npos)
335+ misra = 2012 ;
336+ else if (mSettings .premiumArgs .find (" misra-c-2023" ) != std::string::npos)
337+ misra = 2023 ;
338+ else if (mSettings .addons .count (" misra" ))
339+ misra = 2012 ;
340+
341+ if (misra == 0 ) {
342+ ret += " <misra-c/>\n " ;
343+ } else {
344+ ret += " <misra-c-" + std::to_string (misra) + " >\n " ;
345+ for (const checkers::MisraInfo& info: checkers::misraC2012Directives) {
346+ const std::string directive = " Dir " + std::to_string (info.a ) + " ." + std::to_string (info.b );
347+ const bool active = isMisraRuleActive (mActiveCheckers , directive);
348+ ret += " <checker active=\" " ;
349+ ret += std::string (active ? " Yes" : " No" ) + " \" id=\" Misra C " + std::to_string (misra) + " : " + directive + " \" " ;
350+ ret += " />\n " ;
351+ }
352+ for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
353+ const std::string rule = std::to_string (info.a ) + " ." + std::to_string (info.b );
354+ const bool active = isMisraRuleActive (mActiveCheckers , rule);
355+ ret += " <checker active=\" " ;
356+ ret += std::string (active ? " Yes" : " No" ) + " \" id=\" Misra C " + std::to_string (misra) + " : " + rule + " \" " ;
357+ ret += " />\n " ;
358+ }
359+ ret += " </misra-c-" + std::to_string (misra) + " >\n " ;
360+ }
361+
362+ reportSection (" misra-cpp-2008" , mSettings , mActiveCheckers , checkers::premiumCheckers, " Misra C++ 2008: " );
363+ reportSection (" misra-cpp-2023" , mSettings , mActiveCheckers , checkers::premiumCheckers, " Misra C++ 2023: " );
364+
365+ ret += " </checkers-report>" ;
366+ return ret;
367+ }
0 commit comments