Merge branch 'single-file-check'
This commit is contained in:
commit
ce29342661
|
@ -114,7 +114,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
|
|||
{
|
||||
std::vector<std::string>::iterator iter;
|
||||
for (iter = filenames.begin(); iter != filenames.end(); ++iter)
|
||||
cppcheck->addFile(*iter);
|
||||
_filenames.push_back(*iter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -146,7 +146,11 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
|||
if (_settings._jobs == 1)
|
||||
{
|
||||
// Single process
|
||||
returnValue = cppCheck.check();
|
||||
for (unsigned int c = 0; c < _filenames.size(); c++)
|
||||
{
|
||||
returnValue += cppCheck.check(_filenames[c]);
|
||||
reportStatus(c + 1, _filenames.size());
|
||||
}
|
||||
}
|
||||
else if (!ThreadExecutor::isEnabled())
|
||||
{
|
||||
|
@ -155,9 +159,8 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
|||
else
|
||||
{
|
||||
// Multiple processes
|
||||
const std::vector<std::string> &filenames = cppCheck.filenames();
|
||||
Settings &settings = cppCheck.settings();
|
||||
ThreadExecutor executor(filenames, settings, *this);
|
||||
ThreadExecutor executor(_filenames, settings, *this);
|
||||
returnValue = executor.check();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "errorlogger.h"
|
||||
#include "settings.h"
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
|
||||
class CppCheck;
|
||||
|
||||
|
@ -107,6 +108,11 @@ private:
|
|||
* Has --errorlist been given?
|
||||
*/
|
||||
bool errorlist;
|
||||
|
||||
/**
|
||||
* List of files to check.
|
||||
*/
|
||||
std::vector<std::string> _filenames;
|
||||
};
|
||||
|
||||
#endif // CPPCHECKEXECUTOR_H
|
||||
|
|
|
@ -177,19 +177,19 @@ unsigned int ThreadExecutor::check()
|
|||
|
||||
CppCheck fileChecker(*this, false);
|
||||
fileChecker.settings(_settings);
|
||||
unsigned int resultOfCheck = 0;
|
||||
|
||||
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end())
|
||||
{
|
||||
// File content was given as a string
|
||||
fileChecker.addFile(_filenames[i], _fileContents[ _filenames[i] ]);
|
||||
resultOfCheck = fileChecker.check(_filenames[i], _fileContents[ _filenames[i] ]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read file from a file
|
||||
fileChecker.addFile(_filenames[i]);
|
||||
resultOfCheck = fileChecker.check(_filenames[i]);
|
||||
}
|
||||
|
||||
unsigned int resultOfCheck = fileChecker.check();
|
||||
std::ostringstream oss;
|
||||
oss << resultOfCheck;
|
||||
writeToPipe('3', oss.str());
|
||||
|
|
|
@ -50,9 +50,7 @@ void CheckThread::run()
|
|||
while (!file.isEmpty() && mState == Running)
|
||||
{
|
||||
qDebug() << "Checking file" << file;
|
||||
mCppcheck.addFile(file.toStdString());
|
||||
mCppcheck.check();
|
||||
mCppcheck.clearFiles();
|
||||
mCppcheck.check(file.toStdString());
|
||||
emit FileChecked(file);
|
||||
|
||||
if (mState == Running)
|
||||
|
|
250
lib/cppcheck.cpp
250
lib/cppcheck.cpp
|
@ -54,155 +54,138 @@ void CppCheck::settings(const Settings ¤tSettings)
|
|||
_settings = currentSettings;
|
||||
}
|
||||
|
||||
void CppCheck::addFile(const std::string &filepath)
|
||||
{
|
||||
_filenames.push_back(Path::fromNativeSeparators(filepath));
|
||||
}
|
||||
|
||||
void CppCheck::addFile(const std::string &path, const std::string &content)
|
||||
{
|
||||
_filenames.push_back(Path::fromNativeSeparators(path));
|
||||
_fileContents[ path ] = content;
|
||||
}
|
||||
|
||||
void CppCheck::clearFiles()
|
||||
{
|
||||
_filenames.clear();
|
||||
_fileContents.clear();
|
||||
}
|
||||
|
||||
const char * CppCheck::version()
|
||||
{
|
||||
return "1.48";
|
||||
}
|
||||
|
||||
unsigned int CppCheck::check()
|
||||
unsigned int CppCheck::check(const std::string &path)
|
||||
{
|
||||
_filename = path;
|
||||
return processFile();
|
||||
}
|
||||
|
||||
unsigned int CppCheck::check(const std::string &path, const std::string &content)
|
||||
{
|
||||
_filename = path;
|
||||
_fileContent = content;
|
||||
const unsigned int retval = processFile();
|
||||
_fileContent.clear();
|
||||
return retval;
|
||||
}
|
||||
|
||||
unsigned int CppCheck::processFile()
|
||||
{
|
||||
exitcode = 0;
|
||||
|
||||
std::sort(_filenames.begin(), _filenames.end());
|
||||
|
||||
// TODO: Should this be moved out to its own function so all the files can be
|
||||
// analysed before any files are checked?
|
||||
if (_settings.test_2_pass && _settings._jobs == 1)
|
||||
{
|
||||
for (unsigned int c = 0; c < _filenames.size(); c++)
|
||||
{
|
||||
const std::string fname = _filenames[c];
|
||||
if (_settings.terminated())
|
||||
break;
|
||||
const std::string printname = Path::toNativeSeparators(_filename);
|
||||
reportOut("Analysing " + printname + "...");
|
||||
|
||||
std::string fixedname = Path::toNativeSeparators(fname);
|
||||
reportOut("Analysing " + fixedname + "..");
|
||||
|
||||
std::ifstream f(fname.c_str());
|
||||
analyseFile(f, fname);
|
||||
}
|
||||
std::ifstream f(_filename.c_str());
|
||||
analyseFile(f, _filename);
|
||||
}
|
||||
|
||||
for (unsigned int c = 0; c < _filenames.size(); c++)
|
||||
_errout.str("");
|
||||
|
||||
if (_settings.terminated())
|
||||
return exitcode;
|
||||
|
||||
if (_settings._errorsOnly == false)
|
||||
{
|
||||
_errout.str("");
|
||||
const std::string fname = _filenames[c];
|
||||
|
||||
if (_settings.terminated())
|
||||
break;
|
||||
|
||||
if (_settings._errorsOnly == false)
|
||||
{
|
||||
std::string fixedpath(fname);
|
||||
fixedpath = Path::simplifyPath(fixedpath.c_str());
|
||||
fixedpath = Path::toNativeSeparators(fixedpath);
|
||||
_errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("..."));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Preprocessor preprocessor(&_settings, this);
|
||||
std::list<std::string> configurations;
|
||||
std::string filedata = "";
|
||||
|
||||
if ((!_fileContents.empty()) && (_fileContents.find(_filenames[c]) != _fileContents.end()))
|
||||
{
|
||||
// File content was given as a string
|
||||
std::istringstream iss(_fileContents[ _filenames[c] ]);
|
||||
preprocessor.preprocess(iss, filedata, configurations, fname, _settings._includePaths);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only file name was given, read the content from file
|
||||
std::ifstream fin(fname.c_str());
|
||||
Timer t("Preprocessor::preprocess", _settings._showtime, &S_timerResults);
|
||||
preprocessor.preprocess(fin, filedata, configurations, fname, _settings._includePaths);
|
||||
}
|
||||
|
||||
_settings.ifcfg = bool(configurations.size() > 1);
|
||||
|
||||
if (!_settings.userDefines.empty())
|
||||
{
|
||||
configurations.clear();
|
||||
configurations.push_back(_settings.userDefines);
|
||||
}
|
||||
|
||||
int checkCount = 0;
|
||||
for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it)
|
||||
{
|
||||
// Check only 12 first configurations, after that bail out, unless --force
|
||||
// was used.
|
||||
if (!_settings._force && checkCount > 11)
|
||||
{
|
||||
const std::string fixedpath = Path::toNativeSeparators(fname);
|
||||
ErrorLogger::ErrorMessage::FileLocation location;
|
||||
location.setfile(fixedpath);
|
||||
std::list<ErrorLogger::ErrorMessage::FileLocation> loclist;
|
||||
loclist.push_back(location);
|
||||
const std::string msg("Interrupted checking because of too many #ifdef configurations.\n"
|
||||
"The checking of the file was interrupted because there were too many "
|
||||
"#ifdef configurations. Checking of all #ifdef configurations can be forced "
|
||||
"by --force command line option or from GUI preferences. However that may "
|
||||
"increase the checking time.");
|
||||
ErrorLogger::ErrorMessage errmsg(loclist,
|
||||
Severity::information,
|
||||
msg,
|
||||
"toomanyconfigs",
|
||||
false);
|
||||
_errorLogger.reportErr(errmsg);
|
||||
break;
|
||||
}
|
||||
|
||||
cfg = *it;
|
||||
Timer t("Preprocessor::getcode", _settings._showtime, &S_timerResults);
|
||||
const std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it, fname, &_settings, &_errorLogger);
|
||||
t.Stop();
|
||||
|
||||
// If only errors are printed, print filename after the check
|
||||
if (_settings._errorsOnly == false && it != configurations.begin())
|
||||
{
|
||||
std::string fixedpath = Path::simplifyPath(fname.c_str());
|
||||
fixedpath = Path::toNativeSeparators(fixedpath);
|
||||
_errorLogger.reportOut(std::string("Checking ") + fixedpath + ": " + cfg + std::string("..."));
|
||||
}
|
||||
|
||||
std::string appendCode = _settings.append();
|
||||
if (!appendCode.empty())
|
||||
Preprocessor::preprocessWhitespaces(appendCode);
|
||||
|
||||
checkFile(codeWithoutCfg + appendCode, _filenames[c].c_str());
|
||||
++checkCount;
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error &e)
|
||||
{
|
||||
// Exception was thrown when checking this file..
|
||||
const std::string fixedpath = Path::toNativeSeparators(fname);
|
||||
_errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what());
|
||||
}
|
||||
|
||||
reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(fname));
|
||||
|
||||
_errorLogger.reportStatus(c + 1, (unsigned int)_filenames.size());
|
||||
std::string fixedpath(_filename);
|
||||
fixedpath = Path::simplifyPath(fixedpath.c_str());
|
||||
fixedpath = Path::toNativeSeparators(fixedpath);
|
||||
_errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("..."));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Preprocessor preprocessor(&_settings, this);
|
||||
std::list<std::string> configurations;
|
||||
std::string filedata = "";
|
||||
|
||||
if (!_fileContent.empty())
|
||||
{
|
||||
// File content was given as a string
|
||||
std::istringstream iss(_fileContent);
|
||||
preprocessor.preprocess(iss, filedata, configurations, _filename, _settings._includePaths);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only file name was given, read the content from file
|
||||
std::ifstream fin(_filename.c_str());
|
||||
Timer t("Preprocessor::preprocess", _settings._showtime, &S_timerResults);
|
||||
preprocessor.preprocess(fin, filedata, configurations, _filename, _settings._includePaths);
|
||||
}
|
||||
|
||||
_settings.ifcfg = bool(configurations.size() > 1);
|
||||
|
||||
if (!_settings.userDefines.empty())
|
||||
{
|
||||
configurations.clear();
|
||||
configurations.push_back(_settings.userDefines);
|
||||
}
|
||||
|
||||
int checkCount = 0;
|
||||
for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it)
|
||||
{
|
||||
// Check only 12 first configurations, after that bail out, unless --force
|
||||
// was used.
|
||||
if (!_settings._force && checkCount > 11)
|
||||
{
|
||||
const std::string fixedpath = Path::toNativeSeparators(_filename);
|
||||
ErrorLogger::ErrorMessage::FileLocation location;
|
||||
location.setfile(fixedpath);
|
||||
std::list<ErrorLogger::ErrorMessage::FileLocation> loclist;
|
||||
loclist.push_back(location);
|
||||
const std::string msg("Interrupted checking because of too many #ifdef configurations.\n"
|
||||
"The checking of the file was interrupted because there were too many "
|
||||
"#ifdef configurations. Checking of all #ifdef configurations can be forced "
|
||||
"by --force command line option or from GUI preferences. However that may "
|
||||
"increase the checking time.");
|
||||
ErrorLogger::ErrorMessage errmsg(loclist,
|
||||
Severity::information,
|
||||
msg,
|
||||
"toomanyconfigs",
|
||||
false);
|
||||
_errorLogger.reportErr(errmsg);
|
||||
break;
|
||||
}
|
||||
|
||||
cfg = *it;
|
||||
Timer t("Preprocessor::getcode", _settings._showtime, &S_timerResults);
|
||||
const std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it, _filename, &_settings, &_errorLogger);
|
||||
t.Stop();
|
||||
|
||||
// If only errors are printed, print filename after the check
|
||||
if (_settings._errorsOnly == false && it != configurations.begin())
|
||||
{
|
||||
std::string fixedpath = Path::simplifyPath(_filename.c_str());
|
||||
fixedpath = Path::toNativeSeparators(fixedpath);
|
||||
_errorLogger.reportOut(std::string("Checking ") + fixedpath + ": " + cfg + std::string("..."));
|
||||
}
|
||||
|
||||
std::string appendCode = _settings.append();
|
||||
if (!appendCode.empty())
|
||||
Preprocessor::preprocessWhitespaces(appendCode);
|
||||
|
||||
checkFile(codeWithoutCfg + appendCode, _filename.c_str());
|
||||
++checkCount;
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error &e)
|
||||
{
|
||||
// Exception was thrown when checking this file..
|
||||
const std::string fixedpath = Path::toNativeSeparators(_filename);
|
||||
_errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what());
|
||||
}
|
||||
|
||||
reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions(_filename));
|
||||
|
||||
// This generates false positives - especially for libraries
|
||||
const bool verbose_orig = _settings._verbose;
|
||||
_settings._verbose = false;
|
||||
|
@ -445,11 +428,6 @@ void CppCheck::reportOut(const std::string &outmsg)
|
|||
_errorLogger.reportOut(outmsg);
|
||||
}
|
||||
|
||||
const std::vector<std::string> &CppCheck::filenames() const
|
||||
{
|
||||
return _filenames;
|
||||
}
|
||||
|
||||
void CppCheck::reportProgress(const std::string &filename, const char stage[], const unsigned int value)
|
||||
{
|
||||
_errorLogger.reportProgress(filename, stage, value);
|
||||
|
|
|
@ -55,7 +55,29 @@ public:
|
|||
* parseFromArgs() or settings() and addFile() before calling this.
|
||||
* @return amount of errors found or 0 if none were found.
|
||||
*/
|
||||
unsigned int check();
|
||||
|
||||
/**
|
||||
* @brief Check the file.
|
||||
* This function checks one given file for errors.
|
||||
* @param path Path to the file to check.
|
||||
* @return amount of errors found or 0 if none were found.
|
||||
* @note You must set settings before calling this function (by calling
|
||||
* settings()).
|
||||
*/
|
||||
unsigned int check(const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Check the file.
|
||||
* This function checks one "virtual" file. The file is not read from
|
||||
* the disk but the content is given in @p content. In errors the @p path
|
||||
* is used as a filename.
|
||||
* @param path Path to the file to check.
|
||||
* @param content File content as a string.
|
||||
* @return amount of errors found or 0 if none were found.
|
||||
* @note You must set settings before calling this function (by calling
|
||||
* settings()).
|
||||
*/
|
||||
unsigned int check(const std::string &path, const std::string &content);
|
||||
|
||||
/**
|
||||
* @brief Adjust the settings before doing the check. E.g. show only
|
||||
|
@ -71,37 +93,12 @@ public:
|
|||
*/
|
||||
Settings &settings();
|
||||
|
||||
/**
|
||||
* @brief Add new file to be checked.
|
||||
*
|
||||
* @param filepath Relative or absolute path to the file to be checked,
|
||||
* e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp)
|
||||
* should be added to the list. Include files are gathered automatically.
|
||||
*/
|
||||
void addFile(const std::string &filepath);
|
||||
|
||||
/**
|
||||
* @brief Add new unreal file to be checked.
|
||||
*
|
||||
* @param path File name (used for error reporting).
|
||||
* @param content If the file would be a real file, this should be
|
||||
* the content of the file.
|
||||
*/
|
||||
void addFile(const std::string &path, const std::string &content);
|
||||
|
||||
/**
|
||||
* @brief Remove all files added with addFile() and parseFromArgs().
|
||||
*/
|
||||
void clearFiles();
|
||||
|
||||
/**
|
||||
* @brief Returns current version number as a string.
|
||||
* @return version, e.g. "1.38"
|
||||
*/
|
||||
static const char * version();
|
||||
|
||||
const std::vector<std::string> &filenames() const;
|
||||
|
||||
virtual void reportStatus(unsigned int index, unsigned int max);
|
||||
|
||||
/**
|
||||
|
@ -124,6 +121,10 @@ public:
|
|||
void analyseFile(std::istream &f, const std::string &filename);
|
||||
|
||||
private:
|
||||
|
||||
/** @brief Process one file. */
|
||||
unsigned int processFile();
|
||||
|
||||
/** @brief Check file */
|
||||
void checkFile(const std::string &code, const char FileName[]);
|
||||
|
||||
|
@ -148,13 +149,11 @@ private:
|
|||
std::ostringstream _errout;
|
||||
Settings _settings;
|
||||
bool _useGlobalSuppressions;
|
||||
std::vector<std::string> _filenames;
|
||||
std::string _filename;
|
||||
std::string _fileContent;
|
||||
|
||||
void reportProgress(const std::string &filename, const char stage[], const unsigned int value);
|
||||
|
||||
/** @brief Key is file name, and value is the content of the file */
|
||||
std::map<std::string, std::string> _fileContents;
|
||||
|
||||
CheckUnusedFunctions _checkUnusedFunctions;
|
||||
ErrorLogger &_errorLogger;
|
||||
|
||||
|
|
|
@ -55,8 +55,7 @@ private:
|
|||
|
||||
CppCheck cppCheck(*this, true);
|
||||
cppCheck.settings(settings);
|
||||
cppCheck.addFile("test.cpp", code);
|
||||
cppCheck.check();
|
||||
cppCheck.check("test.cpp", code);
|
||||
|
||||
reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
|
||||
}
|
||||
|
@ -105,8 +104,7 @@ private:
|
|||
CppCheck cppCheck(*this, true);
|
||||
cppCheck.settings(settings);
|
||||
for (int i = 0; names[i] != NULL; ++i)
|
||||
cppCheck.addFile(names[i], codes[i]);
|
||||
cppCheck.check();
|
||||
cppCheck.check(names[i], codes[i]);
|
||||
|
||||
reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue