Page 1 of 4

CppCheck plugin

Posted: Fri Sep 18, 2009 6:09 pm
by jfouche
For your information

I began a CppCheck plugin, based on the CppCheck software, which is a tool for c / c++ static code analysis.
I hope I can provide you this plugin in a few days.

Re: CppCheck plugin

Posted: Fri Sep 18, 2009 6:34 pm
by eranif
This is a great idea, I read the post in C::B forum, and was thinking doing it myself...
Well, I will settle for yours instead:)
Eran

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 12:17 am
by eranif
Hi,

I read in the C::B forum that u created a library out of the sources. Have u managed to check its stability? becuase using such libraries without knowing the stability of their code can bring codelite to crash, and this is something I prefer not to do.

This is, for example, one of the main reasons I keep the codelite_indexer which is based on ctags (even after I converted it to be libctags.so) because in some cases it crashes, and since it is part of the executable (in a form of shared library) it did crashed codelite.

So, why arnt you using the executable itself? and just run it from your plugin?

Eran

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 1:41 am
by jfouche
Hi Eran

I didn't think about this problem. :oops:
First, I tought about linking my plugin with the lib because the interface is so easy :
- CppCheck::settings
- CppCheck::addFile
- ErrorLogger::reportErr is called automaticaly when a error has been see
- ErrorLogger::reportStatus to tell user how many file to parse, and which file is currently parsed is called automaticaly
Moreover, if there are lots of file to analyse, I'm not sure that a command line of 200 kB (or more) is OK. As I can't presume of directory to scan, I prefere to list all project / workspace files. The actual exe doesn't provide a command line option to read files from a file.
What is your point of view ?
Maybe I can patch the exe file to allow using a input file containing all project / workspace files.

[edit] OK, I'm stoling your code from Cscope plugin to use the exe file. If I encouter problems with the command line, I'll patch the CppCheck exe file.

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 9:56 am
by eranif
eranif wrote:[edit] OK, I'm stoling your code from Cscope plugin to use the exe file. If I encouter problems with the command line, I'll patch the CppCheck exe file.
What we need as the following architecture:
- when a user click 'Perform static analysis' a "job" is being passed to a worker thread
- the worker thread invokes the 'cppcheck' command line and by cpaturing its stdout/err it parses the output
- a GUI custom event is sent per file or percentage to update the UI

Please use the JobQueue for creating a new thread (m_manager->GetJobQueue())
Eran

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 3:32 pm
by jfouche
Hi Eran

Everything is fine with my plugin, except...
How can I add an icon to my tab ? Looking to CSope plugin, I see that you load a bitmap name "cscope" which I can't find :shock: I'm wondering how does that work ! Maybe I'm gonna use a XPM icon.
Moreover, I'm currently testing with a small project actually, so I didn't test the big command line...

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 4:21 pm
by eranif
The icon is probably embeded into the resources.xrc file.

However, the new method of adding icons is to place them under plugins/resources/
and then using the method:

Code: Select all

IPlugin::LoadBitmapFile(const wxString &name)
where the name is the full name of the image without the path: e.g. myimage.png

For example, this is how the ContinuosBuild adds tab with icon to the output pane:

Code: Select all

// add our page to the output pane notebook
m_mgr->GetOutputPaneNotebook()->AddPage(m_view, wxT("Continuous Build"), wxT("Continuous Build"), LoadBitmapFile(wxT("compfile.png")), false);
- Is the execution is done in the background (i.e. different thread)?
- Is the UI update taking place in between? (I tried running cppcheck on the entire codelite workspace, and it takes a long time for it to complete ( I didnt wait for it to complete since it was too long) - there should be UI updates in the meantime

Eran

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 4:44 pm
by jfouche
eranif wrote:- Is the execution is done in the background (i.e. different thread)?
yes
eranif wrote:- Is the UI update taking place in between?
Not sure to understand you : As cppcheck doesn't returns until it's finish, the ui is update in 3 steps :
1 - I update ui to inform user that analysis is in progress. Launch cppcheck which returns xml result.
2 - I update UI to inform user that results are parsed. I parse xml results
3 - At the end, show 'No error' or 'You have errors', and update tree.

Does my answer satisfy you ?

An other solution could be to create a specific exe file that inform CodeLite of the current progress... (it's not so difficult).

[edit] : Another idea could be to inform by callback that stdout received some datas. Not sure if it's possible.

Re: CppCheck plugin

Posted: Sat Sep 19, 2009 5:32 pm
by eranif
jfouche wrote:As cppcheck doesn't returns until it's finish
This is true, but not entirely true.

While running, cppcheck outputs 2 things:
- the XML (I am assuming that you are using the --xml switch)
- any progress messages

The XML is output to stderr while the later is directed to stdout

For example:
running this from the command line:

Code: Select all

cppcheck -s -a --xml . 2> output.txt
resulted in the following output:
Checking .\ASBeautifier.cpp...
1/9 files checked 11% done
Checking .\ASEnhancer.cpp...
Checking .\ASEnhancer.cpp: NDEBUG...
Checking .\ASEnhancer.cpp: TRACEcase...
Checking .\ASEnhancer.cpp: TRACEmisc...
Checking .\ASEnhancer.cpp: TRACEswitch...
2/9 files checked 22% done
Checking .\ASFormatter.cpp...
Checking .\ASFormatter.cpp: NDEBUG...
Checking .\ASFormatter.cpp: TRACEarray...
Checking .\ASFormatter.cpp: TRACEbracket...
Checking .\ASFormatter.cpp: TRACEcomment...
Checking .\ASFormatter.cpp: TRACEheader...
Checking .\ASFormatter.cpp: TRACEunpad...
Checking .\ASFormatter.cpp: __VMS...
3/9 files checked 33% done
Checking .\ASResource.cpp...
4/9 files checked 44% done
Checking .\astyle_main.cpp...
Checking .\astyle_main.cpp: ASTYLE_LIB...
Checking .\astyle_main.cpp: _WIN32...
5/9 files checked 55% done
Checking .\codeforammaterbasedlg.cpp...
6/9 files checked 66% done
Checking .\codeformatter.cpp...
Checking .\codeformatter.cpp: defined((__WXMAC__))...
7/9 files checked 77% done
Checking .\codeformatterdlg.cpp...
8/9 files checked 88% done
Checking .\formatoptions.cpp...
9/9 files checked 100% done
Capturing the progress is easy and can be reported to user in the form of progress bar

If you copied the code from cscope, then like I said, cscope is not a good example. Since it simply waits for the process to terminate in a different thread by calling SafeExecuteCommand()

The proper way of doing it, is by launching the process and reading its stdout and stderr into separate buffers (e.g. have a look at custombuildrequest.cpp)
This is done by creating a wxProcess instance and using it by polling using a wxTimer

Btw, can u send me the source files of cppchecker as library? maybe the best way will be to create a daemon out of it and I can then wrap it with code to use unix sockets / named pipes so we can skip this stdout/stderr capturing and process spawning

Eran

Re: CppCheck plugin

Posted: Sun Sep 20, 2009 1:40 am
by eranif
Hi Jeremie,

I invested some time today, and I after changing the code of the cppcheck a bit (added virtual to some methods in CppCheckExecutor so I can overload them) I created a new class CppCheckExecutorNetwork, which by the name of it you can understand that it redirects all its output and input to the network using the code the codelite_indexer uses (unix sockets / named pipes)

So now, you can start the cppchecker like this:

Code: Select all

./cppchecker -s --all --daemon=<codelite process id>  --xml 
the cppchecker will remain up and will wait for connections.

In your code, you use the following code fragment:

Code: Select all

// Include files
#include "../network/cppchecker_request.h"
#include "../network/cppchecker_protocol.h"
#include "../network/named_pipe_client.h"
#include <stdio.h>

// Some macros needed
#ifdef __WXMSW__
#define PIPE_NAME "\\\\.\\pipe\\cppchecker_%s"
#else
#define PIPE_NAME "/tmp/cppchecker.%s.sock"
#endif
to establish connection to the cppchecker:

Code: Select all

// build the channel name
char channel_name[1024];
sprintf(channel_name, PIPE_NAME, argv[1]);

clNamedPipeClient client(channel_name);
Construct a request object:

Code: Select all

CPPCheckerRequest req;
req.setFile("C:\\Development\\C++\\codelite\\trunk\\Subversion\\subversion.cpp"); //set the file to be parsed here
Connect to the cppchecker and send the request

Code: Select all

client.connect();
CPPCheckerProtocol::SendRequest(&client, req);
At this point, if SendRequest returned true, we can start reading for the reply. Now, the 'reply' object has a completion code which needs to be checked as below:

Code: Select all

bool cont( true );
	while ( cont ) {
		CPPCheckerReply reply;
		if ( CPPCheckerProtocol::ReadReply(&client, reply) == false ) {
			// error
			break;
		}
		switch ( reply.getCompletionCode() ) {
		case CPPCheckerReply::StatusMessage:
			printf("STATUS: %s\n", reply.getReport().c_str() );
			break;
		case CPPCheckerReply::CheckingCompleted:
			printf("STATUS: Completed\n");
			cont = false;
			break;
		case CPPCheckerReply::CheckingInProgress:
			printf("REPORT: %s\n", reply.getReport().c_str() );
			break;
		}
	}
In the above code, I am reading a replies from the cppchecker daemon. Until a reply with completion code 'CPPCheckerReply::CheckingCompleted' has arrived or CPPCheckerProtocol::ReadReply returned false, it is safe to assume that we are still reading the output for the last file we sent.

In addition there is CPPCheckerReply::CheckingInProgress which means, we got partial report, keep it in a buffer until you get the CheckingCompleted status.
Requests with CPPCheckerReply::StatusMessage completion code, are messages reporting progress (current file name, precentage)

I checked this code using a demo client and it works flawlessly.

The above code can be implemented within a worker thread, which will send wxEvents to the GUI whenever it receives StatusMessage completion code replies from the cppchecker.

There are many advantages to the above code:
- If cppchecker crashes, codelite is still up and can also bring the cppchecker back to live (search the code for codelite_indexer similar implementation)
- The daemon is up and running so no need to waste time for forking the process (which is slow on Winodws) for each file
- We can build our own list and send the files one by one to the cppchecker daemon (similar to how it is done in codelite_indexer)
- It uses very fast IPC (inter process communication) layer - which is very fast and stable ( the sources were taken from the code I wrote for the indexer ) it uses named pipes on Windows and Unix socket on Linux/Mac
- Very simple C++ API usage wrapped with 3 classes: CPPCHeckerReuqest, CPPCheckReply and CPPCheckerProtocol

Let me know what do you think!
Eran