Refactoring: Started making CppCheck class more generally usable (e.g. as a part of IDE).

This commit is contained in:
Reijo Tomperi 2008-11-23 22:01:09 +00:00
parent beee37c86b
commit 895b1d5561
5 changed files with 109 additions and 45 deletions

View File

@ -37,7 +37,7 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CppCheck::CppCheck() CppCheck::CppCheck() : _checkFunctionUsage( this )
{ {
} }
@ -47,13 +47,21 @@ CppCheck::~CppCheck()
} }
void CppCheck::check(int argc, char* argv[]) void CppCheck::settings( const Settings &settings )
{
_settings = settings;
}
void CppCheck::addFile( const std::string &path )
{
_filenames.push_back( path );
}
std::string CppCheck::parseFromArgs( int argc, char* argv[] )
{ {
std::vector<std::string> pathnames; std::vector<std::string> pathnames;
bool Recursive = false; bool Recursive = false;
Settings _settings;
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
{ {
if (strcmp(argv[i],"--debug") == 0) if (strcmp(argv[i],"--debug") == 0)
@ -77,14 +85,13 @@ void CppCheck::check(int argc, char* argv[])
pathnames.push_back( argv[i] ); pathnames.push_back( argv[i] );
} }
std::vector<std::string> filenames;
// --recursive was used // --recursive was used
if ( Recursive ) if ( Recursive )
{ {
if( pathnames.size() == 0 ) if( pathnames.size() == 0 )
{ {
// Handle situation: cppcheck --recursive // Handle situation: cppcheck --recursive
FileLister::RecursiveAddFiles( filenames, "", true ); FileLister::RecursiveAddFiles( _filenames, "", true );
} }
else else
{ {
@ -93,21 +100,20 @@ void CppCheck::check(int argc, char* argv[])
// Execute RecursiveAddFiles() to each given file parameter // Execute RecursiveAddFiles() to each given file parameter
std::vector<std::string>::const_iterator iter; std::vector<std::string>::const_iterator iter;
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++) for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
FileLister::RecursiveAddFiles( filenames, iter->c_str(), true ); FileLister::RecursiveAddFiles( _filenames, iter->c_str(), true );
} }
} }
else else
{ {
std::vector<std::string>::const_iterator iter; std::vector<std::string>::const_iterator iter;
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++) for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
FileLister::RecursiveAddFiles( filenames, iter->c_str(), false ); FileLister::RecursiveAddFiles( _filenames, iter->c_str(), false );
} }
if (_filenames.empty())
if (filenames.empty())
{ {
std::cout << "C/C++ code checking.\n" std::ostringstream oss;
oss << "C/C++ code checking.\n"
"\n" "\n"
"Syntax:\n" "Syntax:\n"
" cppcheck [--all] [--style] [--errorsonly] [--recursive] [filename1] [filename2]\n" " cppcheck [--all] [--style] [--errorsonly] [--recursive] [filename1] [filename2]\n"
@ -120,20 +126,26 @@ void CppCheck::check(int argc, char* argv[])
" --style Check coding style.\n" " --style Check coding style.\n"
" --errorsonly Only print something when there is an error\n" " --errorsonly Only print something when there is an error\n"
" --recursive Recursively check all *.cpp, *.cc and *.c files\n"; " --recursive Recursively check all *.cpp, *.cc and *.c files\n";
return; return oss.str();
} }
std::sort( filenames.begin(), filenames.end() ); if ( _settings._showAll && _settings._checkCodingStyle )
_settings._checkFunctionUsage = true;
// Check function usage if "--recursive", "--style" and "--all" was given. return "";
CheckFunctionUsage *checkFunctionUsage = NULL; }
if ( Recursive && _settings._showAll && _settings._checkCodingStyle )
checkFunctionUsage = new CheckFunctionUsage( this );
for (unsigned int c = 0; c < filenames.size(); c++) void CppCheck::check()
{
std::sort( _filenames.begin(), _filenames.end() );
// Check function usage if "--style" and "--all" was given.
for (unsigned int c = 0; c < _filenames.size(); c++)
{ {
_errout.str(""); _errout.str("");
std::string fname = filenames[c]; std::string fname = _filenames[c];
// If only errors are printed, print filename after the check // If only errors are printed, print filename after the check
if (!_settings._errorsOnly) if (!_settings._errorsOnly)
@ -144,7 +156,7 @@ void CppCheck::check(int argc, char* argv[])
Preprocessor preprocessor( this ); Preprocessor preprocessor( this );
preprocessor.preprocess(fin, code, fname); preprocessor.preprocess(fin, code, fname);
for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it ) for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
checkFile(it->second, filenames[c].c_str(), _settings, checkFunctionUsage); checkFile(it->second, _filenames[c].c_str());
if (_settings._errorsOnly) if (_settings._errorsOnly)
{ {
@ -164,11 +176,11 @@ void CppCheck::check(int argc, char* argv[])
} }
// This generates false positives - especially for libraries // This generates false positives - especially for libraries
if ( checkFunctionUsage ) if ( _settings._checkFunctionUsage )
{ {
_errout.str(""); _errout.str("");
std::cout << "Checking usage of global functions (this may take several minutes)..\n"; std::cout << "Checking usage of global functions (this may take several minutes)..\n";
checkFunctionUsage->check(); _checkFunctionUsage.check();
if ( ! _errout.str().empty() ) if ( ! _errout.str().empty() )
{ {
std::cerr << "\n"; std::cerr << "\n";
@ -176,7 +188,6 @@ void CppCheck::check(int argc, char* argv[])
} }
} }
delete checkFunctionUsage;
} }
@ -184,7 +195,7 @@ void CppCheck::check(int argc, char* argv[])
// CppCheck - A function that checks a specified file // CppCheck - A function that checks a specified file
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void CppCheck::checkFile(const std::string &code, const char FileName[], Settings &_settings, CheckFunctionUsage *checkFunctionUsage) void CppCheck::checkFile(const std::string &code, const char FileName[])
{ {
Tokenizer _tokenizer; Tokenizer _tokenizer;
_tokenizer.settings( _settings ); _tokenizer.settings( _settings );
@ -227,8 +238,8 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], Setting
_tokenizer.SimplifyTokenList(); _tokenizer.SimplifyTokenList();
if ( checkFunctionUsage ) if ( _settings._checkFunctionUsage )
checkFunctionUsage->parseTokens(_tokenizer); _checkFunctionUsage.parseTokens(_tokenizer);
// Memory leak // Memory leak
CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this ); CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this );

View File

@ -22,30 +22,75 @@
#include <string> #include <string>
#include <list> #include <list>
#include <sstream> #include <sstream>
#include <vector>
#include "settings.h" #include "settings.h"
#include "errorlogger.h" #include "errorlogger.h"
#include "CheckFunctionUsage.h"
class CheckFunctionUsage;
/** /**
* This is the base class which will use other classes to do * This is the base class which will use other classes to do
* static code analysis for C and C++ code to find possible * static code analysis for C and C++ code to find possible
* errors or places that could be improved. * errors or places that could be improved.
* Usage: See check() for more info.
*/ */
class CppCheck : public ErrorLogger class CppCheck : public ErrorLogger
{ {
public: public:
/**
* Constructor.
*/
CppCheck(); CppCheck();
/**
* Destructor.
*/
virtual ~CppCheck(); virtual ~CppCheck();
void check(int argc, char* argv[]);
/**
* This starts the actual checking. Note that you must call
* parseFromArgs() or settings() and addFile() before calling this.
*/
void check();
/**
* Adjust the settings before doing the check. E.g. show only
* actual bugs or also coding style issues.
*
* @param settings New settings which will overwrite the old.
*/
void settings( const Settings &settings );
/**
* Add new file to be checked.
*
* @param path 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 filese are gathered automatically.
*/
void addFile( const std::string &path );
/**
* Parse command line args and get settings and file lists
* from there.
*
* @param argc argc from main()
* @param argv argv from main()
* @return Empty string if parameters were accepted, or
* string containing "help" text if no files were found to be
* checked.
*/
std::string parseFromArgs( int argc, char* argv[] );
private: private:
void checkFile(const std::string &code, const char FileName[], Settings &_settings, CheckFunctionUsage *checkFunctionUsage); void checkFile(const std::string &code, const char FileName[]);
void reportErr( const std::string &errmsg); void reportErr( const std::string &errmsg);
void reportErr( const TOKEN *token, const std::string &errmsg); void reportErr( const TOKEN *token, const std::string &errmsg);
std::list<std::string> _errorList; std::list<std::string> _errorList;
std::ostringstream _errout; std::ostringstream _errout;
Settings _settings;
std::vector<std::string> _filenames;
CheckFunctionUsage _checkFunctionUsage;
}; };
#endif // CPPCHECK_H #endif // CPPCHECK_H

View File

@ -18,6 +18,7 @@
#include "cppcheck.h" #include "cppcheck.h"
#include <iostream>
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Main function of cppcheck // Main function of cppcheck
@ -26,7 +27,12 @@
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
CppCheck cppCheck; CppCheck cppCheck;
cppCheck.check( argc, argv ); std::string result = cppCheck.parseFromArgs( argc, argv );
if( result.length() == 0 )
cppCheck.check();
else
std::cout << result;
return 0; return 0;
} }

View File

@ -24,6 +24,7 @@ Settings::Settings()
_showAll = false; _showAll = false;
_checkCodingStyle = false; _checkCodingStyle = false;
_errorsOnly = false; _errorsOnly = false;
_checkFunctionUsage = false;
} }
Settings::~Settings() Settings::~Settings()

View File

@ -34,6 +34,7 @@ public:
bool _showAll; bool _showAll;
bool _checkCodingStyle; bool _checkCodingStyle;
bool _errorsOnly; bool _errorsOnly;
bool _checkFunctionUsage;
}; };
#endif // SETTINGS_H #endif // SETTINGS_H