Support clang tidy (#2486)
This commit is contained in:
parent
dcee189146
commit
d82da987e5
|
@ -925,6 +925,8 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
|
|||
++c;
|
||||
if (!settings.quiet)
|
||||
reportStatus(c, settings.project.fileSettings.size(), c, settings.project.fileSettings.size());
|
||||
if(settings.clangTidy)
|
||||
cppcheck.analyseClangTidy(fs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1352,6 +1352,83 @@ void CppCheck::getErrorMessages()
|
|||
Preprocessor::getErrorMessages(this, &s);
|
||||
}
|
||||
|
||||
void CppCheck::analyseClangTidy(const ImportProject::FileSettings &fileSettings )
|
||||
{
|
||||
std::string allIncludes = "";
|
||||
std::string allDefines = "-D"+fileSettings.defines;
|
||||
for (const std::string &inc : fileSettings.includePaths) {
|
||||
allIncludes = allIncludes + "-I\"" + inc + "\" ";
|
||||
}
|
||||
|
||||
std::string::size_type pos = 0u;
|
||||
while ((pos = allDefines.find(";", pos)) != std::string::npos)
|
||||
{
|
||||
allDefines.replace(pos, 1, " -D");
|
||||
pos += 3;
|
||||
}
|
||||
|
||||
const std::string cmd = "clang-tidy -quiet -checks=*,-clang-analyzer-*,-llvm* \"" + fileSettings.filename + "\" -- " + allIncludes + allDefines;
|
||||
std::pair<bool, std::string> result = executeCommand(cmd);
|
||||
if (!result.first) {
|
||||
std::cerr << "Failed to execute '" + cmd + "'" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// parse output and create error messages
|
||||
std::istringstream istr(result.second);
|
||||
std::string line;
|
||||
|
||||
if (!mSettings.buildDir.empty())
|
||||
{
|
||||
const std::string analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, fileSettings.filename, "");
|
||||
std::ofstream fcmd(analyzerInfoFile + ".clang-tidy-cmd");
|
||||
fcmd << istr.str();
|
||||
}
|
||||
|
||||
while (std::getline(istr, line)) {
|
||||
if (line.find("error") == std::string::npos && line.find("warning") == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::size_t endColumnPos = line.find(": error:");
|
||||
if (endColumnPos == std::string::npos) {
|
||||
endColumnPos = line.find(": warning:");
|
||||
}
|
||||
|
||||
const std::size_t endLinePos = line.rfind(":", endColumnPos-1);
|
||||
const std::size_t endNamePos = line.rfind(":", endLinePos - 1);
|
||||
const std::size_t endMsgTypePos = line.find(':', endColumnPos + 2);
|
||||
const std::size_t endErrorPos = line.rfind('[', std::string::npos);
|
||||
|
||||
const std::string lineNumString = line.substr(endNamePos + 1, endLinePos - endNamePos - 1);
|
||||
const std::string columnNumString = line.substr(endLinePos + 1, endColumnPos - endLinePos - 1);
|
||||
const std::string errorTypeString = line.substr(endColumnPos + 1, endMsgTypePos - endColumnPos - 1);
|
||||
const std::string messageString = line.substr(endMsgTypePos + 1, endErrorPos - endMsgTypePos - 1);
|
||||
const std::string errorString = line.substr(endErrorPos, line.length());
|
||||
|
||||
std::string fixedpath = Path::simplifyPath(line.substr(0, endNamePos));
|
||||
const int64_t lineNumber = std::atol(lineNumString.c_str());
|
||||
const int64_t column = std::atol(columnNumString.c_str());
|
||||
fixedpath = Path::toNativeSeparators(fixedpath);
|
||||
|
||||
ErrorLogger::ErrorMessage errmsg;
|
||||
errmsg.callStack.emplace_back(ErrorLogger::ErrorMessage::FileLocation(fixedpath, lineNumber, column));
|
||||
|
||||
errmsg.id = "clang-tidy-" + errorString.substr(1, errorString.length() - 2);
|
||||
if (errmsg.id.find("performance") != std::string::npos)
|
||||
errmsg.severity = Severity::SeverityType::performance;
|
||||
else if (errmsg.id.find("portability") != std::string::npos)
|
||||
errmsg.severity = Severity::SeverityType::portability;
|
||||
else if (errmsg.id.find("cert") != std::string::npos || errmsg.id.find("misc") != std::string::npos || errmsg.id.find("unused") != std::string::npos)
|
||||
errmsg.severity = Severity::SeverityType::warning;
|
||||
else
|
||||
errmsg.severity = Severity::SeverityType::style;
|
||||
|
||||
errmsg.file0 = fixedpath;
|
||||
errmsg.setmsg(messageString);
|
||||
reportErr(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
bool CppCheck::analyseWholeProgram()
|
||||
{
|
||||
bool errors = false;
|
||||
|
|
|
@ -136,6 +136,9 @@ public:
|
|||
*/
|
||||
bool analyseWholeProgram();
|
||||
|
||||
/** Analyze all files using clang-tidy */
|
||||
void analyseClangTidy(const ImportProject::FileSettings &fileSettings);
|
||||
|
||||
/** analyse whole program use .analyzeinfo files */
|
||||
void analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files);
|
||||
|
||||
|
|
|
@ -1026,9 +1026,13 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
|
|||
temp.addons = readXmlStringList(node, "", CppcheckXml::AddonElementName, nullptr);
|
||||
else if (strcmp(node->Name(), CppcheckXml::TagsElementName) == 0)
|
||||
node->Attribute(CppcheckXml::TagElementName); // FIXME: Write some warning
|
||||
else if (strcmp(node->Name(), CppcheckXml::ToolsElementName) == 0)
|
||||
node->Attribute(CppcheckXml::ToolElementName); // FIXME: Write some warning
|
||||
else if (strcmp(node->Name(), CppcheckXml::CheckHeadersElementName) == 0)
|
||||
else if (strcmp(node->Name(), CppcheckXml::ToolsElementName) == 0) {
|
||||
const std::list<std::string> toolList = readXmlStringList(node, "", CppcheckXml::ToolElementName, nullptr);
|
||||
for (const std::string &toolName : toolList) {
|
||||
if (toolName == std::string(CppcheckXml::ClangTidy))
|
||||
temp.clangTidy = true;
|
||||
}
|
||||
} else if (strcmp(node->Name(), CppcheckXml::CheckHeadersElementName) == 0)
|
||||
temp.checkHeaders = (strcmp(node->GetText(), "true") == 0);
|
||||
else if (strcmp(node->Name(), CppcheckXml::CheckUnusedTemplatesElementName) == 0)
|
||||
temp.checkUnusedTemplates = (strcmp(node->GetText(), "true") == 0);
|
||||
|
@ -1059,6 +1063,7 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
|
|||
settings->userDefines = temp.userDefines;
|
||||
settings->userUndefs = temp.userUndefs;
|
||||
settings->addons = temp.addons;
|
||||
settings->clangTidy = temp.clangTidy;
|
||||
for (const std::string &p : paths)
|
||||
guiProject.pathNames.push_back(p);
|
||||
for (const std::string &supp : suppressions)
|
||||
|
|
|
@ -152,6 +152,7 @@ namespace CppcheckXml {
|
|||
const char CheckUnusedTemplatesElementName[] = "check-unused-templates";
|
||||
const char MaxCtuDepthElementName[] = "max-ctu-depth";
|
||||
const char CheckUnknownFunctionReturn[] = "check-unknown-function-return-values";
|
||||
const char ClangTidy[] = "clang-tidy";
|
||||
const char Name[] = "name";
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ Settings::Settings()
|
|||
checkHeaders(true),
|
||||
checkUnusedTemplates(false),
|
||||
clang(false),
|
||||
clangTidy(false),
|
||||
debugSimplified(false),
|
||||
debugnormal(false),
|
||||
debugwarnings(false),
|
||||
|
|
|
@ -99,6 +99,9 @@ public:
|
|||
/** Use Clang */
|
||||
bool clang;
|
||||
|
||||
/** Use clang-tidy */
|
||||
bool clangTidy;
|
||||
|
||||
/** @brief include paths excluded from checking the configuration */
|
||||
std::set<std::string> configExcludePaths;
|
||||
|
||||
|
|
Loading…
Reference in New Issue