Support clang tidy (#2486)

This commit is contained in:
fuzzelhjb 2020-01-30 07:14:17 +01:00 committed by GitHub
parent dcee189146
commit d82da987e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 95 additions and 3 deletions

View File

@ -925,6 +925,8 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
++c; ++c;
if (!settings.quiet) if (!settings.quiet)
reportStatus(c, settings.project.fileSettings.size(), c, settings.project.fileSettings.size()); reportStatus(c, settings.project.fileSettings.size(), c, settings.project.fileSettings.size());
if(settings.clangTidy)
cppcheck.analyseClangTidy(fs);
} }
} }

View File

@ -1352,6 +1352,83 @@ void CppCheck::getErrorMessages()
Preprocessor::getErrorMessages(this, &s); 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 CppCheck::analyseWholeProgram()
{ {
bool errors = false; bool errors = false;

View File

@ -136,6 +136,9 @@ public:
*/ */
bool analyseWholeProgram(); bool analyseWholeProgram();
/** Analyze all files using clang-tidy */
void analyseClangTidy(const ImportProject::FileSettings &fileSettings);
/** analyse whole program use .analyzeinfo files */ /** analyse whole program use .analyzeinfo files */
void analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files); void analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files);

View File

@ -1026,9 +1026,13 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
temp.addons = readXmlStringList(node, "", CppcheckXml::AddonElementName, nullptr); temp.addons = readXmlStringList(node, "", CppcheckXml::AddonElementName, nullptr);
else if (strcmp(node->Name(), CppcheckXml::TagsElementName) == 0) else if (strcmp(node->Name(), CppcheckXml::TagsElementName) == 0)
node->Attribute(CppcheckXml::TagElementName); // FIXME: Write some warning node->Attribute(CppcheckXml::TagElementName); // FIXME: Write some warning
else if (strcmp(node->Name(), CppcheckXml::ToolsElementName) == 0) else if (strcmp(node->Name(), CppcheckXml::ToolsElementName) == 0) {
node->Attribute(CppcheckXml::ToolElementName); // FIXME: Write some warning const std::list<std::string> toolList = readXmlStringList(node, "", CppcheckXml::ToolElementName, nullptr);
else if (strcmp(node->Name(), CppcheckXml::CheckHeadersElementName) == 0) 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); temp.checkHeaders = (strcmp(node->GetText(), "true") == 0);
else if (strcmp(node->Name(), CppcheckXml::CheckUnusedTemplatesElementName) == 0) else if (strcmp(node->Name(), CppcheckXml::CheckUnusedTemplatesElementName) == 0)
temp.checkUnusedTemplates = (strcmp(node->GetText(), "true") == 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->userDefines = temp.userDefines;
settings->userUndefs = temp.userUndefs; settings->userUndefs = temp.userUndefs;
settings->addons = temp.addons; settings->addons = temp.addons;
settings->clangTidy = temp.clangTidy;
for (const std::string &p : paths) for (const std::string &p : paths)
guiProject.pathNames.push_back(p); guiProject.pathNames.push_back(p);
for (const std::string &supp : suppressions) for (const std::string &supp : suppressions)

View File

@ -152,6 +152,7 @@ namespace CppcheckXml {
const char CheckUnusedTemplatesElementName[] = "check-unused-templates"; const char CheckUnusedTemplatesElementName[] = "check-unused-templates";
const char MaxCtuDepthElementName[] = "max-ctu-depth"; const char MaxCtuDepthElementName[] = "max-ctu-depth";
const char CheckUnknownFunctionReturn[] = "check-unknown-function-return-values"; const char CheckUnknownFunctionReturn[] = "check-unknown-function-return-values";
const char ClangTidy[] = "clang-tidy";
const char Name[] = "name"; const char Name[] = "name";
} }

View File

@ -35,6 +35,7 @@ Settings::Settings()
checkHeaders(true), checkHeaders(true),
checkUnusedTemplates(false), checkUnusedTemplates(false),
clang(false), clang(false),
clangTidy(false),
debugSimplified(false), debugSimplified(false),
debugnormal(false), debugnormal(false),
debugwarnings(false), debugwarnings(false),

View File

@ -99,6 +99,9 @@ public:
/** Use Clang */ /** Use Clang */
bool clang; bool clang;
/** Use clang-tidy */
bool clangTidy;
/** @brief include paths excluded from checking the configuration */ /** @brief include paths excluded from checking the configuration */
std::set<std::string> configExcludePaths; std::set<std::string> configExcludePaths;