Cppcheck build dir: Better handling when --project is used

This commit is contained in:
Daniel Marjamäki 2016-12-08 22:46:44 +01:00
parent 30bee06cd2
commit e9d950d4f5
6 changed files with 72 additions and 24 deletions

View File

@ -17,6 +17,7 @@
*/
#include "cppcheckexecutor.h"
#include "analyzerinfo.h"
#include "cmdlineparser.h"
#include "cppcheck.h"
#include "filelister.h"
@ -803,11 +804,10 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
}
if (!settings.buildDir.empty()) {
const std::string filename(settings.buildDir + "/files.txt");
std::ofstream fout(filename.c_str());
for (std::map<std::string, std::size_t>::const_iterator f = _files.begin(); f != _files.end(); ++f) {
fout << f->first << '\n';
}
std::list<std::string> fileNames;
for (std::map<std::string, std::size_t>::const_iterator i = _files.begin(); i != _files.end(); ++i)
fileNames.push_back(i->first);
AnalyzerInformation::writeFilesTxt(settings.buildDir, fileNames, settings.project.fileSettings);
}
unsigned int returnValue = 0;

View File

@ -26,6 +26,39 @@ AnalyzerInformation::~AnalyzerInformation()
close();
}
static std::string getFilename(const std::string &fullpath) {
std::string afile(fullpath);
std::string::size_type pos1 = fullpath.find_last_of("/\\");
pos1 = (pos1 == std::string::npos) ? 0U : (pos1 + 1U);
std::string::size_type pos2 = fullpath.rfind('.');
if (pos2 < pos1)
pos2 = std::string::npos;
if (pos2 != std::string::npos)
pos2 = pos2 - pos1;
return fullpath.substr(pos1,pos2);
}
void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::list<std::string> &sourcefiles, const std::list<ImportProject::FileSettings> &fileSettings)
{
std::map<std::string, unsigned int> fileCount;
const std::string filesTxt(buildDir + "/files.txt");
std::ofstream fout(filesTxt.c_str());
for (std::list<std::string>::const_iterator f = sourcefiles.begin(); f != sourcefiles.end(); ++f) {
const std::string afile = getFilename(*f);
if (fileCount.find(afile) == fileCount.end())
fileCount[afile] = 0;
fout << afile << ".a" << (++fileCount[afile]) << "::" << Path::fromNativeSeparators(*f) << '\n';
}
for (std::list<ImportProject::FileSettings>::const_iterator fs = fileSettings.begin(); fs != fileSettings.end(); ++fs) {
const std::string afile = getFilename(fs->filename);
if (fileCount.find(afile) == fileCount.end())
fileCount[afile] = 0;
fout << afile << ".a" << (++fileCount[afile]) << ":" << fs->cfg << ":" << Path::fromNativeSeparators(fs->filename) << std::endl;
}
}
void AnalyzerInformation::close()
{
analyzerInfoFile.clear();
@ -58,21 +91,22 @@ static bool skipAnalysis(const std::string &analyzerInfoFile, unsigned long long
return true;
}
std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile)
std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg)
{
const std::string files(buildDir + "/files.txt");
std::ifstream fin(files.c_str());
if (fin.is_open()) {
int id = 1;
std::string line;
const std::string endsWith(':' + cfg + ':' + sourcefile);
while (std::getline(fin,line)) {
if (line == sourcefile) {
if (line.size() <= endsWith.size() + 2U)
continue;
if (line.compare(line.size()-endsWith.size(), endsWith.size(), endsWith) != 0)
continue;
std::ostringstream ostr;
ostr << buildDir << '/' << id << ".analyzeinfo";
ostr << buildDir << '/' << line.substr(0,line.find(':'));
return ostr.str();
}
id++;
}
}
std::string filename = Path::fromNativeSeparators(buildDir);
@ -87,13 +121,13 @@ std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir
return filename;
}
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, unsigned long long checksum, std::list<ErrorLogger::ErrorMessage> *errors)
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, unsigned long long checksum, std::list<ErrorLogger::ErrorMessage> *errors)
{
if (buildDir.empty() || sourcefile.empty())
return true;
close();
analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile);
analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg);
if (skipAnalysis(analyzerInfoFile, checksum, errors))
return false;

View File

@ -23,6 +23,8 @@
#include "config.h"
#include "errorlogger.h"
#include "importproject.h"
#include <list>
#include <string>
#include <fstream>
@ -47,12 +49,14 @@ class CPPCHECKLIB AnalyzerInformation {
public:
~AnalyzerInformation();
static void writeFilesTxt(const std::string &buildDir, const std::list<std::string> &sourcefiles, const std::list<ImportProject::FileSettings> &fileSettings);
/** Close current TU.analyzerinfo file */
void close();
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, unsigned long long checksum, std::list<ErrorLogger::ErrorMessage> *errors);
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, unsigned long long checksum, std::list<ErrorLogger::ErrorMessage> *errors);
void reportErr(const ErrorLogger::ErrorMessage &msg, bool verbose);
void setFileInfo(const std::string &check, const std::string &fileInfo);
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile);
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg);
private:
std::ofstream fout;
std::string analyzerInfoFile;

View File

@ -312,14 +312,23 @@ namespace {
};
}
void CheckUnusedFunctions::analyseWholeProgram(ErrorLogger * const errorLogger, const std::string &buildDir, const std::map<std::string, std::size_t> &files)
void CheckUnusedFunctions::analyseWholeProgram(ErrorLogger * const errorLogger, const std::string &buildDir)
{
std::map<std::string, Location> decls;
std::set<std::string> calls;
for (std::map<std::string, std::size_t>::const_iterator it = files.begin(); it != files.end(); ++it) {
const std::string &sourcefile = it->first;
const std::string xmlfile = AnalyzerInformation::getAnalyzerInfoFile(buildDir, sourcefile);
const std::string filesTxt(buildDir + "/files.txt");
std::ifstream fin(filesTxt.c_str());
std::string filesTxtLine;
while (std::getline(fin, filesTxtLine)) {
const std::string::size_type firstColon = filesTxtLine.find(':');
if (firstColon == std::string::npos)
continue;
const std::string::size_type lastColon = filesTxtLine.rfind(':');
if (firstColon == lastColon)
continue;
const std::string xmlfile = filesTxtLine.substr(0,firstColon);
const std::string sourcefile = filesTxtLine.substr(lastColon+1);
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.LoadFile(xmlfile.c_str());

View File

@ -62,7 +62,7 @@ public:
std::string analyzerInfo() const;
/** @brief Combine and analyze all analyzerInfos for all TUs */
static void analyseWholeProgram(ErrorLogger * const errorLogger, const std::string &buildDir, const std::map<std::string, std::size_t> &files);
static void analyseWholeProgram(ErrorLogger * const errorLogger, const std::string &buildDir);
private:

View File

@ -153,7 +153,7 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin
// Calculate checksum so it can be compared with old checksum / future checksums
const unsigned int checksum = preprocessor.calculateChecksum(tokens1, toolinfo);
std::list<ErrorLogger::ErrorMessage> errors;
if (!analyzerInformation.analyzeFile(_settings.buildDir, filename, checksum, &errors)) {
if (!analyzerInformation.analyzeFile(_settings.buildDir, filename, cfgname, checksum, &errors)) {
while (!errors.empty()) {
reportErr(errors.front());
errors.pop_front();
@ -737,10 +737,11 @@ void CppCheck::analyseWholeProgram()
void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<std::string, std::size_t> &files)
{
(void)files;
if (buildDir.empty())
return;
if (_settings.isEnabled("unusedFunction"))
CheckUnusedFunctions::analyseWholeProgram(this, buildDir, files);
CheckUnusedFunctions::analyseWholeProgram(this, buildDir);
}
bool CppCheck::isUnusedFunctionCheckEnabled() const