Difference between revisions of "Development/Tutorials/Code Checking"

Jump to: navigation, search
(Describe the EXCLUDE directive)
m (Controlling Krazy on the EBN: Wiki no more exist, and empty on community.kde.org)
 
(35 intermediate revisions by 16 users not shown)
Line 6: Line 6:
  
 
You can also run the tests yourself. To do this, you need to obtain a copy of  
 
You can also run the tests yourself. To do this, you need to obtain a copy of  
the code (from the kdesdk module, in {{path|ebn/krazy}}) and install them. You can then test either a single file (using the krazy application) or a whole tree, including subdirectories (using the krazyall application).
+
the code from [http://gitorious.org/krazy/krazy/trees/master krazy2/install.txt] and install them. You can then test either a single file (using the krazy2 application) or a whole tree, including subdirectories (using the krazy2all application).
  
 
====How Krazy works====
 
====How Krazy works====
Line 13: Line 13:
  
 
Krazy exists as a framework comprising a number of different test runners, and
 
Krazy exists as a framework comprising a number of different test runners, and
a set of plugins. The test runners are called krazy, krazyall, and krazyebn. The test runners just call one or more plugins on the appropriate code, and  
+
a set of plugins. The test runners are called krazy2, krazy2all, and krazy2ebn. The test runners just call one or more plugins on the appropriate code, and  
 
format the results for display.
 
format the results for display.
  
Line 22: Line 22:
 
====Installing Krazy====
 
====Installing Krazy====
 
Krazy needs to be installed before use. Krazy has two different ways to be
 
Krazy needs to be installed before use. Krazy has two different ways to be
installed - you can either modify the {{path|krazy/install.sh}} script and
+
installed - you can either modify the {{path|krazy2/install.sh}} script and
run it, or follow the instructions in the [http://websvn.kde.org/trunk/KDE/kdesdk/ebn/krazy/INSTALL.txt krazy/INSTALL.txt] file. I recommend the second.
+
run it, or follow the instructions in the [http://gitorious.org/krazy/krazy/trees/master krazy2/install.txt] file. I recommend the second.
 +
 
 +
You may need to install additional perl modules like XML::LibXML, here is how:
 +
<pre>
 +
linux-pudb:~/krazy2 # ./install.sh
 +
MakeMaker FATAL: prerequisites not found.
 +
    Tie::IxHash not installed
 +
    XML::LibXML not installed
 +
 +
Please install these modules first and rerun 'perl Makefile.PL'.
 +
linux-pudb:~/krazy2 # perl -mCPAN -e CPAN::shell
 +
</pre>
 +
You may have to answer 25 useless questions here. In this case, just press ENTER 25 times. Then you go on like this:
 +
<pre>
 +
cpan[1]> install XML::LibXML
 +
</pre>
 +
 
 +
The Tie::IxHash I installed from the distro repository (libtie-ixhash-perl) and also the perl-doc package is needed to install it.
  
 
{{Note|I had a minor problem with the plugin that is built from C++, because that plugin got installed into the wrong directory. If you are missing the passbyvalue plugin, then you may need to move it into the directory that contains the rest of your plugins.}}
 
{{Note|I had a minor problem with the plugin that is built from C++, because that plugin got installed into the wrong directory. If you are missing the passbyvalue plugin, then you may need to move it into the directory that contains the rest of your plugins.}}
Line 31: Line 48:
 
options and a usage example. The file is generated on installation. This is definitely recommended reading!
 
options and a usage example. The file is generated on installation. This is definitely recommended reading!
  
As noted above, there are three test runners - krazy, krazyebn and krazyall. If you are trying to check a single file, then krazy is the right tool. If you are trying to check a source tree (say, an application or a whole subversion module), then krazyall is more useful. krazyall doesn't have a man page, but
+
As noted above, there are three test runners - krazy2, krazy2ebn and krazy2all. If you are trying to check a single file, then krazy2 is the right tool. If you are trying to check a source tree (say, an application or a whole subversion module), then krazy2all is more useful. krazy2all doesn't have a man page, but
you can get a list of the options with krazyall --help. You can also use krazy to get information on the various plugins, which can help you understand more about krazyall.
+
you can get a list of the options with krazy2all --help. You can also use krazy2 to get information on the various plugins, which can help you understand more about krazy2all.
  
krazyebn is the tool that runs over the KDE codebase on the [http://www.englishbreakfastnetwork.org EBN] and should not be run locally.
+
krazy2ebn is the tool that runs over the KDE codebase on the [http://www.englishbreakfastnetwork.org EBN] and should not be run locally.
However, please see [[#Controlling Krazy on the EBN|Controlling Krazy on the EBN]] below to learn how you can control which plugins are run, and what files are processed by the krazyebn program on the EBN machine.
+
However, please see [[#Controlling Krazy on the EBN|Controlling Krazy on the EBN]] below to learn how you can control which plugins are run, and what files are processed by the krazy2ebn program on the EBN machine.
  
 
Remember that Krazy doesn't change your code - it only examines it. So you can safely experiment with running Krazy checks until you are confident that you understand what is happening.
 
Remember that Krazy doesn't change your code - it only examines it. So you can safely experiment with running Krazy checks until you are confident that you understand what is happening.
Line 44: Line 61:
 
The Krazy plugins support the following list of in-code directives:
 
The Krazy plugins support the following list of in-code directives:
 
* <tt>//krazy:skip</tt> - no Krazy tests will run on this file.
 
* <tt>//krazy:skip</tt> - no Krazy tests will run on this file.
* <tt>//krazy:excludeall=<name1[,name2,...,nameN]></tt> - the Krazy tests ''name1'', etc will not be run on this file.
+
* <tt>//krazy:excludeall=<name1[,name2,...,nameN]></tt> - the Krazy tests ''name1'', etc will not be run on this file. Multiple occurrences of krazy:excludeall are allowed.
 
* <tt>//krazy:exclude=<name1[,name2,...,nameN]></tt> - the Krazy tests ''name1'', etc. will not be run on the line where this directive is found (see the [[#Suppressing false-positives|next section]] below for more information).
 
* <tt>//krazy:exclude=<name1[,name2,...,nameN]></tt> - the Krazy tests ''name1'', etc. will not be run on the line where this directive is found (see the [[#Suppressing false-positives|next section]] below for more information).
  
Line 51: Line 68:
 
====Suppressing false-positives====
 
====Suppressing false-positives====
 
The Krazy tests are designed to minimise false positives (that is, alerts that do not represent real problems). However because most of the tests are conducted on a single line, there are some tests that might produce such a false positive. For example, code that does something like:
 
The Krazy tests are designed to minimise false positives (that is, alerts that do not represent real problems). However because most of the tests are conducted on a single line, there are some tests that might produce such a false positive. For example, code that does something like:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
QString mystring;
 
QString mystring;
 
mystring += "/";
 
mystring += "/";
</code>
+
</syntaxhighlight>
 
will be flagged by the doublequote_chars checker, because it is more efficient to add a single char, as shown below:
 
will be flagged by the doublequote_chars checker, because it is more efficient to add a single char, as shown below:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
QString mystring;
 
QString mystring;
 
// note that we are using single quotes
 
// note that we are using single quotes
 
// this is a char, not a char array
 
// this is a char, not a char array
 
mystring += '/';  
 
mystring += '/';  
</code>
+
</syntaxhighlight>
  
 
That same checker will produce a false positive for code that looks like:
 
That same checker will produce a false positive for code that looks like:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
std::string mystring;
 
std::string mystring;
 
mystring += "/";
 
mystring += "/";
</code>
+
</syntaxhighlight>
  
 
You can suppress these false positives using a special comment format.
 
You can suppress these false positives using a special comment format.
 
To exclude a particular plugin from being run on a line of code, simply add
 
To exclude a particular plugin from being run on a line of code, simply add
 
a C++ comment containing the string "krazy:exclude=<plugin_name>". The plugins currently available can be found in the  
 
a C++ comment containing the string "krazy:exclude=<plugin_name>". The plugins currently available can be found in the  
[http://websvn.kde.org/trunk/KDE/kdesdk/ebn/krazy/plugins repository].
+
[http://gitorious.org/krazy/krazy/trees/master repository].
  
 
Specifically, for this plugin use "krazy:exclude=doublequote_chars".
 
Specifically, for this plugin use "krazy:exclude=doublequote_chars".
 
For example:
 
For example:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
  lenstr = "0" + lenstr;
+
lenstr = "0" + lenstr;
</code>
+
</syntaxhighlight>
 
becomes
 
becomes
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
  lenstr = "0" + lenstr;  // krazy:exclude=doublequote_chars
+
lenstr = "0" + lenstr;  // krazy:exclude=doublequote_chars
</code>
+
</syntaxhighlight>
  
 
{{Note|Using c-style (/* */) comments will ''not'' work. You must use C++ style (//) comments when noting tests to be skipped.}}
 
{{Note|Using c-style (/* */) comments will ''not'' work. You must use C++ style (//) comments when noting tests to be skipped.}}
Line 91: Line 108:
 
To ignore a sub-directory within a module, say {{path|kdepim/kmail}}, use the IGNORESUBS directory within the {{path|kdepim/.krazy}} file, like so:
 
To ignore a sub-directory within a module, say {{path|kdepim/kmail}}, use the IGNORESUBS directory within the {{path|kdepim/.krazy}} file, like so:
  
<code>
+
<pre>
 
IGNORESUBS kmail
 
IGNORESUBS kmail
</code>
+
</pre>
  
 
Or you can ignore a set of directories by specifying a comma-separated list:
 
Or you can ignore a set of directories by specifying a comma-separated list:
  
<code>
+
<pre>
 
IGNORESUBS kmail,kontact,knode
 
IGNORESUBS kmail,kontact,knode
</code>
+
</pre>
  
 
To ignore files or directories within a module/subdir, specify a regular expression that matches the files to skip together with the SKIP directive.
 
To ignore files or directories within a module/subdir, specify a regular expression that matches the files to skip together with the SKIP directive.
 
For example, to skip the directories {{path|kdepimlibs/kcal/libical}}, {{path|kdepimlibs/kcal/versit}}, and the {{path|kdepimlibs/kcal/fred.c}} file, use this directive within the {{path|kdepim/kcal/.krazy}} file:
 
For example, to skip the directories {{path|kdepimlibs/kcal/libical}}, {{path|kdepimlibs/kcal/versit}}, and the {{path|kdepimlibs/kcal/fred.c}} file, use this directive within the {{path|kdepim/kcal/.krazy}} file:
  
<code>
+
<pre>
 
SKIP /libical/\|/versit/\|fred\.c
 
SKIP /libical/\|/versit/\|fred\.c
</code>
+
</pre>
  
 
Use the EXCLUDE directive to disable a list of plugins for all files within a module/subdir:
 
Use the EXCLUDE directive to disable a list of plugins for all files within a module/subdir:
  
<code>
+
<pre>
 
EXCLUDE doublequote_chars,qclasses
 
EXCLUDE doublequote_chars,qclasses
</code>
+
</pre>
 +
 
 +
To override the EXCLUDE directive set from a {{path|.krazy}} file up in the directory hierarchy, use the CHECK command.  For example, the component level {{path|.krazy}} file may EXCLUDE the ''copyright'' and ''license'' plugins, but those plugins can be re-enabled in a module/subdir with the CHECK directive like so:
 +
 
 +
<pre>
 +
CHECK copyright,license
 +
</pre>
 +
 
 +
{{Note|Individual modules can be ignored as well, but this is an EBN administrator duty controlled by component-level ''.krazy'' files within the ''/usr/local/src'' hierarchy.}}
 +
 
 +
===Krazy Modules===
 +
 
 +
Risk Ratings:
 +
 
 +
'''Low:'''  Can be fixed by anyone with minimal risk of error.
 +
 
 +
'''Medium:'''  Can be fixed by anyone with appropriate knowledge of C++ features involved, some testing advised.
 +
 
 +
'''High:'''  Should only be fixed by maintainer/owner of code
 +
 
 +
If you don't understand the code, or you don't understand the fix, then do not fix the code.
 +
 
 +
Fixing apidox and spelling mistakes only requires a compile before submitting.  All other fixes should be tested to an appropriate degree, the standard unit tests are useful for this.
 +
 
 +
====Module=spelling====
 +
 
 +
'''Risk from Fixing:''' Low
 +
 
 +
Spelling errors in comments and strings should be fixed as they may show up later in API documentation, handbooks, etc. Misspelled strings make the translator's job harder. Please use US English.
 +
 
 +
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=spelling
 +
</syntaxhighlight>
 +
 
 +
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=spelling
 +
</syntaxhighlight>
 +
 
 +
====Module=doublequote_chars====
 +
 
 +
'''Risk from Fixing:''' Low
 +
 
 +
Adding single characters to a QString is faster if the characters are QChars and not QStrings, i.e. use single quotes instead of double quotes around single characters.
 +
 
 +
The same holds for arguments to QString::startsWith(), QString::endsWith(), QString::remove(), QString::section(), and QString::split().
 +
 
 +
Use QString::remove() instead of QString::replace(foo,"")
 +
 
 +
Replace
 +
<syntaxhighlight lang="cpp-qt">
 +
QString path = oldpath + "/" + base;
 +
</syntaxhighlight>
 +
with
 +
<syntaxhighlight lang="cpp-qt">
 +
QString path = oldpath + '/' + base;
 +
</syntaxhighlight>
 +
 
 +
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=doublequote_chars
 +
</syntaxhighlight>
 +
 
 +
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=doublequote_chars
 +
</syntaxhighlight>
 +
 
 +
====Module=nullstrassign====
 +
 
 +
'''Risk from Fixing:''' Low
 +
 
 +
Do not assign QString::null or QString() to a QString. Instead use the .clear() method.
 +
 
 +
Replace
 +
<syntaxhighlight lang="cpp-qt">
 +
fileName = QString::null;
 +
</syntaxhighlight>
 +
or
 +
<syntaxhighlight lang="cpp-qt">
 +
fileName = QString();
 +
</syntaxhighlight>
 +
with
 +
<syntaxhighlight lang="cpp-qt">
 +
fileName.clear();
 +
</syntaxhighlight>
 +
 
 +
When returning an empty string from a method use "return QString()" When passing an empty string use "QString()".
 +
 
 +
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=nullstrassign
 +
</syntaxhighlight>
 +
 
 +
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=nullstrassign
 +
</syntaxhighlight>
 +
 
 +
====Module=foreach====
 +
 
 +
'''Message:''' non-const ref iterator
 +
 
 +
'''Risk from Fixing:''' Low to Medium
 +
 
 +
When not using POD types (int, double, pointer, ...) you should use const & for your foreach variables. There are two reasons for this: 1) Prevents you from the mistake of writing foreach loops that modify the list, that is 'foreach(Foo f, list) f.a = f.b = f.c = 0;' compiles but does not modify the contents of list 2) Saves a copy constructor call for each of the list elements
 +
 
 +
Be careful if dealing with pointers?  False positive for bool, qlonglong and qulonglong?
 +
 
 +
http://tsdgeos.blogspot.com/2008/04/qforeach-is-your-friend.html
 +
 
 +
Replace
 +
<syntaxhighlight lang="cpp-qt">
 +
foreach(QString str, stringList) {
 +
</syntaxhighlight>
 +
with
 +
<syntaxhighlight lang="cpp-qt">
 +
foreach(const QString &str, stringList) {
 +
</syntaxhighlight>
 +
 
 +
'''Message:''' values or keys iteration
 +
 
 +
'''Risk from Fixing:''' Medium to High
 +
 
 +
http://tsdgeos.blogspot.com/2009/04/how-to-make-foreach-loops-that-dont.html
 +
 
 +
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=foreach
 +
</syntaxhighlight>
 +
 
 +
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=foreach
 +
</syntaxhighlight>
 +
 
 +
====Module=strings====
 +
 
 +
'''Message:''' QLatin1String issues
 +
 
 +
'''Risk from Fixing:''' Low to Medium
 +
 
 +
Some QString methods (like startsWith() and endsWith()) are more efficient if they are passed a QLatin1String, avoiding an implicit conversion from const char *.
 +
 
 +
Replace
 +
<syntaxhighlight lang="cpp-qt">
 +
aString.startsWith("init")
 +
</syntaxhighlight>
 +
with
 +
<syntaxhighlight lang="cpp-qt">
 +
aString.startsWith(QLatin1String("init"))
 +
</syntaxhighlight>
 +
 
 +
A common false positive is with QByteArray which cannot take a QLatin1String.
 +
 
 +
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=strings
 +
</syntaxhighlight>
 +
 
 +
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=strings
 +
</syntaxhighlight>
 +
 
 +
====Module=includes====
 +
 
 +
See http://techbase.kde.org/Policies/Library_Code_Policy#Getting_.23includes_right.
 +
 
 +
'''Message:''' duplicate includes
 +
 
 +
'''Risk from Fixing:''' Low
 +
 
 +
The same file has been included twice, remove the second occurrence.
 +
 
 +
'''Message:''' include own header first
 +
 
 +
'''Message:''' include own _p header first
 +
 
 +
'''Risk from Fixing:''' Medium
 +
 
 +
The cpp file should include their own .h and _p.h headers first in the file (but below config.h).  Move the includes to the correct position.  You may need to adjust includes and forward declarations in other files as a result, the compiler will advise of these.
 +
 
 +
'''Message:''' missing or improper include guard in header
 +
 
 +
'''Risk from Fixing:''' Low
 +
 
 +
Either the include guards are missing, or they are not appropriately encoded macro names, e.g. do not include the class name.
 +
 
 +
'''Message:'''
 +
 
 +
Use <..> to include installed headers.
 +
 
 +
'''Message:'''
 +
 
 +
To include Qt headers from installed headers.
 +
 
 +
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=includes
 +
</syntaxhighlight>
 +
 
 +
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=includes
 +
</syntaxhighlight>
 +
 
 +
====Module=qclasses====
 +
 
 +
'''Risk from Fixing:''' Medium
 +
 
 +
Deprecated Qt classes and classes that have a KDE version shouldn't be used. Also KDE versions of some Qt GUI elements provide a consistent look and feel for the KDE desktop. See http://techbase.kde.org/Policies/API_to_Avoid
 +
 
 +
Some of the K classes don't just add features to the Qt ones and might not even be based on the Qt class. '''Please refer to the API documentation before porting to the K classes.'''
  
'''TODO''': note how the subdir directives are merged with the module directives, but that CHECK plugin lists override EXCLUDE plugin lists
+
To exclude all checks in file comment at top of file:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:excludeall=qclasses
 +
</syntaxhighlight>
  
{{Note|Individual modules can be ignored as well, but this is an EBN administrator duty controlled by component-level ''.krazy'' files within the ''/usr/local/src'' hierarchy. See the [http://wiki.kde.org/English+Breakfast+Network English Breakfast Network wiki] for details.}}
+
To exclude an individual check comment at the end of the line:
 +
<syntaxhighlight lang="cpp-qt">
 +
// krazy:exclude=qclasses
 +
</syntaxhighlight>
  
===Compiler Warnings===
+
==Compiler Warnings==
 
In addition to the various Krazy tools, you can also get valuable assistance from the warnings that the compiler emits, especially if you enable additional warnings (per the documentation for your compiler), and also if you test with more than one compiler (e.g. if you can test on Linux with both GCC and the Intel compiler; or on Linux with GCC and also on Windows with the Microsoft compiler).
 
In addition to the various Krazy tools, you can also get valuable assistance from the warnings that the compiler emits, especially if you enable additional warnings (per the documentation for your compiler), and also if you test with more than one compiler (e.g. if you can test on Linux with both GCC and the Intel compiler; or on Linux with GCC and also on Windows with the Microsoft compiler).

Latest revision as of 04:00, 2 December 2012

Contents

[edit] Code Checking

There are a lot of ways to find bugs in KDE code. Increasingly, KDE developers have started to use automated tools. You can use some of those tools to improve your own code.

[edit] The KDE 'Krazy' Checker

KDE developers have a simple set of tests that are collectively known as "Krazy". These tests were originally developed to be run as part of a larger set of tests on a machine known as http://www.englishbreakfastnetwork.org, or EBN for short. You can see the results of running the various tests on EBN (at http://www.englishbreakfastnetwork.org/krazy/).

You can also run the tests yourself. To do this, you need to obtain a copy of the code from krazy2/install.txt and install them. You can then test either a single file (using the krazy2 application) or a whole tree, including subdirectories (using the krazy2all application).

[edit] How Krazy works

The Krazy tests are essentially a form of static analysis - they check the source code, but not how it runs.

Krazy exists as a framework comprising a number of different test runners, and a set of plugins. The test runners are called krazy2, krazy2all, and krazy2ebn. The test runners just call one or more plugins on the appropriate code, and format the results for display.

At this stage, most of the test runners are written in perl, however one is written in C++ (using Qt) and it is quite possible to add your own tests, or to modify a test - all sources are provided.

[edit] Installing Krazy

Krazy needs to be installed before use. Krazy has two different ways to be installed - you can either modify the krazy2/install.sh script and run it, or follow the instructions in the krazy2/install.txt file. I recommend the second.

You may need to install additional perl modules like XML::LibXML, here is how:

linux-pudb:~/krazy2 # ./install.sh 
MakeMaker FATAL: prerequisites not found.
    Tie::IxHash not installed
    XML::LibXML not installed
 
Please install these modules first and rerun 'perl Makefile.PL'.
linux-pudb:~/krazy2 # perl -mCPAN -e CPAN::shell

You may have to answer 25 useless questions here. In this case, just press ENTER 25 times. Then you go on like this:

cpan[1]> install XML::LibXML

The Tie::IxHash I installed from the distro repository (libtie-ixhash-perl) and also the perl-doc package is needed to install it.

noframe
 
Note
I had a minor problem with the plugin that is built from C++, because that plugin got installed into the wrong directory. If you are missing the passbyvalue plugin, then you may need to move it into the directory that contains the rest of your plugins.

[edit] Using Krazy

Krazy comes with a particularly good man page, which gives you the various options and a usage example. The file is generated on installation. This is definitely recommended reading!

As noted above, there are three test runners - krazy2, krazy2ebn and krazy2all. If you are trying to check a single file, then krazy2 is the right tool. If you are trying to check a source tree (say, an application or a whole subversion module), then krazy2all is more useful. krazy2all doesn't have a man page, but you can get a list of the options with krazy2all --help. You can also use krazy2 to get information on the various plugins, which can help you understand more about krazy2all.

krazy2ebn is the tool that runs over the KDE codebase on the EBN and should not be run locally. However, please see Controlling Krazy on the EBN below to learn how you can control which plugins are run, and what files are processed by the krazy2ebn program on the EBN machine.

Remember that Krazy doesn't change your code - it only examines it. So you can safely experiment with running Krazy checks until you are confident that you understand what is happening.

Equally, that means that Krazy doesn't fix problems - it only tries to report them. Understanding what is being reported, and how to fix it, is up to you. You should also remember the KDE commit policy about not committing code that you don't understand. So fixing a spelling error in a comment is pretty safe, but blindly changing code to stop explicit constructor warnings from Krazy is not a good idea.

[edit] In-Code directives

The Krazy plugins support the following list of in-code directives:

  • //krazy:skip - no Krazy tests will run on this file.
  • //krazy:excludeall=<name1[,name2,...,nameN]> - the Krazy tests name1, etc will not be run on this file. Multiple occurrences of krazy:excludeall are allowed.
  • //krazy:exclude=<name1[,name2,...,nameN]> - the Krazy tests name1, etc. will not be run on the line where this directive is found (see the next section below for more information).

Note that these directives must be C++ style comments that can be put anywhere in the file desired (except embedded within C-style comments).

[edit] Suppressing false-positives

The Krazy tests are designed to minimise false positives (that is, alerts that do not represent real problems). However because most of the tests are conducted on a single line, there are some tests that might produce such a false positive. For example, code that does something like:

QString mystring;
mystring += "/";

will be flagged by the doublequote_chars checker, because it is more efficient to add a single char, as shown below:

QString mystring;
// note that we are using single quotes
// this is a char, not a char array
mystring += '/';

That same checker will produce a false positive for code that looks like:

std::string mystring;
mystring += "/";

You can suppress these false positives using a special comment format. To exclude a particular plugin from being run on a line of code, simply add a C++ comment containing the string "krazy:exclude=<plugin_name>". The plugins currently available can be found in the repository.

Specifically, for this plugin use "krazy:exclude=doublequote_chars". For example:

lenstr = "0" + lenstr;

becomes

lenstr = "0" + lenstr;  // krazy:exclude=doublequote_chars
noframe
 
Note
Using c-style (/* */) comments will not work. You must use C++ style (//) comments when noting tests to be skipped.

[edit] Controlling Krazy on the EBN

This section describes how to use .krazy files to control the Krazy runs on the EBN. The .krazy files are used to tell Krazy to skip over specific sub-directories, or files; or to disable certain plugins within those modules and sub-directories.

To ignore a sub-directory within a module, say kdepim/kmail, use the IGNORESUBS directory within the kdepim/.krazy file, like so:

IGNORESUBS kmail

Or you can ignore a set of directories by specifying a comma-separated list:

IGNORESUBS kmail,kontact,knode

To ignore files or directories within a module/subdir, specify a regular expression that matches the files to skip together with the SKIP directive. For example, to skip the directories kdepimlibs/kcal/libical, kdepimlibs/kcal/versit, and the kdepimlibs/kcal/fred.c file, use this directive within the kdepim/kcal/.krazy file:

SKIP /libical/\|/versit/\|fred\.c

Use the EXCLUDE directive to disable a list of plugins for all files within a module/subdir:

EXCLUDE doublequote_chars,qclasses

To override the EXCLUDE directive set from a .krazy file up in the directory hierarchy, use the CHECK command. For example, the component level .krazy file may EXCLUDE the copyright and license plugins, but those plugins can be re-enabled in a module/subdir with the CHECK directive like so:

CHECK copyright,license
noframe
 
Note
Individual modules can be ignored as well, but this is an EBN administrator duty controlled by component-level .krazy files within the /usr/local/src hierarchy.

[edit] Krazy Modules

Risk Ratings:

Low: Can be fixed by anyone with minimal risk of error.

Medium: Can be fixed by anyone with appropriate knowledge of C++ features involved, some testing advised.

High: Should only be fixed by maintainer/owner of code

If you don't understand the code, or you don't understand the fix, then do not fix the code.

Fixing apidox and spelling mistakes only requires a compile before submitting. All other fixes should be tested to an appropriate degree, the standard unit tests are useful for this.

[edit] Module=spelling

Risk from Fixing: Low

Spelling errors in comments and strings should be fixed as they may show up later in API documentation, handbooks, etc. Misspelled strings make the translator's job harder. Please use US English.

To exclude all checks in file comment at top of file:

// krazy:excludeall=spelling

To exclude an individual check comment at the end of the line:

// krazy:exclude=spelling

[edit] Module=doublequote_chars

Risk from Fixing: Low

Adding single characters to a QString is faster if the characters are QChars and not QStrings, i.e. use single quotes instead of double quotes around single characters.

The same holds for arguments to QString::startsWith(), QString::endsWith(), QString::remove(), QString::section(), and QString::split().

Use QString::remove() instead of QString::replace(foo,"")

Replace

QString path = oldpath + "/" + base;

with

QString path = oldpath + '/' + base;

To exclude all checks in file comment at top of file:

// krazy:excludeall=doublequote_chars

To exclude an individual check comment at the end of the line:

// krazy:exclude=doublequote_chars

[edit] Module=nullstrassign

Risk from Fixing: Low

Do not assign QString::null or QString() to a QString. Instead use the .clear() method.

Replace

fileName = QString::null;

or

fileName = QString();

with

fileName.clear();

When returning an empty string from a method use "return QString()" When passing an empty string use "QString()".

To exclude all checks in file comment at top of file:

// krazy:excludeall=nullstrassign

To exclude an individual check comment at the end of the line:

// krazy:exclude=nullstrassign

[edit] Module=foreach

Message: non-const ref iterator

Risk from Fixing: Low to Medium

When not using POD types (int, double, pointer, ...) you should use const & for your foreach variables. There are two reasons for this: 1) Prevents you from the mistake of writing foreach loops that modify the list, that is 'foreach(Foo f, list) f.a = f.b = f.c = 0;' compiles but does not modify the contents of list 2) Saves a copy constructor call for each of the list elements

Be careful if dealing with pointers? False positive for bool, qlonglong and qulonglong?

http://tsdgeos.blogspot.com/2008/04/qforeach-is-your-friend.html

Replace

foreach(QString str, stringList) {

with

foreach(const QString &str, stringList) {

Message: values or keys iteration

Risk from Fixing: Medium to High

http://tsdgeos.blogspot.com/2009/04/how-to-make-foreach-loops-that-dont.html

To exclude all checks in file comment at top of file:

// krazy:excludeall=foreach

To exclude an individual check comment at the end of the line:

// krazy:exclude=foreach

[edit] Module=strings

Message: QLatin1String issues

Risk from Fixing: Low to Medium

Some QString methods (like startsWith() and endsWith()) are more efficient if they are passed a QLatin1String, avoiding an implicit conversion from const char *.

Replace

aString.startsWith("init")

with

aString.startsWith(QLatin1String("init"))

A common false positive is with QByteArray which cannot take a QLatin1String.

To exclude all checks in file comment at top of file:

// krazy:excludeall=strings

To exclude an individual check comment at the end of the line:

// krazy:exclude=strings

[edit] Module=includes

See http://techbase.kde.org/Policies/Library_Code_Policy#Getting_.23includes_right.

Message: duplicate includes

Risk from Fixing: Low

The same file has been included twice, remove the second occurrence.

Message: include own header first

Message: include own _p header first

Risk from Fixing: Medium

The cpp file should include their own .h and _p.h headers first in the file (but below config.h). Move the includes to the correct position. You may need to adjust includes and forward declarations in other files as a result, the compiler will advise of these.

Message: missing or improper include guard in header

Risk from Fixing: Low

Either the include guards are missing, or they are not appropriately encoded macro names, e.g. do not include the class name.

Message:

Use <..> to include installed headers.

Message:

To include Qt headers from installed headers.

To exclude all checks in file comment at top of file:

// krazy:excludeall=includes

To exclude an individual check comment at the end of the line:

// krazy:exclude=includes

[edit] Module=qclasses

Risk from Fixing: Medium

Deprecated Qt classes and classes that have a KDE version shouldn't be used. Also KDE versions of some Qt GUI elements provide a consistent look and feel for the KDE desktop. See http://techbase.kde.org/Policies/API_to_Avoid

Some of the K classes don't just add features to the Qt ones and might not even be based on the Qt class. Please refer to the API documentation before porting to the K classes.

To exclude all checks in file comment at top of file:

// krazy:excludeall=qclasses

To exclude an individual check comment at the end of the line:

// krazy:exclude=qclasses

[edit] Compiler Warnings

In addition to the various Krazy tools, you can also get valuable assistance from the warnings that the compiler emits, especially if you enable additional warnings (per the documentation for your compiler), and also if you test with more than one compiler (e.g. if you can test on Linux with both GCC and the Intel compiler; or on Linux with GCC and also on Windows with the Microsoft compiler).


This page was last modified on 2 December 2012, at 04:00. This page has been accessed 33,674 times. Content is available under Creative Commons License SA 3.0 as well as the GNU Free Documentation License 1.2.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal