Merge branch 'single-file-check'

This commit is contained in:
Kimmo Varis 2011-04-25 15:31:46 +03:00
commit ce29342661
7 changed files with 162 additions and 180 deletions

View File

@ -114,7 +114,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
{ {
std::vector<std::string>::iterator iter; std::vector<std::string>::iterator iter;
for (iter = filenames.begin(); iter != filenames.end(); ++iter) for (iter = filenames.begin(); iter != filenames.end(); ++iter)
cppcheck->addFile(*iter); _filenames.push_back(*iter);
return true; return true;
} }
@ -146,7 +146,11 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
if (_settings._jobs == 1) if (_settings._jobs == 1)
{ {
// Single process // 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()) else if (!ThreadExecutor::isEnabled())
{ {
@ -155,9 +159,8 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
else else
{ {
// Multiple processes // Multiple processes
const std::vector<std::string> &filenames = cppCheck.filenames();
Settings &settings = cppCheck.settings(); Settings &settings = cppCheck.settings();
ThreadExecutor executor(filenames, settings, *this); ThreadExecutor executor(_filenames, settings, *this);
returnValue = executor.check(); returnValue = executor.check();
} }

View File

@ -22,6 +22,7 @@
#include "errorlogger.h" #include "errorlogger.h"
#include "settings.h" #include "settings.h"
#include <ctime> #include <ctime>
#include <vector>
class CppCheck; class CppCheck;
@ -107,6 +108,11 @@ private:
* Has --errorlist been given? * Has --errorlist been given?
*/ */
bool errorlist; bool errorlist;
/**
* List of files to check.
*/
std::vector<std::string> _filenames;
}; };
#endif // CPPCHECKEXECUTOR_H #endif // CPPCHECKEXECUTOR_H

View File

@ -177,19 +177,19 @@ unsigned int ThreadExecutor::check()
CppCheck fileChecker(*this, false); CppCheck fileChecker(*this, false);
fileChecker.settings(_settings); fileChecker.settings(_settings);
unsigned int resultOfCheck = 0;
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end()) if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end())
{ {
// File content was given as a string // File content was given as a string
fileChecker.addFile(_filenames[i], _fileContents[ _filenames[i] ]); resultOfCheck = fileChecker.check(_filenames[i], _fileContents[ _filenames[i] ]);
} }
else else
{ {
// Read file from a file // Read file from a file
fileChecker.addFile(_filenames[i]); resultOfCheck = fileChecker.check(_filenames[i]);
} }
unsigned int resultOfCheck = fileChecker.check();
std::ostringstream oss; std::ostringstream oss;
oss << resultOfCheck; oss << resultOfCheck;
writeToPipe('3', oss.str()); writeToPipe('3', oss.str());

View File

@ -50,9 +50,7 @@ void CheckThread::run()
while (!file.isEmpty() && mState == Running) while (!file.isEmpty() && mState == Running)
{ {
qDebug() << "Checking file" << file; qDebug() << "Checking file" << file;
mCppcheck.addFile(file.toStdString()); mCppcheck.check(file.toStdString());
mCppcheck.check();
mCppcheck.clearFiles();
emit FileChecked(file); emit FileChecked(file);
if (mState == Running) if (mState == Running)

View File

@ -54,155 +54,138 @@ void CppCheck::settings(const Settings &currentSettings)
_settings = currentSettings; _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() const char * CppCheck::version()
{ {
return "1.48"; 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; exitcode = 0;
std::sort(_filenames.begin(), _filenames.end());
// TODO: Should this be moved out to its own function so all the files can be // TODO: Should this be moved out to its own function so all the files can be
// analysed before any files are checked? // analysed before any files are checked?
if (_settings.test_2_pass && _settings._jobs == 1) if (_settings.test_2_pass && _settings._jobs == 1)
{ {
for (unsigned int c = 0; c < _filenames.size(); c++) const std::string printname = Path::toNativeSeparators(_filename);
{ reportOut("Analysing " + printname + "...");
const std::string fname = _filenames[c];
if (_settings.terminated())
break;
std::string fixedname = Path::toNativeSeparators(fname); std::ifstream f(_filename.c_str());
reportOut("Analysing " + fixedname + ".."); analyseFile(f, _filename);
std::ifstream f(fname.c_str());
analyseFile(f, fname);
}
} }
for (unsigned int c = 0; c < _filenames.size(); c++) _errout.str("");
if (_settings.terminated())
return exitcode;
if (_settings._errorsOnly == false)
{ {
_errout.str(""); std::string fixedpath(_filename);
const std::string fname = _filenames[c]; fixedpath = Path::simplifyPath(fixedpath.c_str());
fixedpath = Path::toNativeSeparators(fixedpath);
if (_settings.terminated()) _errorLogger.reportOut(std::string("Checking ") + fixedpath + std::string("..."));
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());
} }
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 // This generates false positives - especially for libraries
const bool verbose_orig = _settings._verbose; const bool verbose_orig = _settings._verbose;
_settings._verbose = false; _settings._verbose = false;
@ -445,11 +428,6 @@ void CppCheck::reportOut(const std::string &outmsg)
_errorLogger.reportOut(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) void CppCheck::reportProgress(const std::string &filename, const char stage[], const unsigned int value)
{ {
_errorLogger.reportProgress(filename, stage, value); _errorLogger.reportProgress(filename, stage, value);

View File

@ -55,7 +55,29 @@ public:
* parseFromArgs() or settings() and addFile() before calling this. * parseFromArgs() or settings() and addFile() before calling this.
* @return amount of errors found or 0 if none were found. * @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 * @brief Adjust the settings before doing the check. E.g. show only
@ -71,37 +93,12 @@ public:
*/ */
Settings &settings(); 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. * @brief Returns current version number as a string.
* @return version, e.g. "1.38" * @return version, e.g. "1.38"
*/ */
static const char * version(); static const char * version();
const std::vector<std::string> &filenames() const;
virtual void reportStatus(unsigned int index, unsigned int max); virtual void reportStatus(unsigned int index, unsigned int max);
/** /**
@ -124,6 +121,10 @@ public:
void analyseFile(std::istream &f, const std::string &filename); void analyseFile(std::istream &f, const std::string &filename);
private: private:
/** @brief Process one file. */
unsigned int processFile();
/** @brief Check file */ /** @brief Check file */
void checkFile(const std::string &code, const char FileName[]); void checkFile(const std::string &code, const char FileName[]);
@ -148,13 +149,11 @@ private:
std::ostringstream _errout; std::ostringstream _errout;
Settings _settings; Settings _settings;
bool _useGlobalSuppressions; 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); 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; CheckUnusedFunctions _checkUnusedFunctions;
ErrorLogger &_errorLogger; ErrorLogger &_errorLogger;

View File

@ -55,8 +55,7 @@ private:
CppCheck cppCheck(*this, true); CppCheck cppCheck(*this, true);
cppCheck.settings(settings); cppCheck.settings(settings);
cppCheck.addFile("test.cpp", code); cppCheck.check("test.cpp", code);
cppCheck.check();
reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions()); reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
} }
@ -105,8 +104,7 @@ private:
CppCheck cppCheck(*this, true); CppCheck cppCheck(*this, true);
cppCheck.settings(settings); cppCheck.settings(settings);
for (int i = 0; names[i] != NULL; ++i) for (int i = 0; names[i] != NULL; ++i)
cppCheck.addFile(names[i], codes[i]); cppCheck.check(names[i], codes[i]);
cppCheck.check();
reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions()); reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
} }