Add --plist-output argument

This commit is contained in:
Daniel Marjamäki 2017-05-16 14:07:23 +02:00
parent 3ef2f825c7
commit 6967d68137
5 changed files with 159 additions and 6 deletions

View File

@ -268,6 +268,15 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
}
}
// Write results in results.plist
else if (std::strncmp(argv[i], "--plist-output=", 15) == 0) {
_settings->plistOutput = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 15));
if (_settings->plistOutput.empty())
_settings->plistOutput = "./";
else if (!endsWith(_settings->plistOutput,'/'))
_settings->plistOutput += '/';
}
// Write results in results.xml
else if (std::strcmp(argv[i], "--xml") == 0)
_settings->xml = true;
@ -937,6 +946,8 @@ void CmdLineParser::PrintHelp()
" further assumptions.\n"
" * unspecified\n"
" Unknown type sizes\n"
" --plist-output=<path>\n"
" Generate Clang-plist output files in folder.\n"
" -q, --quiet Do not show progress reports.\n"
" -rp, --relative-paths\n"
" -rp=<paths>, --relative-paths=<paths>\n"

View File

@ -123,6 +123,11 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin
}
}
if (plistFile.is_open()) {
plistFile << ErrorLogger::plistFooter();
plistFile.close();
}
CheckUnusedFunctions checkUnusedFunctions(0,0,0);
bool internalErrorFound(false);
@ -135,6 +140,17 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin
simplecpp::TokenList tokens1(fileStream, files, filename, &outputList);
preprocessor.loadFiles(tokens1, files);
if (!_settings.plistOutput.empty()) {
std::string filename2;
if (filename.find("/") != std::string::npos)
filename2 = filename.substr(filename.rfind("/") + 1);
else
filename2 = filename;
filename2 = _settings.plistOutput + filename2.substr(0, filename2.find(".")) + ".plist";
plistFile.open(filename2);
plistFile << ErrorLogger::plistHeader(version(), files);
}
// write dump file xml prolog
std::ofstream fdump;
if (_settings.dump) {
@ -428,7 +444,6 @@ void CppCheck::internalError(const std::string &filename, const std::string &msg
false);
_errorLogger.reportErr(errmsg);
} else {
// Report on stdout
_errorLogger.reportOut(fullmsg);
@ -692,6 +707,9 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
_errorLogger.reportErr(msg);
analyzerInformation.reportErr(msg, _settings.verbose);
if (!_settings.plistOutput.empty() && plistFile.is_open()) {
plistFile << ErrorLogger::plistData(msg);
}
}
void CppCheck::reportOut(const std::string &outmsg)

View File

@ -449,7 +449,7 @@ std::string ErrorLogger::callStackToString(const std::list<ErrorLogger::ErrorMes
ErrorLogger::ErrorMessage::FileLocation::FileLocation(const Token* tok, const TokenList* list)
: line(tok->linenr()), _file(list->file(tok))
: line(tok->linenr()), fileNumber(tok->fileIndex()), _file(list->file(tok))
{
}
@ -509,3 +509,106 @@ std::string ErrorLogger::toxml(const std::string &str)
}
return xml.str();
}
std::string ErrorLogger::plistHeader(const std::string &version, const std::vector<std::string> &files)
{
std::ostringstream ostr;
ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
<< "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\r\n"
<< "<plist version=\"1.0\">\r\n"
<< "<dict>\r\n"
<< " <key>clang_version</key>\r\n"
<< "<string>cppcheck version " << version << "</string>\r\n"
<< " <key>files</key>\r\n"
<< " <array>\r\n";
for (unsigned int i = 0; i < files.size(); ++i)
ostr << " <string>" << ErrorLogger::toxml(files[i]) << "</string>\r\n";
ostr << " </array>\r\n"
<< " <key>diagnostics</key>\r\n"
<< " <array>\r\n";
return ostr.str();
}
static std::string plistLoc(const char indent[], const ErrorLogger::ErrorMessage::FileLocation &loc)
{
std::ostringstream ostr;
ostr << indent << "<dict>\r\n"
<< indent << ' ' << "<key>line</key><integer>" << loc.line << "</integer>\r\n"
<< indent << ' ' << "<key>col</key><integer>1</integer>\r\n"
<< indent << ' ' << "<key>file</key><integer>" << loc.fileNumber << "</integer>\r\n"
<< indent << "</dict>\r\n";
return ostr.str();
}
std::string ErrorLogger::plistData(const ErrorLogger::ErrorMessage &msg)
{
std::ostringstream plist;
plist << " <dict>\r\n"
<< " <key>path</key>\r\n"
<< " <array>\r\n";
std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator prev = msg._callStack.begin();
for (std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator it = msg._callStack.begin(); it != msg._callStack.end(); ++it) {
if (prev != it) {
plist << " <dict>\r\n"
<< " <key>kind</key><string>control</string>\r\n"
<< " <key>edges</key>\r\n"
<< " <array>\r\n"
<< " <dict>\r\n"
<< " <key>start</key>\r\n"
<< " <array>\r\n"
<< plistLoc(" ", *prev)
<< plistLoc(" ", *prev)
<< " </array>\r\n"
<< " <key>end</key>\r\n"
<< " <array>\r\n"
<< plistLoc(" ", *it)
<< plistLoc(" ", *it)
<< " </array>\r\n"
<< " </dict>\r\n"
<< " </array>\r\n"
<< " </dict>\r\n";
prev = it;
}
std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator next = it;
++next;
const std::string shortMessage = (next == msg._callStack.end() ? msg.shortMessage() : std::string());
const std::string verboseMessage = (next == msg._callStack.end() ? msg.verboseMessage() : std::string());
plist << " <dict>\r\n"
<< " <key>kind</key><string>event</string>\r\n"
<< " <key>location</key>\r\n"
<< plistLoc(" ", *it)
<< " <key>ranges</key>\r\n"
<< " <array>\r\n"
<< " <array>\r\n"
<< plistLoc(" ", *it)
<< plistLoc(" ", *it)
<< " </array>\r\n"
<< " </array>\r\n"
<< " <key>depth</key><integer>0</integer>\r\n"
<< " <key>extended_message</key>\r\n"
<< " <string>" << ErrorLogger::toxml(verboseMessage) << "</string>\r\n"
<< " <key>message</key>\r"
<< " <string>" << ErrorLogger::toxml(shortMessage) << "</string>\r\n"
<< " </dict>\r\n";
}
plist << " </array>\r\n"
<< " <key>description</key><string>" << ErrorLogger::toxml(msg.shortMessage()) << "</string>\r\n"
<< " <key>category</key><string>" << Severity::toString(msg._severity) << "</string>\r\n"
<< " <key>type</key><string>" << ErrorLogger::toxml(msg.shortMessage()) << "</string>\r\n"
<< " <key>check_name</key><string>" << msg._id << "</string>\r\n"
<< " <!-- This hash is experimental and going to change! -->\r\n"
<< " <key>issue_hash_content_of_line_in_context</key><string>" << 0 << "</string>\r\n"
<< " <key>issue_context_kind</key><string></string>\r\n"
<< " <key>issue_context</key><string></string>\r\n"
<< " <key>issue_hash_function_offset</key><string></string>\r\n"
<< " <key>location</key>\r\n"
<< plistLoc(" ", msg._callStack.back())
<< " </dict>\r\n";
return plist.str();
}

View File

@ -24,8 +24,10 @@
#include "config.h"
#include "suppressions.h"
#include <fstream>
#include <list>
#include <string>
#include <vector>
/**
* CWE id (Common Weakness Enumeration)
@ -163,6 +165,8 @@ public:
* should implement.
*/
class CPPCHECKLIB ErrorLogger {
protected:
std::ofstream plistFile;
public:
/**
@ -178,11 +182,11 @@ public:
class CPPCHECKLIB FileLocation {
public:
FileLocation()
: line(0) {
: line(0), fileNumber(0) {
}
FileLocation(const std::string &file, unsigned int aline)
: line(aline), _file(file) {
: line(aline), fileNumber(0), _file(file) {
}
FileLocation(const Token* tok, const TokenList* list);
@ -206,6 +210,7 @@ public:
std::string stringify() const;
unsigned int line;
unsigned int fileNumber;
private:
std::string _file;
@ -283,7 +288,12 @@ public:
};
ErrorLogger() { }
virtual ~ErrorLogger() { }
virtual ~ErrorLogger() {
if (plistFile.is_open()) {
plistFile << ErrorLogger::plistFooter();
plistFile.close();
}
}
/**
* Information about progress is directed here.
@ -335,6 +345,14 @@ public:
* @return The output string containing XML entities
*/
static std::string toxml(const std::string &str);
static std::string plistHeader(const std::string &version, const std::vector<std::string> &files);
static std::string plistData(const ErrorLogger::ErrorMessage &msg);
static const char *plistFooter() {
return " </array>\r\n"
"</dict>\r\n"
"</plist>";
}
};
/// @}

View File

@ -131,10 +131,13 @@ public:
/** @brief Paths used as base for conversion to relative paths. */
std::vector<std::string> basePaths;
/** @brief write XML results (--plist-output=<dir>) */
std::string plistOutput;
/** @brief write XML results (--xml) */
bool xml;
/** @brief XML version (--xmlver=..) */
/** @brief XML version (--xml-version=..) */
int xml_version;
/** @brief How many processes/threads should do checking at the same