Checkstyle is a great tool to ensure that coding in Java follows some rules.
Many standard checkers are provided in standard, but it is also possible to write new ones.
The goal of this place is to provide new (and sometimes experimental) checkers that will be hopfully one day integrated into Checkstyle.
cs.jar
.
config.xml
(you can find a example here).
java -classpath cs.jar:checkstyle-all-4.4.jar \ com.puppycrawl.tools.checkstyle.Main \ -c config.xml -r .
Checker Summary | |
---|---|
AvoidNegativeLogic | This checker avoid the usage of inverted logic. |
AvoidSelfAssignement | This checker detects variable that are assigned to itself. |
AvoidSingleton | Singleton without any field are really useless. |
CanonicalFor | This checker tries to detect inconsistence into for loop. |
CollapseIfStatement | This checker looks for if statement with can be simplified. |
DeclareVariableInItsBloc | Variable should be declared in the bloc that uses it. |
DuplicateBranche | This checker detects branches that are exactly the same. |
DuplicateCondition | This checker detect useless duplicated test. |
HiddenCatchBloc | Very often, people catch exception and do not use the exception itself. |
ImmutableField | This checker detects private fields that are unused in a class and promotes
the usage of final for fields that are never changed. |
ImportControl | This check control that import are valid into a java file, depending on its package. |
InstanceofIsNeverNull | When an object is an instanceof something, it cannot be
null . |
MisspelledIdent | This checker looks for misspelled ident in source code. |
NewIsNeverNull | When an object is created with new , it is never null. |
PatternFilter | This filter looks like SuppressionFilter, but the configuration is done in the filter itself, and not into another XML file. |
PotentialNPE | This checker tries to find some trivial NullPointerException . |
ReturnZeroLengthArray | Return a zero length array instead of returning null. |
TooEarlyVariableDeclaration | This checker try to detect too early variable declaration. |
UnitTestMethods | This checker is really great for Test Driven Developpement. |
UnnecessarilyElse | This checker detects unnecessarily else statement. |
UnnecessaryParentheses | This checker detects some unnecessary parentheses which are not detected by the standard check of CheckStyle. |
UnusedImports | Patched version of the standard UnusedImport. |
UnusedLocalVariable | This checker detects unused local variable. |
UnusedPrivateMethod | This checker looks for unused private method in a class. |
if (a != null) { System.out.println("not null"); } else { System.out.println("null"); }and promotes the usage of :
if (a == null) { System.out.println("null"); } else { System.out.println("not null"); }
This is likely a typo. Example:
this.foo = this.foo
for
loop.
For example, if the variable declared in the initialisation is not used in the condition.
==
, !=
, &&
and ||
For example:
if (a != null) { if (b == null) { System.err.println(); } }Can be simplified in:
if (a != null && b == null) { System.err.println(); }Another example:
if (a == null) { // some code } else { if (b == null) { // Some other code } }Can be simplified in:
if (a == null) { // some code } else if (b == null) { // Some other code }
For example:
Object dummy; for (Iterator it = list.iterator(); it.hasNext();) { dummy = it.next(); ... } (dummy not used anymore)Can be changed in:
for (Iterator it = list.iterator(); it.hasNext();) { Object dummy = it.next(); ... }
Example:
if (a > 0) { b = 9; } else { b = 9; }Or:
switch (a) { case 1: b = 15; break; case 2: b = 15; break; }
if (getText() > 1 && getText() > 1) ...
Example:
try { ... } catch (IOException e) { return null; }May be we should at least log the exception:
try { ... } catch (IOException e) { log.error("IOError ", e); return null; }
final
for fields that are never changed.
By default log
and serialVersionUID
is ignored,
but you can change this in the configuration file:
<module name="cs.ImmutableField"> <property name="ignore" value="ˆ(log|serialVersionUID|special.*)$" /> </module>
Example, to control that classes into com.foo2
(and
subpackages) does not import com.foo1
:
<module name="cs.ImportControl"> <property name="importThis" value="com\.foo1" /> <property name="notByPackages" value="com\.foo2" /> </module>
Another example, to control that only classes into com.dummy2
(and
subpackages) does import com.dummy1
:
<module name="cs.ImportControl"> <property name="importThis" value="com\.dummy1" /> <property name="onlyByPackages" value="com\.dummy2" /> </module>
instanceof
something, it cannot be
null
.
So the following code :
if (obj != null && obj instanceof List) {...}should be changed into:
if (obj instanceof List) {...}
For example, hashcode
or hascode
is considered
as a bad spelling of hashCode
.
The property correctIdents
which default value is
hashCode,equals,compareTo
can be changed in the configuration
file:
<module name="cs.MisspelledIdent"> <property name="correctIdents" value="hashCode,equals,compareTo,hasCode" /> </module>
new
, it is never null.
So the following code :
MyClass obj = new MyClass(); if (obj != null) { // Some code }should be changed into:
MyClass obj = new MyClass(); // Some code
<module name="Checker"> <module name="cs.PatternFilter"> <property name="ignoreFiles" value="(.*(<=Managed)(<=View)Bean\.java)|(.*Home\.java)" /> <property name="modules" value="TabCharacter|WhitespaceAround" /> </module> <module name="TreeWalker"> ... </module> </module>
NullPointerException
. If a private
method contains a "return null" statement, and if the result of this method
is used without being tested against null, the checker log a error.
This is quite experimental.
When a method returns an array, it is often more logical to do:
public String[] getFoo() { if (...) { return new String[0]; } ... }instead of :
public String[] getFoo() { if (...) { return null; } ... }
int i = 0, j = 4; // Error: Declare variables on separate lines
int i;
i = 4; // those two lines can be merged into "int i = 4"
int i = 0; // this affectation is useless
i = 4;
int i; // Declare variable as close as possible to where they are used
[...A lot of code that does NOT use i...]
i = 6;
Example of module configuration:
<module name="cs.UnitTestMethods"> <property name="severity" value="warning" /> <property name="filesToCheck" value="(.*[/\\])src([/\\]dummy[/\\]\w+)\.java$" /> <property name="testCases" value="$1test$2Test.java" /> <property name="minSemicolon" value="2"/> <!-- method with less than 2 semicolons are too simple to be tested --> </module>This example looks for every Java file in
src/dummy
or
src\dummy
. The TestCase must be in test/dummy
directory. Indeed, the testCases
property is a pattern applied
to retrieve the name of the TestCase. In the previous example, we just
replace the src
by test
and we add
Test
to the java filename.
The test method is considered correct if :
identToSearch
which default value is assert.*|fail
).
if (a==null) { // some code return null; } else { // other things }which can be changed into:
if (a==null) { // some code return null; } // other things
==
,!=
,&&
and
||
It detects the following code:
((a==null) && (b!=null))which is better read this way (except for people coming from LISP :-)
(a==null && b!=null)
So I've patched the standard UnusedImport, and added a method
isSeeOrThrowJavadocTag()
foo
and that
you also have some method called foo()
used.
It is not 100% accurate, since it can be confused if severals methods have the same name, but not the same number of arguments. It can also be confused if two methods have the same name in two differents classes.
<?xml version="1.0"?> <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd"> <module name="Checker"> <!-- Filtering some log message using cs.PatternFilter --> <module name="cs.PatternFilter"> <property name="ignoreFiles" value="^src\\cs\\(Avoid|Col)\w+.java" /> <property name="modules" value="cs\.NewIsNeverNull" /> </module> <module name="TreeWalker"> <!-- Some standard Checker --> <module name="LocalFinalVariableName" /> <module name="LocalVariableName" /> <module name="MemberName" /> <module name="MethodName" /> <module name="PackageName"> <!-- Some csplugin Checker --> <module name="cs.CollapseIfStatement" /> <module name="cs.AvoidNegativeLogic" /> <module name="cs.DeclareVariableInItsBloc" /> <module name="cs.TooEarlyVariableDeclaration" /> <module name="cs.UnusedLocalVariable" /> <module name="cs.InstanceofIsNeverNull" /> <module name="cs.NewIsNeverNull" /> <module name="cs.UnnecessarilyElse" /> <module name="cs.HiddenCatchBloc" /> <module name="cs.UnusedImports" /> </module> </module>