Add --plist-output argument
This commit is contained in:
parent
3ef2f825c7
commit
6967d68137
|
@ -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
|
// Write results in results.xml
|
||||||
else if (std::strcmp(argv[i], "--xml") == 0)
|
else if (std::strcmp(argv[i], "--xml") == 0)
|
||||||
_settings->xml = true;
|
_settings->xml = true;
|
||||||
|
@ -937,6 +946,8 @@ void CmdLineParser::PrintHelp()
|
||||||
" further assumptions.\n"
|
" further assumptions.\n"
|
||||||
" * unspecified\n"
|
" * unspecified\n"
|
||||||
" Unknown type sizes\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"
|
" -q, --quiet Do not show progress reports.\n"
|
||||||
" -rp, --relative-paths\n"
|
" -rp, --relative-paths\n"
|
||||||
" -rp=<paths>, --relative-paths=<paths>\n"
|
" -rp=<paths>, --relative-paths=<paths>\n"
|
||||||
|
|
|
@ -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);
|
CheckUnusedFunctions checkUnusedFunctions(0,0,0);
|
||||||
|
|
||||||
bool internalErrorFound(false);
|
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);
|
simplecpp::TokenList tokens1(fileStream, files, filename, &outputList);
|
||||||
preprocessor.loadFiles(tokens1, files);
|
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
|
// write dump file xml prolog
|
||||||
std::ofstream fdump;
|
std::ofstream fdump;
|
||||||
if (_settings.dump) {
|
if (_settings.dump) {
|
||||||
|
@ -428,7 +444,6 @@ void CppCheck::internalError(const std::string &filename, const std::string &msg
|
||||||
false);
|
false);
|
||||||
|
|
||||||
_errorLogger.reportErr(errmsg);
|
_errorLogger.reportErr(errmsg);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Report on stdout
|
// Report on stdout
|
||||||
_errorLogger.reportOut(fullmsg);
|
_errorLogger.reportOut(fullmsg);
|
||||||
|
@ -692,6 +707,9 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
|
|
||||||
_errorLogger.reportErr(msg);
|
_errorLogger.reportErr(msg);
|
||||||
analyzerInformation.reportErr(msg, _settings.verbose);
|
analyzerInformation.reportErr(msg, _settings.verbose);
|
||||||
|
if (!_settings.plistOutput.empty() && plistFile.is_open()) {
|
||||||
|
plistFile << ErrorLogger::plistData(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheck::reportOut(const std::string &outmsg)
|
void CppCheck::reportOut(const std::string &outmsg)
|
||||||
|
|
|
@ -449,7 +449,7 @@ std::string ErrorLogger::callStackToString(const std::list<ErrorLogger::ErrorMes
|
||||||
|
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::FileLocation::FileLocation(const Token* tok, const TokenList* list)
|
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();
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,10 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "suppressions.h"
|
#include "suppressions.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CWE id (Common Weakness Enumeration)
|
* CWE id (Common Weakness Enumeration)
|
||||||
|
@ -163,6 +165,8 @@ public:
|
||||||
* should implement.
|
* should implement.
|
||||||
*/
|
*/
|
||||||
class CPPCHECKLIB ErrorLogger {
|
class CPPCHECKLIB ErrorLogger {
|
||||||
|
protected:
|
||||||
|
std::ofstream plistFile;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,11 +182,11 @@ public:
|
||||||
class CPPCHECKLIB FileLocation {
|
class CPPCHECKLIB FileLocation {
|
||||||
public:
|
public:
|
||||||
FileLocation()
|
FileLocation()
|
||||||
: line(0) {
|
: line(0), fileNumber(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLocation(const std::string &file, unsigned int aline)
|
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);
|
FileLocation(const Token* tok, const TokenList* list);
|
||||||
|
@ -206,6 +210,7 @@ public:
|
||||||
std::string stringify() const;
|
std::string stringify() const;
|
||||||
|
|
||||||
unsigned int line;
|
unsigned int line;
|
||||||
|
unsigned int fileNumber;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _file;
|
std::string _file;
|
||||||
|
@ -283,7 +288,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorLogger() { }
|
ErrorLogger() { }
|
||||||
virtual ~ErrorLogger() { }
|
virtual ~ErrorLogger() {
|
||||||
|
if (plistFile.is_open()) {
|
||||||
|
plistFile << ErrorLogger::plistFooter();
|
||||||
|
plistFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about progress is directed here.
|
* Information about progress is directed here.
|
||||||
|
@ -335,6 +345,14 @@ public:
|
||||||
* @return The output string containing XML entities
|
* @return The output string containing XML entities
|
||||||
*/
|
*/
|
||||||
static std::string toxml(const std::string &str);
|
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>";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -131,10 +131,13 @@ public:
|
||||||
/** @brief Paths used as base for conversion to relative paths. */
|
/** @brief Paths used as base for conversion to relative paths. */
|
||||||
std::vector<std::string> basePaths;
|
std::vector<std::string> basePaths;
|
||||||
|
|
||||||
|
/** @brief write XML results (--plist-output=<dir>) */
|
||||||
|
std::string plistOutput;
|
||||||
|
|
||||||
/** @brief write XML results (--xml) */
|
/** @brief write XML results (--xml) */
|
||||||
bool xml;
|
bool xml;
|
||||||
|
|
||||||
/** @brief XML version (--xmlver=..) */
|
/** @brief XML version (--xml-version=..) */
|
||||||
int xml_version;
|
int xml_version;
|
||||||
|
|
||||||
/** @brief How many processes/threads should do checking at the same
|
/** @brief How many processes/threads should do checking at the same
|
||||||
|
|
Loading…
Reference in New Issue