- ]]>
- bug
-
-
-
-
- org.codenarc.rule.serialization.SerializableClassMustDefineSerialVersionUIDRule
- MINOR
-
-
- Classes that implement Serializable should define a serialVersionUID. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If you don't define serialVersionUID, the system will make one by hashing most of your class's features. Then if you change anything, the UID will change and Java won't let you reload old data.
-
-]]>
- bug
-
-
-
-
- org.codenarc.rule.serialization.SerialPersistentFieldsRule
- MINOR
-
-
- To use a Serializable object's serialPersistentFields correctly, it must be declared private, static, and final.
-
The Java Object Serialization Specification allows developers to manually define Serializable fields for a class by specifying them in the serialPersistentFields array. This feature will only work if serialPersistentFields is declared as private, static, and final. Also, specific to Groovy, the field must be of type ObjectStreamField[], and cannot be Object.
-
References:
-]]>
- bug
-
-
-
-
- org.codenarc.rule.serialization.EnumCustomSerializationIgnoredRule
- MINOR
-
-
- Checks for enums that define writeObject() or writeReplace() methods, or declare serialPersistentFields or serialVersionUID fields, all of which are ignored for enums.
-
-]]>
- design
-
-
-
- org.codenarc.rule.design.ImplementationAsTypeRule
- MINOR
-
-
- Checks for use of the following concrete classes when specifying the type of a method parameter, closure parameter, constructor parameter, method return type or field type. The corresponding interfaces should be used to specify the type instead.
-]]>
- design
-
-
-
-
- org.codenarc.rule.design.BooleanMethodReturnsNullRule
- MINOR
-
-
- Checks for a method with Boolean return type that returns an explicit null. A method that returns either Boolean.TRUE, Boolean.FALSE or null is an accident waiting to happen. This method can be invoked as though it returned a value of type boolean, and the compiler will insert automatic of the Boolean value. If a null value is returned, this will result in a NullPointerException.
- ]]>
- design
-
-
-
-
- org.codenarc.rule.design.ReturnsNullInsteadOfEmptyArrayRule
- MINOR
-
-
- If you have a method or closure that returns an array, then when there are no results return a zero-length (empty) array rather than null. It is often a better design to return a zero-length array rather than a null reference to indicate that there are no results (i.e., an list of results). This way, no explicit check for null is needed by clients of the method.
- ]]>
- design
-
+
- org.codenarc.rule.design.ReturnsNullInsteadOfEmptyCollectionRule
- MINOR
-
-
- If you have a method or closure that returns a collection, then when there are no results return a zero-length (empty) collection rather than null. It is often a better design to return a zero-length collection rather than a null reference to indicate that there are no results (i.e., an list of results). This way, no explicit check for null is needed by clients of the method.
+ org.codenarc.rule.convention.InvertedIfElseRule
+ MAJOR
+
+
+ An inverted statement is one in which there is a single if statement with a single else branch and the boolean test of the if is negated. For instance if (!x) false else true. It is usually clearer to write this as if (x) true else false.
]]>
- design
+ bug
- org.codenarc.rule.design.CompareToWithoutComparableRule
- MINOR
-
-
- If you implement a compareTo method then you should also implement the Comparable interface. If you don't then you could possibly get an exception if the Groovy == operator is invoked on your object. This is an issue fixed in Groovy 1.8 but present in previous versions.
-
Here is an example of code that produces a violation:
+ org.codenarc.rule.convention.ConfusingTernaryRule
+ MAJOR
+
+
+ In a ternary expression avoid negation in the test. For example, rephrase: (x != y) ? diff : same as: (x == y) ? same : diff. Consistent use of this rule makes the code easier to read. Also, this resolves trivial ordering problems, such as "does the error case go first?" or "does the common case go first?".
+
Example:
- class BadClass {
- int compareTo(Object o) { ... }
- }
+ (x != y) ? diff : same // triggers violation
+ (!x) ? diff : same // triggers violation
+
+ (x == y) ? same : diff // OK
+ (x) ? same : diff // OK
+
+ // this is OK, because of GroovyTruth there is no inverse of != null
+ (x != null) ? diff : same
+
+ // this is OK, because of GroovyTruth there is no inverse of != true
+ (x != true) ? diff : same
+
+ // this is OK, because of GroovyTruth there is no inverse of != false
+ (x != false) ? diff : same
]]>
- design
+ bug
-
+
- org.codenarc.rule.design.SimpleDateFormatMissingLocaleRule
- MINOR
-
-
- Be sure to specify a Locale when creating a new instance of SimpleDateFormat; the class is locale-sensitive. If you instantiate SimpleDateFormat without a Locale parameter, it will format the date and time according to the default Locale. Both the pattern and the Locale determine the format. For the same pattern, SimpleDateFormat may format a date and time differently if the Locale varies.
+ org.codenarc.rule.convention.CouldBeElvisRule
+ MAJOR
+
+
+ Catch an if block that could be written as an elvis expression.
+
Example of violations:
- // violation, missing locale
- new SimpleDateFormat('pattern')
+ if (!x) { // violation
+ x = 'some value'
+ }
- // OK, includes locale
- new SimpleDateFormat('pattern', Locale.US)
+ if (!x) // violation
+ x = "some value"
- // OK, includes a variable that perhaps is a locale
- new SimpleDateFormat('pattern', locale)
+ if (!params.max) { // violation
+ params.max = 10
+ }
+
+ x ?: 'some value' // OK
]]>
- design
+ bug
-
+
- org.codenarc.rule.design.AbstractClassWithoutAbstractMethodRule
+ org.codenarc.rule.convention.LongLiteralWithLowerCaseLRuleMINOR
-
-
- The abstract class does not contain any abstract methods. An abstract class suggests an incomplete implementation, which is to be completed by subclasses implementing the abstract methods. If the class is intended to be used as a base class only (not to be instantiated directly) a protected constructor can be provided prevent direct instantiation.
-
Example:
+
+
+ In Java and Groovy, you can specify long literals with the L or l character, for instance 55L or 24l. It is best practice to always use an uppercase L and never a lowercase l. This is because 11l rendered in some fonts may look like 111 instead of 11L.
+
Example of violations:
- public abstract class MyBaseClass {
- void method1() { }
- void method2() { }
- // consider using abstract methods or removing
- // the abstract modifier and adding protected constructors
- }
+ def x = 1l
+ def y = 55l
+]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.ParameterReassignmentRule
+ MAJOR
+
+
+ Checks for a method or closure parameter being reassigned to a new value within the body of the method/closure, which is a confusing and questionable practice. Use a temporary variable instead.
+
Example of violations:
- abstract class MyClass extends AbstractParent {
- // OK because parent is named Abstract.*
+ void myMethod(int a, String b) {
+ println a
+ b = 'new value' // violation
}
- abstract class MyClass extends BaseParent{
- // OK because parent is named Base.*
+
+ def myClosure1 = { int a, b ->
+ a = 123 // violation
}
]]>
- design
+ bug
-
+
- org.codenarc.rule.design.CloseWithoutCloseableRule
- MINOR
-
-
- If a class defines a "void close()" then that class should implement java.io.Closeable.
- ]]>
- design
-
+ org.codenarc.rule.convention.TernaryCouldBeElvisRule
+ MAJOR
+
+
+ Checks for ternary expressions where the and expressions are the same. These can be simplified to an expression.
+
Example of violations:
+
+ x ? x : false // violation; can simplify to x ?: false
-
-
- org.codenarc.rule.design.ConstantsOnlyInterfaceRule
- MINOR
-
-
- An interface should be used only to model a behaviour of a class: using an interface as a container of constants is a poor usage pattern. Example:
-
- public interface ConstantsInterface {
- public static final int CONSTANT_1 = 0
- public static final String CONSTANT_2 = "1"
- }
-
-]]>
- design
-
+ foo() ? foo() : bar() // violation; can simplify to foo() ?: bar()
+ foo(1) ? foo(1) : 123 // violation; can simplify to foo(1) ?: 123
-
-
- org.codenarc.rule.design.EmptyMethodInAbstractClassRule
- MINOR
-
-
- An empty method in an abstract class should be abstract instead, as developer may rely on this empty implementation rather than code the appropriate one.
-
- abstract class MyClass {
- def couldBeAbstract_1() {
- return null // Should be abstract method
- }
+ (x == y) ? same : diff // OK
+ x ? y : z // OK
+ x ? x + 1 : x + 2 // OK
+ x ? 1 : 0 // OK
+ x ? !x : x // OK
+ !x ? x : null // OK
- void couldBeAbstract_2() {
- // Should be abstract method
- }
- }
+ foo() ? bar() : 123 // OK
+ foo() ? foo(99) : 123 // OK
+ foo(x) ? foo() : 123 // OK
+ foo(1) ? foo(2) : 123 // OK
]]>
- design
-
-
-
-
- org.codenarc.rule.design.FinalClassWithProtectedMemberRule
- MINOR
-
-
- This rule finds classes marked final that contain protected members. If a class is final then it may not be subclassed, and there is therefore no point in having a member with protected visibility. Either the class should not be final or the member should be private or protected.
- ]]>
- design
+ bug
-
+
- org.codenarc.rule.design.PublicInstanceFieldRule
+ org.codenarc.rule.convention.VectorIsObsoleteRuleMINOR
-
-
- Using public fields is considered to be a bad design. Use properties instead.
+
+
+ Checks for references to the () obsolete java.util.Vector class. Use the Java Collections Framework classes instead, including ArrayList or Collections.synchronizedList(). See the JDK javadoc.
Example of violations:
- class Person {
- public String name
- }
+ def myList = new Vector() // violation
]]>
- design
+ bug
-
+
- org.codenarc.rule.design.StatelessSingletonRule
+ org.codenarc.rule.convention.HashtableIsObsoleteRuleMINOR
-
-
- There is no point in creating a stateless Singleton because there is nothing within the class that needs guarding and no side effects to calling the constructor. Just create new instances of the object or write a Utility class with static methods. In the long term, Singletons can cause strong coupling and hard to change systems.
-
If the class has any fields at all, other than a self reference, then it is not considered stateless. A self reference is a field of the same type as the enclosing type, or a field named instance or _instance. The field name self reference is a property named instanceRegex that defaults to the value 'instance|_instance'
+
+
+ Checks for references to the () obsolete java.util.Hashtable class. Use the Java Collections Framework classes instead, including HashMap or ConcurrentHashMap. See the JDK javadoc.
Example of violations:
- @groovy.lang.Singleton
- class Service {
- // violation: the class has no fields but is marked Singleton
- void processItem(item){
- }
- }
-
- class Service {
- // violation: the class has no fields other than 'instance' but is marked Singleton
- static instance
- void processItem(item){
- }
- }
-
- class Service { // violation
- static Service service
- void processItem(item){
- }
- }
+ def myMap = new Hashtable() // violation
]]>
- design
+ bug
-
+
- org.codenarc.rule.design.AbstractClassWithPublicConstructorRule
+ org.codenarc.rule.convention.IfStatementCouldBeTernaryRuleMINOR
-
-
- Checks for abstract classes that define a public constructor, which is useless and confusing.
-
The following code produces a violation:
-
- abstract class MyClass {
- MyClass() { }
- }
-
+
+
+ Checks for:
]]>
- design
+ bug
-
+
- org.codenarc.rule.design.BuilderMethodWithSideEffectsRule
- MINOR
-
-
- A builder method is defined as one that creates objects. As such, they should never be of void return type. If a method is named build, create, or make, then it should always return a value.
-
This rule has one property: methodNameRegex. The default value is (make.*|create.*|build.*). Update this property if you have some other naming convention for your builder methods.
+ org.codenarc.rule.convention.NoDefRule
+ MAJOR
+
+
+ Do not allow using the def keyword in code. Use a specific type instead.
+
NOTE: This rule applies to the text contents of a rather than a specific , so it does not support the and configuration properties.
]]>
- design
+ bug
+
+ excludeRegex
+
+
-
+
- org.codenarc.rule.design.PrivateFieldCouldBeFinalRule.fixed
+ org.codenarc.rule.convention.TrailingCommaRuleMAJOR
-
-
- This rule finds private fields that are only set within a or . Such fields can safely be made final.
+
+
+ Check whether list and map literals contain optional trailing comma. Rationale: Putting this comma in make is easier to change the order of the elements or add new elements on the end.
+
This is valid code:
+
+ int[] array1 = [] // one line declaration
+ int[] array2 = [ // empty list
+ ]
+ int[] array3 = [1,2,3] // one line declaration
+ int[] array4 = [1,
+ 2,
+ 3, // contains trailing comma
+ ]
+
+
+ int[] array2 = [1,
+ 2 // there is no trailing comma
+ ]
+
]]>
- design
+ bug
- ignoreFieldNames
-
+ checkList
+
+ true
- ignoreJpaEntities
-
- false
+ checkMap
+
+ true
-
+
- org.codenarc.rule.design.CloneWithoutCloneableRule
+ org.codenarc.rule.convention.NoTabCharacterRule
+ MAJOR
+
+
+ Checks that all source files do not contain the tab character.
+]]>
+ bug
+
+
+
+
+
+ org.codenarc.rule.design.CloneableWithoutCloneRuleMINOR
-
-
- The method clone() should only be declared if the class implements the Cloneable interface.
-
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
-
Example of violations:
+
+
+ Checks for classes that implement the java.lang.Cloneable interface without implementing the clone() method.
+
Here is an example of code that produces a violation:
- class ValueClass {
- ValueClass clone() {
- }
+ class BadClass implements Cloneable {
+ def someMethod()
}
]]>design
-
- org.codenarc.rule.design.LocaleSetDefaultRule
+ org.codenarc.rule.design.ImplementationAsTypeRuleMINOR
-
-
- Checks for calls to Locale.setDefault(), or Locale.default = Xxx, which sets the Locale across the entire JVM. That can impact other applications on the same web server, for instance.
-
From the java.util.Locale javadoc for setDefault: should only be used if the caller is prepared to reinitialize locale-sensitive code running within the same Java Virtual Machine.>
+
+
+ Checks for use of the following concrete classes when specifying the type of a method parameter, closure parameter, constructor parameter, method return type or field type. The corresponding interfaces should be used to specify the type instead.
]]>design
-
+
- org.codenarc.rule.design.ToStringReturnsNullRule
+ org.codenarc.rule.design.BooleanMethodReturnsNullRuleMINOR
-
-
- Checks for toString() methods that return null. This is unconventional and could cause unexpected NullPointerExceptions from normal or implicit use of toString().
-
Example of violations:
-
- class MyClass {
- String toString() {
- if (foo()) {
- return 'MyClass'
- } else {
- return null // violation
- }
- }
- }
+
+
+ Checks for a method with Boolean return type that returns an explicit null. A method that returns either Boolean.TRUE, Boolean.FALSE or null is an accident waiting to happen. This method can be invoked as though it returned a value of type boolean, and the compiler will insert automatic of the Boolean value. If a null value is returned, this will result in a NullPointerException.
+ ]]>
+ design
+
- class MyClass {
- String toString() {
- calculateStuff()
- null // violation
- }
- }
+
+
+ org.codenarc.rule.design.ReturnsNullInsteadOfEmptyArrayRule
+ MINOR
+
+
+ If you have a method or closure that returns an array, then when there are no results return a zero-length (empty) array rather than null. It is often a better design to return a zero-length array rather than a null reference to indicate that there are no results (i.e., an list of results). This way, no explicit check for null is needed by clients of the method.
+ ]]>
+ design
+
- class MyClass {
- String toString() { // violation - implicit return of null
- }
+
+
+ org.codenarc.rule.design.ReturnsNullInsteadOfEmptyCollectionRule
+ MINOR
+
+
+ If you have a method or closure that returns a collection, then when there are no results return a zero-length (empty) collection rather than null. It is often a better design to return a zero-length collection rather than a null reference to indicate that there are no results (i.e., an list of results). This way, no explicit check for null is needed by clients of the method.
+ ]]>
+ design
+
+
+
+
+ org.codenarc.rule.design.CompareToWithoutComparableRule
+ MINOR
+
+
+ If you implement a compareTo method then you should also implement the Comparable interface. If you don't then you could possibly get an exception if the Groovy == operator is invoked on your object. This is an issue fixed in Groovy 1.8 but present in previous versions.
+
Here is an example of code that produces a violation:
+
+ class BadClass {
+ int compareTo(Object o) { ... }
}
]]>design
-
+
- org.codenarc.rule.design.InstanceofRule
+ org.codenarc.rule.design.SimpleDateFormatMissingLocaleRuleMINOR
-
-
- Checks for use of the instanceof operator. Prefer using instead.
-
Use the ignoreTypeNames property to configure ignored type names (the class name specified as the right-hand expression of the instanceof). It defaults to ignoring instanceof checks against exception classes.
-
Here are a couple references that discuss the problems with using instanceof and the preference for using instead:
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
-
Example of violations:
+
+
+ Be sure to specify a Locale when creating a new instance of SimpleDateFormat; the class is locale-sensitive. If you instantiate SimpleDateFormat without a Locale parameter, it will format the date and time according to the default Locale. Both the pattern and the Locale determine the format. For the same pattern, SimpleDateFormat may format a date and time differently if the Locale varies.
- class MyClass {
- boolean isRunnable = this instanceof Runnable // violation
- }
+ // violation, missing locale
+ new SimpleDateFormat('pattern')
+
+ // OK, includes locale
+ new SimpleDateFormat('pattern', Locale.US)
+
+ // OK, includes a variable that perhaps is a locale
+ new SimpleDateFormat('pattern', locale)
]]>design
-
- ignoreTypeNames
-
- *Exceptions
-
-
+
- org.codenarc.rule.design.NestedForLoopRule
- MAJOR
-
-
- Reports classes with nested for loops.
-
Example of violations:
+ org.codenarc.rule.design.AbstractClassWithoutAbstractMethodRule
+ MINOR
+
+
+ The abstract class does not contain any abstract methods. An abstract class suggests an incomplete implementation, which is to be completed by subclasses implementing the abstract methods. If the class is intended to be used as a base class only (not to be instantiated directly) a protected constructor can be provided prevent direct instantiation.
+
Example:
-for (int i = 0; i < 100; ++i) {
- for (int j = 0; j < 100; ++j) { // violation
- println i + j
+ public abstract class MyBaseClass {
+ void method1() { }
+ void method2() { }
+ // consider using abstract methods or removing
+ // the abstract modifier and adding protected constructors
}
-}
-
-for (int i = 0; i < 100; ++i) {
- for (int j = 0; j < 100; ++j) { // violation
- println i + j
+
+
+ abstract class MyClass extends AbstractParent {
+ // OK because parent is named Abstract.*
}
- for (int j = 0; j < 100; ++j) { // violation
- println i + j
+ abstract class MyClass extends BaseParent{
+ // OK because parent is named Base.*
}
-}
+
+]]>
+ design
+
-for (int i = 0; i < 100; ++i) {
- for (int j = 0; j < 100; ++j) { // violation
- for (int k = 0; k < 100; ++k) { // violation
- println i + j + k
- }
+
+
+ org.codenarc.rule.design.CloseWithoutCloseableRule
+ MINOR
+
+
+ If a class defines a "void close()" then that class should implement java.io.Closeable.
+ ]]>
+ design
+
+
+
+
+ org.codenarc.rule.design.ConstantsOnlyInterfaceRule
+ MINOR
+
+
+ An interface should be used only to model a behaviour of a class: using an interface as a container of constants is a poor usage pattern. Example:
+
+ public interface ConstantsInterface {
+ public static final int CONSTANT_1 = 0
+ public static final String CONSTANT_2 = "1"
}
-}
]]>design
-
+
- org.codenarc.rule.design.AssignmentToStaticFieldFromInstanceMethodRule
+ org.codenarc.rule.design.EmptyMethodInAbstractClassRuleMINOR
-
-
- Checks for assignment to a static field from an instance method.
-
Influenced by the AssignmentToNonFinalStatic rule from PMD, and the ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD rule from FindBugs.
-
Example of violations:
+
+
+ An empty method in an abstract class should be abstract instead, as developer may rely on this empty implementation rather than code the appropriate one.
- class MyClass {
- private static field1
- protected static String field2 = 'abc'
- public static int field3 = 123
- static String property1 = 'abc'
- private static final NAME = 'joe'
-
- private void doStuff() {
- field1 = new Object() // violation
- field2 = 'xxx' // violation
- field3 = 999 // violation
- property1 = 'xxx' // violation
+ abstract class MyClass {
+ def couldBeAbstract_1() {
+ return null // Should be abstract method
+ }
- final NAME = 'martin' // no violation; local var hides static field
+ void couldBeAbstract_2() {
+ // Should be abstract method
}
}
@@ -2490,330 +2366,624 @@ for (int i = 0; i < 100; ++i) {
design
-
-
-
+
- org.codenarc.rule.dry.DuplicateNumberLiteralRule
+ org.codenarc.rule.design.FinalClassWithProtectedMemberRuleMINOR
-
-
- This rule checks for duplicate number literals within the current class.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
+
+ This rule finds classes marked final that contain protected members. If a class is final then it may not be subclassed, and there is therefore no point in having a member with protected visibility. Either the class should not be final or the member should be private or protected.
]]>
- bug
-
- ignoreNumbers
-
- 0,1
-
+ design
-
+
- org.codenarc.rule.dry.DuplicateStringLiteralRule
+ org.codenarc.rule.design.PublicInstanceFieldRuleMINOR
-
-
- This rule checks for duplicate String literals within the current class.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
- ]]>
- bug
-
- ignoreStrings
-
- '' (empty string)
-
+
+
+ Using public fields is considered to be a bad design. Use properties instead.
+
Example of violations:
+
+ class Person {
+ public String name
+ }
+
+]]>
+ design
-
+
- org.codenarc.rule.dry.DuplicateMapLiteralRule
- MAJOR
-
-
- This rule checks for duplicate
- def var1 = [a:7+5]
- def var2 = [a:7+5] // not a violation; contains a non-constant/literal expression
+
+
+ org.codenarc.rule.design.AbstractClassWithPublicConstructorRule
+ MINOR
+
+
+ Checks for abstract classes that define a public constructor, which is useless and confusing.
+
The following code produces a violation:
+
+ abstract class MyClass {
+ MyClass() { }
+ }
]]>
- bug
+ design
- org.codenarc.rule.dry.DuplicateListLiteralRule
- MAJOR
-
-
- This rule checks for duplicate literals within the current class. This rule only checks for s where values are all constants or literals.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
-
Examples of violations:
+ org.codenarc.rule.design.BuilderMethodWithSideEffectsRule
+ MINOR
+
+
+ A builder method is defined as one that creates objects. As such, they should never be of void return type. If a method is named build, create, or make, then it should always return a value.
+
This rule has one property: methodNameRegex. The default value is (make.*|create.*|build.*). Update this property if you have some other naming convention for your builder methods.
]]>
- bug
-
-
-
-
-
- org.codenarc.rule.exceptions.CatchErrorRule
- MINOR
-
-
- Checks for catching a Error. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.
- ]]>
- error-handling
+ design
+
- org.codenarc.rule.exceptions.CatchExceptionRule
- MINOR
-
-
- Checks for catching a Exception. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.
- ]]>
- error-handling
+ org.codenarc.rule.design.PrivateFieldCouldBeFinalRule.fixed
+ MAJOR
+
+
+ This rule finds private fields that are only set within a or . Such fields can safely be made final.
+]]>
+ design
+
+ ignoreFieldNames
+
+
+
+ ignoreJpaEntities
+
+ false
+
+
- org.codenarc.rule.exceptions.CatchNullPointerExceptionRule
+ org.codenarc.rule.design.CloneWithoutCloneableRuleMINOR
-
-
- Checks for catching a NullPointerException. Catching NullPointerException is never appropriate. It should be avoided in the first place with proper null checking, and it can mask underlying errors.
- ]]>
- error-handling
+
+
+ The method clone() should only be declared if the class implements the Cloneable interface.
+
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
+]]>
+ design
+
- org.codenarc.rule.exceptions.CatchRuntimeExceptionRule
+ org.codenarc.rule.design.LocaleSetDefaultRuleMINOR
-
-
- Checks for catching a RuntimeException. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.
- ]]>
- error-handling
-
+
+
+ Checks for calls to Locale.setDefault(), or Locale.default = Xxx, which sets the Locale across the entire JVM. That can impact other applications on the same web server, for instance.
+
From the java.util.Locale javadoc for setDefault: should only be used if the caller is prepared to reinitialize locale-sensitive code running within the same Java Virtual Machine.>
+
Example of violations:
+
+ Locale.setDefault(Locale.UK) // violation
+ java.util.Locale.setDefault(Locale.FRANCE) // violation
+ Locale.setDefault(Locale.Category.DISPLAY, Locale.JAPAN) // violation
-
- org.codenarc.rule.exceptions.CatchThrowableRule
- MINOR
-
-
- Checks for catching a Throwable. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.
- ]]>
- error-handling
+ Locale.default = Locale.UK // violation
+
+]]>
+ design
+
- org.codenarc.rule.exceptions.ThrowErrorRule
+ org.codenarc.rule.design.ToStringReturnsNullRuleMINOR
-
-
- Checks for throwing an instance of java.lang.Error. This is not appropriate within normal application code. Throw an instance of a more specific exception subclass instead.
- ]]>
- error-handling
-
+
+
+ Checks for toString() methods that return null. This is unconventional and could cause unexpected NullPointerExceptions from normal or implicit use of toString().
+
Example of violations:
+
+ class MyClass {
+ String toString() {
+ if (foo()) {
+ return 'MyClass'
+ } else {
+ return null // violation
+ }
+ }
+ }
-
- org.codenarc.rule.exceptions.ThrowExceptionRule
- MINOR
-
-
- Checks for throwing an instance of java.lang.Exception. Throw an instance of a more specific exception subclass instead.
- ]]>
- error-handling
-
+ class MyClass {
+ String toString() {
+ calculateStuff()
+ null // violation
+ }
+ }
-
- org.codenarc.rule.exceptions.ThrowNullPointerExceptionRule
- MINOR
-
-
- Checks for throwing an instance of java.lang.NullPointerException. Applications should never throw a NullPointerException.
- ]]>
- error-handling
+ class MyClass {
+ String toString() { // violation - implicit return of null
+ }
+ }
+
+]]>
+ design
+
- org.codenarc.rule.exceptions.ThrowRuntimeExceptionRule
+ org.codenarc.rule.design.InstanceofRuleMINOR
-
-
- Checks for throwing an instance of java.lang.RuntimeException. Throw an instance of a more specific exception subclass instead.
- ]]>
- error-handling
+
+
+ Checks for use of the instanceof operator. Prefer using instead.
+
Use the ignoreTypeNames property to configure ignored type names (the class name specified as the right-hand expression of the instanceof). It defaults to ignoring instanceof checks against exception classes.
+
Here are a couple references that discuss the problems with using instanceof and the preference for using instead:
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
Example of violations:
+
+ class MyClass {
+ boolean isRunnable = this instanceof Runnable // violation
+ }
+
+]]>
+ design
+
+ ignoreTypeNames
+
+ *Exceptions
+
+
- org.codenarc.rule.exceptions.ThrowThrowableRule
- MINOR
-
-
- Checks for throwing an instance of java.lang.Throwable. Throw an instance of a more specific exception subclass instead.
+ org.codenarc.rule.design.NestedForLoopRule
+ MAJOR
+
+
+ Reports classes with nested for loops.
+
Example of violations:
+
+for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) { // violation
+ println i + j
+ }
+}
+
+for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) { // violation
+ println i + j
+ }
+ for (int j = 0; j < 100; ++j) { // violation
+ println i + j
+ }
+}
+
+for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) { // violation
+ for (int k = 0; k < 100; ++k) { // violation
+ println i + j + k
+ }
+ }
+}
+
]]>
- error-handling
+ design
-
+
- org.codenarc.rule.exceptions.CatchIllegalMonitorStateExceptionRule
+ org.codenarc.rule.design.AssignmentToStaticFieldFromInstanceMethodRuleMINOR
-
-
- Dubious catching of IllegalMonitorStateException. IllegalMonitorStateException is generally only thrown in case of a design flaw in your code (calling wait or notify on an object you do not hold a lock on).
- ]]>
- error-handling
+
+
+ Checks for assignment to a static field from an instance method.
+
Influenced by the AssignmentToNonFinalStatic rule from PMD, and the ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD rule from FindBugs.
+
Example of violations:
+
+ class MyClass {
+ private static field1
+ protected static String field2 = 'abc'
+ public static int field3 = 123
+ static String property1 = 'abc'
+ private static final NAME = 'joe'
+
+ private void doStuff() {
+ field1 = new Object() // violation
+ field2 = 'xxx' // violation
+ field3 = 999 // violation
+ property1 = 'xxx' // violation
+
+ final NAME = 'martin' // no violation; local var hides static field
+ }
+ }
+
+]]>
+ design
+
+
- org.codenarc.rule.exceptions.ConfusingClassNamedExceptionRule
+ org.codenarc.rule.dry.DuplicateNumberLiteralRuleMINOR
-
-
- This class is not derived from another exception, but ends with 'Exception'. This will be confusing to users of this class.
+
+
+ This rule checks for duplicate number literals within the current class.
+
Code containing duplicate literals can usually be improved by declaring the as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
]]>
- error-handling
+ bug
+
+ ignoreNumbers
+
+ 0,1
+
- org.codenarc.rule.exceptions.ReturnNullFromCatchBlockRule
+ org.codenarc.rule.dry.DuplicateStringLiteralRuleMINOR
-
-
- Returning null from a catch block often masks errors and requires the client to handle error codes. In some coding styles this is discouraged. This rule ignores methods with void return type.
+
+
+ This rule checks for duplicate String literals within the current class.
+
Code containing duplicate literals can usually be improved by declaring the as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
]]>
- error-handling
+ bug
+
+ ignoreStrings
+
+ '' (empty string)
+
-
+
- org.codenarc.rule.exceptions.CatchArrayIndexOutOfBoundsExceptionRule
+ org.codenarc.rule.dry.DuplicateMapLiteralRule
+ MAJOR
+
+
+ This rule checks for duplicate literals within the current class. This rule only checks for s where the keys and values are all constants or literals.
+
Code containing duplicate literals can usually be improved by declaring the as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+ def name
+ def var1 = [(name):1, b:1, c:1]
+ def var2 = [(name):1, b:1, c:1] // not a violation; name is a variable
+
+ def var1 = [a:1, b:['x', name]]
+ def var2 = [a:1, b:['x', name]] // not a violation; name is a variable
+
+ def var1 = [a:7+5]
+ def var2 = [a:7+5] // not a violation; contains a non-constant/literal expression
+
+]]>
+ bug
+
+
+
+
+ org.codenarc.rule.dry.DuplicateListLiteralRule
+ MAJOR
+
+
+ This rule checks for duplicate literals within the current class. This rule only checks for s where values are all constants or literals.
+
Code containing duplicate literals can usually be improved by declaring the as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+ def name
+ def var1 = [name, 'b', 'c']
+ def var2 = [name, 'b', 'c'] // not a violation; name is a variable
+
+ def var1 = [1, 7+5]
+ def var2 = [1, 7+5] // not a violation; contains a non-constant/literal expression
+
+]]>
+ bug
+
+
+
+
+
+ org.codenarc.rule.exceptions.CatchErrorRuleMINOR
-
-
- Checks for catching a ArrayIndexOutOfBoundsException. Catching ArrayIndexOutOfBoundsException should be avoided in the first place by checking the array size before accessing an array element. Catching the exception may mask underlying errors.
+
+
+ Checks for catching a Error. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.
]]>error-handling
-
- org.codenarc.rule.exceptions.CatchIndexOutOfBoundsExceptionRule
+ org.codenarc.rule.exceptions.CatchExceptionRuleMINOR
-
-
- Checks for catching a IndexOutOfBoundsException. Catching IndexOutOfBoundsException should be avoided in the first place by checking for a valid index before accessing an indexed element. Catching the exception may mask underlying errors.
+
+
+ Checks for catching a Exception. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.
]]>error-handling
-
- org.codenarc.rule.exceptions.MissingNewInThrowStatementRule
+ org.codenarc.rule.exceptions.CatchNullPointerExceptionRuleMINOR
-
-
- A common Groovy mistake when throwing exceptions is to forget the new keyword. For instance, throw RuntimeException() instead of throw new RuntimeException(). If the error path is not unit tested then the production system will throw a Method Missing exception and hide the root cause. This rule finds constructs like throw RuntimeException() that look like a new keyword was meant to be used but forgotten.
-
The following code will all cause violations:
-
- throw RuntimeException() // ends in Exceptions, first letter Capitalized
- throw RuntimeFailure() // ends in Failure, first letter Capitalized
- throw RuntimeFault(foo) // ends in Fault, first letter Capitalized
-
-
- throw new RuntimeException()
- throw runtimeFailure() // first letter lowercase, assumed to be method call
-
-]]>
+
+
+ Checks for catching a NullPointerException. Catching NullPointerException is never appropriate. It should be avoided in the first place with proper null checking, and it can mask underlying errors.
+ ]]>error-handling
-
- org.codenarc.rule.exceptions.ExceptionExtendsErrorRule
+ org.codenarc.rule.exceptions.CatchRuntimeExceptionRuleMINOR
-
-
- Errors are system exceptions. Do not extend them.
-
Examples:
-
- class MyError extends Error { } // violation
- class MyError extends java.lang.Error { } // violation
-
- class MyException extends Exception { } // OK
-
-]]>
+
+
+ Checks for catching a RuntimeException. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.
+ ]]>error-handling
-
- org.codenarc.rule.exceptions.SwallowThreadDeathRule
+ org.codenarc.rule.exceptions.CatchThrowableRuleMINOR
-
-
- Detects code that catches java.lang.ThreadDeath without re-throwing it.
-
-]]>
+
+
+ Checks for catching a Throwable. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.
+ ]]>error-handling
-
+
+ org.codenarc.rule.exceptions.ThrowErrorRule
+ MINOR
+
+
+ Checks for throwing an instance of java.lang.Error. This is not appropriate within normal application code. Throw an instance of a more specific exception subclass instead.
+ ]]>
+ error-handling
+
+
+
+ org.codenarc.rule.exceptions.ThrowExceptionRule
+ MINOR
+
+
+ Checks for throwing an instance of java.lang.Exception. Throw an instance of a more specific exception subclass instead.
+ ]]>
+ error-handling
+
+
+
+ org.codenarc.rule.exceptions.ThrowNullPointerExceptionRule
+ MINOR
+
+
+ Checks for throwing an instance of java.lang.NullPointerException. Applications should never throw a NullPointerException.
+ ]]>
+ error-handling
+
+
+
+ org.codenarc.rule.exceptions.ThrowRuntimeExceptionRule
+ MINOR
+
+
+ Checks for throwing an instance of java.lang.RuntimeException. Throw an instance of a more specific exception subclass instead.
+ ]]>
+ error-handling
+
+
+
+ org.codenarc.rule.exceptions.ThrowThrowableRule
+ MINOR
+
+
+ Checks for throwing an instance of java.lang.Throwable. Throw an instance of a more specific exception subclass instead.
+]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.CatchIllegalMonitorStateExceptionRule
+ MINOR
+
+
+ Dubious catching of IllegalMonitorStateException. IllegalMonitorStateException is generally only thrown in case of a design flaw in your code (calling wait or notify on an object you do not hold a lock on).
+ ]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.ConfusingClassNamedExceptionRule
+ MINOR
+
+
+ This class is not derived from another exception, but ends with 'Exception'. This will be confusing to users of this class.
+ ]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.ReturnNullFromCatchBlockRule
+ MINOR
+
+
+ Returning null from a catch block often masks errors and requires the client to handle error codes. In some coding styles this is discouraged. This rule ignores methods with void return type.
+ ]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.CatchArrayIndexOutOfBoundsExceptionRule
+ MINOR
+
+
+ Checks for catching a ArrayIndexOutOfBoundsException. Catching ArrayIndexOutOfBoundsException should be avoided in the first place by checking the array size before accessing an array element. Catching the exception may mask underlying errors.
+ ]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.CatchIndexOutOfBoundsExceptionRule
+ MINOR
+
+
+ Checks for catching a IndexOutOfBoundsException. Catching IndexOutOfBoundsException should be avoided in the first place by checking for a valid index before accessing an indexed element. Catching the exception may mask underlying errors.
+ ]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.MissingNewInThrowStatementRule
+ MINOR
+
+
+ A common Groovy mistake when throwing exceptions is to forget the new keyword. For instance, throw RuntimeException() instead of throw new RuntimeException(). If the error path is not unit tested then the production system will throw a Method Missing exception and hide the root cause. This rule finds constructs like throw RuntimeException() that look like a new keyword was meant to be used but forgotten.
+
The following code will all cause violations:
+
+ throw RuntimeException() // ends in Exceptions, first letter Capitalized
+ throw RuntimeFailure() // ends in Failure, first letter Capitalized
+ throw RuntimeFault(foo) // ends in Fault, first letter Capitalized
+
+
+ throw new RuntimeException()
+ throw runtimeFailure() // first letter lowercase, assumed to be method call
+
+]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.ExceptionExtendsErrorRule
+ MINOR
+
+
+ Errors are system exceptions. Do not extend them.
+
Examples:
+
+ class MyError extends Error { } // violation
+ class MyError extends java.lang.Error { } // violation
+
+ class MyException extends Exception { } // OK
+
+]]>
+ error-handling
+
+
+
+
+ org.codenarc.rule.exceptions.SwallowThreadDeathRule
+ MINOR
+
+
+ Detects code that catches java.lang.ThreadDeath without re-throwing it.
+
+]]>
+ error-handling
+
+
+
org.codenarc.rule.exceptions.ExceptionNotThrownRuleMINOR
@@ -2858,2971 +3028,2536 @@ for (int i = 0; i < 100; ++i) {
error-handling
-
+
+
- org.codenarc.rule.generic.IllegalRegexRule.fixed
- MAJOR
-
-
- Checks for a specified illegal regular expression within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
+ org.codenarc.rule.formatting.BracesForClassRule
+ MINOR
+
+
+ Checks the location of the opening brace (\{) for classes. By default, requires them on the same line, but the sameLine property can be set to false to override this.
+
NOTE: This rule ignores annotation types, e.g. @interface MyAnnotation {}.
]]>
- bug
+ convention
- regex
-
+ sameLine
+ true
+
- org.codenarc.rule.generic.RequiredRegexRule.fixed
- MAJOR
-
-
- Checks for a specified regular expression that must exist within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
+ org.codenarc.rule.formatting.LineLengthRule
+ MINOR
+
+
+ Checks the maximum length for each line of source code. It checks for number of characters, so lines that include tabs may appear longer than the allowed number when viewing the file. The maximum line length can be configured by setting the length property, which defaults to 120.
+
NOTE: This rule does not support the @SuppressAnnotations annotation or the classname-based rule properties (applyToClassNames, doNotApplyToClassNames) to enable/disable the rule. If you want to specify or restrict where this rule is applied, you must use the file-based rule properties: applyToFileNames, doNotApplyToFileNames, applyToFilesMatching and doNotApplyToFilesMatching.
]]>
- bug
+ convention
- regex
-
+ ignoreImportStatements
+
+ true
+
+
+ ignoreLineRegex
+
+
+
+ ignorePackageStatements
+
+ true
+
+
+ length
+
+ 120
+
- org.codenarc.rule.generic.RequiredStringRule.fixed
- MAJOR
-
-
- Checks for a specified text string that must exist within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
+ org.codenarc.rule.formatting.BracesForForLoopRule
+ MINOR
+
+
+ Checks the location of the opening brace (\{) for for loops. By default, requires them on the same line, but the sameLine property can be set to false to override this.
]]>
- bug
+ convention
- string
-
+ sameLine
+ true
+
- org.codenarc.rule.generic.StatelessClassRule.fixed
+ org.codenarc.rule.formatting.BracesForIfElseRuleMINOR
-
-
- Checks for non-final fields on a class. The intent of this rule is to check a configured set of classes that should remain "stateless" and reentrant. One example might be Grails service classes which are singletons, by default, and so they should be reentrant.
-
This rule ignores final fields (either instance or static). Fields that are static and non-final, however, do cause a violation.
This rule also ignores all fields annotated with the @Inject annotation.
-
You can configure this rule to ignore certain fields either by name or by type. This can be useful to ignore fields that hold references to (static) dependencies (such as DAOs or Service objects) or static configuration.
-
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
- [[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
-
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.
-
[[3]] At least one of the (standard) applyToClassNames, applyToFileNames or applyToFilesMatching properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule to apply to a specific set of classes or files.
-
[[4]] This rule will not catch violations of true / if you define a final field whose value is itself mutable, e.g. a final HashMap.
-]]>
- bug
+
+
+ Checks the location of the opening brace (\{) for if statements. By default, requires them on the same line, but the sameLine property can be set to false to override this.
+]]>
+ convention
- addToIgnoreFieldNames
-
+ elseOnSameLineAsClosingBrace
+
+ true
- ignoreFieldNames
-
+ elseOnSameLineAsOpeningBrace
+
+ true
- ignoreFieldTypes
-
+ sameLine
+
+ true
-
-
-
-
- org.codenarc.rule.generic.IllegalPackageReferenceRule.fixed
- MINOR
-
-
- Checks for reference to any of the packages configured in packageNames.
-
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
-
This rule can be useful for governance and enforcement of . For instance, making sure that view or model classes, for instance, do not contain references to JDBC-specific packages (e.g. java.sql and javax.sql).
-
Here is an example configuration of this rule used to ensure that JDBC packages/classes are only referenced within DAO classes:
-
- ruleset {
- description "Example CodeNarc Ruleset"
-
- // ...
-
- IllegalPackageReference {
- name = 'UseJdbcOnlyInDaoClasses'
- priority = 2
- packageNames = 'groovy.sql, java.sql, javax.sql'
- doNotApplyToClassNames = 'com.example.framework.dao.*, *Dao, *DaoImpl'
- description = 'Reference to JDBC packages should be restricted to DAO classes.'
- }
- }
-
-]]>
- bug
- packageNames
-
+ validateElse
+
+ false
- org.codenarc.rule.generic.IllegalClassReferenceRule.fixed
- MINOR
-
-
- Checks for reference to any of the classes configured in classNames.
-
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
-
This rule can be useful for governance and enforcement of . For instance, making sure that view or model classes, for instance, do not contain references to DAO classes (e.g., *Dao).
-
Here is an example configuration of this rule used to ensure that DAO classes are not referenced from within model classes:
-]]>
- bug
-
- classNames
-
-
-
-
-
-
- org.codenarc.rule.generic.IllegalClassMemberRule.fixed
+ org.codenarc.rule.formatting.BracesForMethodRuleMINOR
-
-
- Checks for classes containing fields/properties/methods matching configured illegal member modifiers or not matching any of the configured allowed member modifiers.
-
Modifiers for fields and methods include:
-]]>
- bug
-
- allowedFieldModifiers
-
-
-
- allowedMethodModifiers
-
-
-
- allowedPropertyModifiers
-
-
-
- ignoreMethodNames
-
-
-
- ignoreMethodsWithAnnotationNames
-
-
-
- illegalFieldModifiers
-
-
-
- illegalMethodModifiers
-
-
+
+
+ Checks the location of the opening brace (\{) for constructors and methods. By default, requires them on the same line, but the sameLine property can be set to false to override this.
+ ]]>
+ convention
- illegalPropertyModifiers
-
+ sameLine
+ true
-
+
- org.codenarc.rule.generic.IllegalStringRule.fixed
+ org.codenarc.rule.formatting.BracesForTryCatchFinallyRuleMINOR
-
-
- Checks for a specified illegal string within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
+
+
+ Checks the location of the opening brace (\{) for try statements. By default, requires them on the line, but the sameLine property can be set to false to override this.
]]>
- bug
+ convention
- string
-
+ sameLine
+ true
-
+
- org.codenarc.rule.generic.IllegalSubclassRule.fixed
+ org.codenarc.rule.formatting.ClassJavadocRuleMINOR
-
-
- Checks for classes that extend one of the specified set of illegal superclasses.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
+
+
+ Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.
]]>
- bug
-
- superclassNames
-
-
+ convention
-
-
+
- org.codenarc.rule.grails.GrailsPublicControllerMethodRule.fixed
- MINOR
-
-
- Rule that checks for public methods on Grails controller classes. Static methods are ignored.
-
Grails controller actions and interceptors are defined as properties on the controller class. Public methods on a controller class are unnecessary. They break encapsulation and can be confusing.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' folder. You can override this with a different regular expression value if appropriate.
-
This rule also sets the default value of applyToClassNames to only match class names ending in 'Controller'. You can override this with a different class name pattern (String with wildcards) if appropriate.
- ]]>
- grails
-
- ignoreMethodNames
-
-
+ org.codenarc.rule.formatting.SpaceAfterCommaRule
+ MAJOR
+
+
+ Checks that there is at least one space or whitespace following each comma. That includes checks for method and closure declaration parameter lists, method call parameter lists, Map literals and List literals.
+
Known limitations:
+]]>
+ convention
+
- org.codenarc.rule.grails.GrailsSessionReferenceRule
- MINOR
-
-
- Rule that checks for references to the session object from within Grails controller and taglib classes.
-
This rule is intended as a "governance" rule to enable monitoring and controlling access to the session from within application source code. Storing objects in the session may inhibit scalability and/or performance and should be carefully considered.
-
Note that this rule does not check for direct access to the session from within GSP (Groovy Server Pages) files.
-
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate session access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
- ]]>
- grails
+ org.codenarc.rule.formatting.SpaceAfterSemicolonRule
+ MAJOR
+
+
+ Check that there is at least one space (blank) or whitespace following a semicolon that separates:
+]]>
+ convention
+
- org.codenarc.rule.grails.GrailsServletContextReferenceRule
- MINOR
-
-
- Rule that checks for references to the servletContext object from within Grails controller and taglib classes.
-
This rule is intended as a "governance" rule to enable monitoring and controlling access to the servletContext from within application source code. Storing objects in the servletContext may inhibit scalability and/or performance and should be carefully considered. Furthermore, access to the servletContext is not synchronized, so reading/writing objects from the servletConext must be manually synchronized, as described in The Definitive Guide to Grails (2nd edition).
-
Note that this rule does not check for direct access to the servletContext from within GSP (Groovy Server Pages) files.
-
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate servletContext access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
- ]]>
- grails
+ org.codenarc.rule.formatting.SpaceAroundOperatorRule
+ MAJOR
+
+
+ Check that there is at least one space (blank) or whitespace around each binary operator, including: +, -, *, /, \>\>, \<\<, &&, ||, &, |, ?:, =, "as".
+
Do not check dot ('.') operator. Do not check unary operators (!, +, -, ++, --, ?.). Do not check array ('[') operator.
+
Known limitations:
+]]>
+ convention
+
- org.codenarc.rule.grails.GrailsStatelessServiceRule
- MINOR
-
-
- Checks for non-final fields on a Grails service class. Grails service classes are singletons by default, and so they should be reentrant. In most cases, this implies (or at least encourages) that they should be stateless.
-
This rule ignores (i.e., does not cause violations for) the following:
+ org.codenarc.rule.formatting.SpaceBeforeOpeningBraceRule
+ MAJOR
+
+
+ Check that there is at least one space (blank) or whitespace before each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+
Ignores classes annotated with @ToString or @Canonical.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
Ignores classes annotated with @EqualsAndHashCode or @Canonical.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
- ]]>
- grails
-
-
- org.codenarc.rule.grails.GrailsDuplicateMappingRule
- MINOR
-
-
- Check for duplicate name in a Grails domain class mapping. Duplicate names/entries are legal, but can be confusing and error-prone.
-
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
-
Example of violations:
+ org.codenarc.rule.formatting.SpaceAfterOpeningBraceRule
+ MAJOR
+
+
+ Check that there is at least one space (blank) or whitespace after each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+ Examples of violations:
- class Person {
- String firstName
- String lastName
+ class MyClass{int count } // violation
- static mapping = {
- table 'people'
- firstName column: 'First_Name'
- lastName column: 'Last_Name'
- firstName column: 'First_Name' // violation
- table 'people2' // violation
- }
- }
+ interface MyInterface {static final OK = 1 }// violation
+
+ enum MyEnum {OK, BAD } // violation
+
+ def myMethod() {int count } // violation
+
+ if (ready) {println 9 } // violation
+
+ if (ready) {
+ } else {println 99} // violation
+
+ for (int i=0; i<10; i++) {println i } // violation
+
+ for (String name in names) {println name } // violation
+
+ for (String name: names) {println name } // violation
+
+ while (ready) {println time } // violation
+
+ try {doStuff() // violation
+ } catch(Exception e) {x=77 } // violation
+ } finally {println 'error' } // violation
+
+ list.each {name -> } // violation
+
+ shouldFail(Exception) {doStuff() } // violation
]]>
- grails
+ convention
+
+ checkClosureMapEntryValue
+
+ true
+
+
+ ignoreEmptyBlock
+
+ false
+
- org.codenarc.rule.grails.GrailsDuplicateConstraintRule
- MINOR
-
-
- Check for duplicate name in a Grails domain class constraints. Duplicate names/entries are legal, but can be confusing and error-prone.
-
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
+ org.codenarc.rule.formatting.SpaceAfterClosingBraceRule
+ MAJOR
+
+
+ Check that there is at least one space (blank) or whitespace after each closing brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
+ Known limitations:
]]>
- grails
+ convention
+
+ checkClosureMapEntryValue
+
+ true
+
-
+
- org.codenarc.rule.grails.GrailsDomainReservedSqlKeywordNameRule
- MINOR
-
-
- Forbids usage of SQL reserved keywords as class or field names in Grails domain classes. Naming a domain class (or its field) with such a keyword causes SQL schema creation errors and/or redundant table/column name mappings.
-
Note: due to limited type information available during CodeNarc's operation, this rule will report fields of type java.io.Serializable, but not of its implementations. Please specify any implementations used as domain properties in additionalHibernateBasicTypes.
+ org.codenarc.rule.formatting.SpaceBeforeClosingBraceRule
+ MAJOR
+
+
+ Check that there is at least one space (blank) or whitespace before each closing brace ("\}") for method/class/interface declarations, closure expressions and block statements.
+
Known limitations:
]]>
- grails
+ convention
- additionalHibernateBasicTypes
-
+ checkClosureMapEntryValue
+
+ true
- additionalReservedSqlKeywords
-
+ ignoreEmptyBlock
+
+ false
-
+
- org.codenarc.rule.grails.GrailsDomainWithServiceReferenceRule
- MINOR
-
-
- Checks that Grails Domain classes do not have Service classes injected.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
- ]]>
- grails
+ org.codenarc.rule.formatting.SpaceAfterIfRule
+ MAJOR
+
+
+ Check that there is exactly one space (blank) after the if keyword and before the opening parenthesis.
+
+]]>
+ convention
-
+
- org.codenarc.rule.grails.GrailsMassAssignmentRule
- MINOR
-
-
- Untrusted input should not be allowed to set arbitrary object fields without restriction.
-
Example of violations:
+ org.codenarc.rule.formatting.SpaceAfterWhileRule
+ MAJOR
+
+
+ Check that there is exactly one space (blank) after the while keyword and before the opening parenthesis.
+
Examples of violations:
- // Person would be a grails domain object
- def person = new Person(params)
- person.save()
-
- // or using .properties
- def person = Person.get(1)
- person.properties = params
- person.save()
+ while(true) { } // violation
+ while (true) { } // violation
]]>
- grails
+ convention
-
-
+
- org.codenarc.rule.imports.DuplicateImportRule
+ org.codenarc.rule.formatting.SpaceAfterForRuleMAJOR
-
-
- Checks for a duplicate statements.
- ]]>
- bug
+
+
+ Check that there is exactly one space (blank) after the for keyword and before the opening parenthesis.
+
Examples of violations:
+
+ for(name in names) { } // violation
+ for (int i=0; i < 10; i++) { } // violation
+
+]]>
+ convention
+
- org.codenarc.rule.imports.ImportFromSamePackageRule
+ org.codenarc.rule.formatting.SpaceAfterSwitchRuleMAJOR
-
-
- Checks for an of a class that is within the same package as the importing class.
- ]]>
- bug
+
+
+ Check that there is exactly one space (blank) after the switch keyword and before the opening parenthesis.
+
+]]>
+ convention
+
- org.codenarc.rule.imports.UnnecessaryGroovyImportRule
+ org.codenarc.rule.formatting.SpaceAfterCatchRuleMAJOR
-
-
- Checks for an from any package that is already automatically imported for Groovy files. A Groovy file does not need to include an import for classes from , , , , and , as well as the classes and .
- ]]>
- bug
+
+
+ Check that there is exactly one space (blank) after the catch keyword and before the opening parenthesis.
+
+]]>
+ convention
+
- org.codenarc.rule.imports.UnusedImportRule
+ org.codenarc.rule.formatting.SpaceAroundClosureArrowRuleMAJOR
-
-
- Checks for statements for classes that are never referenced within the source file. Also checks static imports.
+
+
+ Checks that there is at least one space (blank) or whitespace around each closure arrow (->) symbol.
Known limitations:
]]>
- bug
+ convention
-
+
- org.codenarc.rule.imports.ImportFromSunPackagesRule
- MINOR
-
-
- Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change.
+ org.codenarc.rule.formatting.SpaceAroundMapEntryColonRule
+ MAJOR
+
+
+ Check for proper formatting of whitespace around colons for literal Map entries. By default, no whitespace is allowed either before or after the Map entry colon, but you can change that through the configuration properties below.
Example of violations:
- import sun.misc.foo
- import sun.misc.foo as Foo
-
- public class MyClass{}
+ Map m1 = [myKey : 12345] // violation (both before and after the colon)
+ println [a :[1:11, 2:22], // violation on a (before colon)
+ b:[(Integer): 33]] // violation on Integer (after colon)
]]>
- bug
+ convention
+
+ characterAfterColonRegex
+ entry. For example, /\\S/ matches any non-whitespace character and /\\s/ matches any whitespace character (thus requiring a space or whitespace). ]]>
+ \\S
+
+
+ characterBeforeColonRegex
+ entry. For example, /\\S/ matches any non-whitespace character and /\\s/ matches any whitespace character (thus requiring a space or whitespace). ]]>
+ \\S
+
-
+
- org.codenarc.rule.imports.MisorderedStaticImportsRule
+ org.codenarc.rule.formatting.ClosureStatementOnOpeningLineOfMultipleLineClosureRuleMAJOR
-
-
- Checks for static statements which should never be after nonstatic imports.
-
This rule has one property comesBefore, which defaults to true. If you like your static imports to come after the others, then set this property to false.
-
Examples of violations:
+
+
+ Checks for closure logic on first line (after -\) for a multi-line closure. That breaks the symmetry of indentation (if the subsequent statements are indented normally), and that first statement can be easily missed when reading the code.
+
Example of violations:
- import my.something.another
- import static foo.bar
-
- public class MyClass{}
+ def closure = { name -> println name
+ addToCounts()
+ println “done” }
]]>
- bug
-
- comesBefore
-
- true
-
+ convention
- org.codenarc.rule.imports.NoWildcardImportsRule
+ org.codenarc.rule.formatting.ConsecutiveBlankLinesRuleMAJOR
-
-
- Wildcard imports, static or otherwise, should not be used.
-
Example of violations:
+
+
+ Makes sure there are no consecutive lines that are either blank or whitespace only. This reduces the need to scroll further than necessary when reading code, and increases the likelihood that a logical block of code will fit on one screen for easier comprehension.
+
Example of violation:
- import my.something.*
- import static foo.bar.*
+ def name
- public class MyClass{}
-
-]]>
- bug
-
-
+ def value
-
- org.codenarc.rule.junit.JUnitAssertAlwaysFailsRule
- MINOR
-
-
- Rule that checks for JUnit <<>> method calls with constant or literal arguments such that theassertion always fails. This includes:
-]]>
- junit
-
-
- org.codenarc.rule.junit.JUnitAssertAlwaysSucceedsRule
- MINOR
-
-
- Rule that checks for JUnit assert() method calls with constant arguments such that the assertion always succeeds. This includes:
-]]>
- junit
-
-
- org.codenarc.rule.junit.JUnitPublicNonTestMethodRule
- MINOR
-
-
- Rule that checks if a JUnit test class contains public methods other than standard test methods, JUnit framework methods or methods with JUnit annotations.
-
The following public methods are ignored by this rule:
+ def id
+
]]>
- junit
+ convention
+
- org.codenarc.rule.junit.JUnitSetUpCallsSuperRule
- MINOR
-
-
- Rule that checks that if the JUnit setUp method is defined, that it includes a call to super.setUp().
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ org.codenarc.rule.formatting.BlankLineBeforePackageRule
+ MAJOR
+
+
+ Makes sure there are no blank lines before the package declaration of a source code file.
]]>
- junit
+ convention
+
- org.codenarc.rule.junit.JUnitTearDownCallsSuperRule
- MINOR
-
-
- Rule that checks that if the JUnit tearDown method is defined, that it includes a call to super.tearDown().
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ org.codenarc.rule.formatting.FileEndsWithoutNewlineRule
+ MAJOR
+
+
+ Makes sure each source file ends with a newline character.
]]>
- junit
+ convention
+
- org.codenarc.rule.junit.JUnitUnnecessarySetUpRule
+ org.codenarc.rule.formatting.MissingBlankLineAfterImportsRuleMAJOR
-
-
- Rule that checks checks for JUnit setUp() methods that contain only a call to super.setUp(). The method is then unnecessary.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Here is an example of a violation:
+
+
+ Makes sure there is a blank line after the imports of a source code file.
+
]]>
- junit
+ convention
+
- org.codenarc.rule.junit.JUnitUnnecessaryTearDownRule
+ org.codenarc.rule.formatting.MissingBlankLineAfterPackageRuleMAJOR
-
-
- Rule that checks checks for JUnit tearDown() methods that contain only a call to super.tearDown(). The method is then unnecessary.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Here is an example of a violation:
+
+
+ Makes sure there is a blank line after the package statement of a source code file.
+
]]>
- junit
+ convention
-
+
- org.codenarc.rule.junit.JUnitStyleAssertionsRule
+ org.codenarc.rule.formatting.TrailingWhitespaceRuleMAJOR
-
-
- This rule detects calling JUnit style assertions like assertEquals, assertTrue, assertFalse, assertNull, assertNotNull. Groovy 1.7 ships with a feature called the "power assert", which is an assert statement with better error reporting. This is preferable to the JUnit assertions.
- ]]>
- junit
+
+
+ Checks that no lines of source code end with whitespace characters.
+]]>
+ convention
-
+
+
- org.codenarc.rule.junit.UseAssertEqualsInsteadOfAssertTrueRule
+ org.codenarc.rule.generic.IllegalRegexRule.fixedMAJOR
-
-
- This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
+
+ Checks for a specified illegal regular expression within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
+
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
]]>
- junit
+ bug
+
+ regex
+
+
-
- org.codenarc.rule.junit.UseAssertFalseInsteadOfNegationRule
- MINOR
-
-
- In unit tests, if a condition is expected to be false then there is no sense using assertTrue with the negation operator. For instance, assertTrue(!condition) can always be simplified to assertFalse(condition).
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ org.codenarc.rule.generic.RequiredRegexRule.fixed
+ MAJOR
+
+
+ Checks for a specified regular expression that must exist within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
+
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
]]>
- junit
+ bug
+
+ regex
+
+
-
- org.codenarc.rule.junit.UseAssertTrueInsteadOfAssertEqualsRule
+ org.codenarc.rule.generic.RequiredStringRule.fixedMAJOR
-
-
- This rule detects JUnit calling assertEquals where the first parameter is a boolean. These assertions should be made by more specific methods, like assertTrue or assertFalse.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- All of the following examples can be simplified to assertTrue or remove the true literal:
-
-]]>
- junit
+
+
+ Checks for a specified text string that must exist within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
+
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
+ ]]>
+ bug
- checkAssertStatements
-
- false
+ string
+
-
-
- org.codenarc.rule.junit.UseAssertNullInsteadOfAssertEqualsRule
- MAJOR
-
-
- This rule detects JUnit calling assertEquals where the first or second parameter is null. These assertion should be made against the assertNull method instead.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
- junit
-
-
-
-
- org.codenarc.rule.junit.UseAssertSameInsteadOfAssertTrueRule
- MAJOR
-
-
- This rule detects JUnit calling assertTrue or assertFalse where the first or second parameter is an Object#is() call testing for reference equality. These assertion should be made against the assertSame or assertNotSame method instead.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-]]>
- junit
-
-
-
-
- org.codenarc.rule.junit.JUnitFailWithoutMessageRule
- MINOR
-
-
- This rule detects JUnit calling the fail() method without an argument. For better error reporting you should always provide a message.
- ]]>
- junit
-
-
-
-
- org.codenarc.rule.junit.UseAssertTrueInsteadOfNegationRule
- MINOR
-
-
- In unit tests, if a condition is expected to be true then there is no sense using assertFalse with the negation operator. For instance, assertFalse(!condition) can always be simplified to assertTrue(condition).
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
- junit
-
-
-
- org.codenarc.rule.junit.JUnitTestMethodWithoutAssertRule
+ org.codenarc.rule.generic.StatelessClassRule.fixedMINOR
-
-
- This rule searches for test methods that do not contain assert statements. Either the test method is missing assert statements, which is an error, or the test method contains custom assert statements that do not follow a proper assert naming convention. Test methods are defined as public void methods that begin with the work test or have a @Test annotation. By default this rule applies to the default test class names, but this can be changed using the rule's applyToClassNames property. An assertion is defined as either using the assert keyword or invoking a method that starts with the work assert, like assertEquals, assertNull, or assertMyClassIsSimilar. Also, any method named should.* also counts as an assertion so that shouldFail methods do not trigger an assertion, any method that starts with fail counts as an assertion, and any method that starts with verify counts as an assertion. Since version 0.23 CodeNarc has support for JUnit's ExpectedException.
-
What counts as an assertion method can be overridden using the assertMethodPatterns property of the rule. The default value is this comma separated list of regular expressions:
+
+
+ Checks for non-final fields on a class. The intent of this rule is to check a configured set of classes that should remain "stateless" and reentrant. One example might be Grails service classes which are singletons, by default, and so they should be reentrant.
+
This rule ignores final fields (either instance or static). Fields that are static and non-final, however, do cause a violation.
This rule also ignores all fields annotated with the @Inject annotation.
+
You can configure this rule to ignore certain fields either by name or by type. This can be useful to ignore fields that hold references to (static) dependencies (such as DAOs or Service objects) or static configuration.
+
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
+ [[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
+
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.
+
[[3]] At least one of the (standard) applyToClassNames, applyToFileNames or applyToFilesMatching properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule to apply to a specific set of classes or files.
+
[[4]] This rule will not catch violations of true / if you define a final field whose value is itself mutable, e.g. a final HashMap.
]]>
- junit
+ bug
+
+ addToIgnoreFieldNames
+
+
+
+ ignoreFieldNames
+
+
+
+ ignoreFieldTypes
+
+
-
+
- org.codenarc.rule.junit.ChainedTestRule
+ org.codenarc.rule.generic.IllegalPackageReferenceRule.fixedMINOR
-
-
- A test method that invokes another test method is a chained test; the methods are dependent on one another. Tests should be isolated, and not be dependent on one another.
-
Example of violations:
+
+
+ Checks for reference to any of the packages configured in packageNames.
+
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
+
This rule can be useful for governance and enforcement of . For instance, making sure that view or model classes, for instance, do not contain references to JDBC-specific packages (e.g. java.sql and javax.sql).
+
Here is an example configuration of this rule used to ensure that JDBC packages/classes are only referenced within DAO classes:
- class MyTest extends GroovyTestCase {
- public void testFoo() {
-
- // violations, calls test method on self
- 5.times { testBar() }
- 5.times { this.testBar() }
-
- // OK, no violation: one arg method is not actually a test method
- 5.times { testBar(it) }
- }
+ ruleset {
+ description "Example CodeNarc Ruleset"
- private static void assertSomething() {
- testBar() // violation, even if in helper method
- this.testBar() // violation, even if in helper method
- }
+ // ...
- public void testBar() {
- // ...
+ IllegalPackageReference {
+ name = 'UseJdbcOnlyInDaoClasses'
+ priority = 2
+ packageNames = 'groovy.sql, java.sql, javax.sql'
+ doNotApplyToClassNames = 'com.example.framework.dao.*, *Dao, *DaoImpl'
+ description = 'Reference to JDBC packages should be restricted to DAO classes.'
}
}
]]>
- junit
+ bug
+
+ packageNames
+
+
-
+
- org.codenarc.rule.junit.CoupledTestCaseRule
+ org.codenarc.rule.generic.IllegalClassReferenceRule.fixedMINOR
-
-
- This rule finds test cases that are coupled to other test cases, either by invoking static methods on another test case or by creating instances of another test case. If you require shared logic in test cases then extract that logic to a new class where it can properly be reused. Static references to methods on the current test class are ignored.
-
Example of violations:
+
+
+ Checks for reference to any of the classes configured in classNames.
+
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
+
This rule can be useful for governance and enforcement of . For instance, making sure that view or model classes, for instance, do not contain references to DAO classes (e.g., *Dao).
+
Here is an example configuration of this rule used to ensure that DAO classes are not referenced from within model classes:
- class MyTest extends GroovyTestCase {
- public void testMethod() {
- // violation, static method call to other test
- MyOtherTest.helperMethod()
+ ruleset {
+ description "Example CodeNarc Ruleset"
- // violation, instantiation of another test class
- new MyOtherTest()
+ // ...
- // no violation; same class
- def input = MyTest.getResourceAsStream('sample.txt')
+ IllegalClassReference {
+ name = 'DoNotReferenceDaoFromModelClasses'
+ priority = 2
+ classNames = '*Dao'
+ applyToClassNames = 'com.example.model.*'
+ description = 'Do not reference DAOs from model classes.'
}
}
]]>
- junit
+ bug
+
+ classNames
+
+
-
+
- org.codenarc.rule.junit.UnnecessaryFailRule
+ org.codenarc.rule.generic.IllegalClassMemberRule.fixedMINOR
-
-
- In a unit test, catching an exception and immediately calling Assert.fail() is pointless and hides the stack trace. It is better to rethrow the exception or not catch the exception at all.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
+
+ Checks for classes containing fields/properties/methods matching configured illegal member modifiers or not matching any of the configured allowed member modifiers.
+
Modifiers for fields and methods include:
]]>
- junit
+ bug
+
+ allowedFieldModifiers
+
+
+
+ allowedMethodModifiers
+
+
+
+ allowedPropertyModifiers
+
+
+
+ ignoreMethodNames
+
+
+
+ ignoreMethodsWithAnnotationNames
+
+
+
+ illegalFieldModifiers
+
+
+
+ illegalMethodModifiers
+
+
+
+ illegalPropertyModifiers
+
+
-
+
- org.codenarc.rule.junit.SpockIgnoreRestUsedRule.fixed
+ org.codenarc.rule.generic.IllegalStringRule.fixedMINOR
-
-
- If Spock's @IgnoreRest annotation appears on any method, all non-annotated test methods are not executed. This behaviour is almost always unintended. It's fine to use @IgnoreRest locally during development, but when committing code, it should be removed.
-
The and properties determine which classes are considered Spock classes.
-
Example of violations:
-
- public class MySpec extends spock.lang.Specification {
- @spock.lang.IgnoreRest
- def "my first feature"() {
- expect: false
- }
+
+
+ Checks for a specified illegal string within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
+
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
+ ]]>
+ bug
+
+ string
+
+
+
- def "my second feature"() {
- given: def a = 2
+
+
+ org.codenarc.rule.generic.IllegalSubclassRule.fixed
+ MINOR
+
+
+ Checks for classes that extend one of the specified set of illegal superclasses.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
+ ]]>
+ bug
+
+ superclassNames
+
+
+
- when: a *= 2
+
- then: a == 4
- }
- }
-
+
+ org.codenarc.rule.grails.GrailsPublicControllerMethodRule.fixed
+ MINOR
+
+
+ Rule that checks for public methods on Grails controller classes. Static methods are ignored.
+
Grails controller actions and interceptors are defined as properties on the controller class. Public methods on a controller class are unnecessary. They break encapsulation and can be confusing.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' folder. You can override this with a different regular expression value if appropriate.
+
This rule also sets the default value of applyToClassNames to only match class names ending in 'Controller'. You can override this with a different class name pattern (String with wildcards) if appropriate.
+ ]]>
+ grails
+
+ ignoreMethodNames
+
+
+
+
+
+ org.codenarc.rule.grails.GrailsSessionReferenceRule
+ MINOR
+
+
+ Rule that checks for references to the session object from within Grails controller and taglib classes.
+
This rule is intended as a "governance" rule to enable monitoring and controlling access to the session from within application source code. Storing objects in the session may inhibit scalability and/or performance and should be carefully considered.
+
Note that this rule does not check for direct access to the session from within GSP (Groovy Server Pages) files.
+
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate session access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
+ ]]>
+ grails
+
+
+
+ org.codenarc.rule.grails.GrailsServletContextReferenceRule
+ MINOR
+
+
+ Rule that checks for references to the servletContext object from within Grails controller and taglib classes.
+
This rule is intended as a "governance" rule to enable monitoring and controlling access to the servletContext from within application source code. Storing objects in the servletContext may inhibit scalability and/or performance and should be carefully considered. Furthermore, access to the servletContext is not synchronized, so reading/writing objects from the servletConext must be manually synchronized, as described in The Definitive Guide to Grails (2nd edition).
+
Note that this rule does not check for direct access to the servletContext from within GSP (Groovy Server Pages) files.
+
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate servletContext access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
+ ]]>
+ grails
+
+
+
+ org.codenarc.rule.grails.GrailsStatelessServiceRule
+ MINOR
+
+
+ Checks for non-final fields on a Grails service class. Grails service classes are singletons by default, and so they should be reentrant. In most cases, this implies (or at least encourages) that they should be stateless.
+
This rule ignores (i.e., does not cause violations for) the following:
Ignores classes annotated with @ToString or @Canonical.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
Ignores classes annotated with @EqualsAndHashCode or @Canonical.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
+ ]]>
+ grails
+
+
- org.codenarc.rule.junit.JUnitLostTestRule
+ org.codenarc.rule.grails.GrailsDuplicateMappingRuleMINOR
-
-
- This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named * that is not annotated with the JUnit 4 @Test annotation.
-
Note: This rule should be disabled for Grails 2.x projects, since the Grails test framework can use AST Transformations to automatically annotate test methods.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
+
+ Check for duplicate name in a Grails domain class mapping. Duplicate names/entries are legal, but can be confusing and error-prone.
+
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
]]>
- junit
+ grails
- org.codenarc.rule.junit.JUnitUnnecessaryThrowsExceptionRule
- MAJOR
-
-
- Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ org.codenarc.rule.grails.GrailsDuplicateConstraintRule
+ MINOR
+
+
+ Check for duplicate name in a Grails domain class constraints. Duplicate names/entries are legal, but can be confusing and error-prone.
+
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
]]>
- junit
+ grails
- org.codenarc.rule.junit.JUnitPublicFieldRule
- MAJOR
-
-
- Checks for public fields on a JUnit test class. There is usually no reason to have a public field (even a constant) on a test class.
-
Fields within interfaces and fields annotated with @Rule are ignored.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Example of violations:
-
- import org.junit.Test
- class MyTestCase {
- public int count // violation
- public static final MAX_VALUE = 1000 // violation
-
- @Test
- void testMe() { }
- }
-
+ org.codenarc.rule.grails.GrailsDomainReservedSqlKeywordNameRule
+ MINOR
+
+
+ Forbids usage of SQL reserved keywords as class or field names in Grails domain classes. Naming a domain class (or its field) with such a keyword causes SQL schema creation errors and/or redundant table/column name mappings.
+
Note: due to limited type information available during CodeNarc's operation, this rule will report fields of type java.io.Serializable, but not of its implementations. Please specify any implementations used as domain properties in additionalHibernateBasicTypes.
]]>
- junit
+ grails
+
+ additionalHibernateBasicTypes
+
+
+
+ additionalReservedSqlKeywords
+
+
- org.codenarc.rule.junit.JUnitAssertEqualsConstantActualValueRule
+ org.codenarc.rule.grails.GrailsDomainWithServiceReferenceRuleMINOR
-
-
- Reports usages of org.junit.Assert.assertEquals([message,] expected, actual) where the actual parameter is a constant or a literal. Most likely it was intended to be the expected value.
-
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
-]]>
- junit
+
+
+ Checks that Grails Domain classes do not have Service classes injected.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
+ ]]>
+ grails
- org.codenarc.rule.junit.JUnitPublicPropertyRule.fixed
+ org.codenarc.rule.grails.GrailsMassAssignmentRuleMINOR
-
-
- Checks for public properties defined on JUnit test classes. There is typically no need to expose a public property (with public and methods) on a test class.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
+
+ Untrusted input should not be allowed to set arbitrary object fields without restriction.
Example of violations:
- import org.junit.Test
- class MyTestCase {
- static String id // violation
- def helper // violation
- String name // violation
+ // Person would be a grails domain object
+ def person = new Person(params)
+ person.save()
- @Test
- void testMe() { }
- }
+ // or using .properties
+ def person = Person.get(1)
+ person.properties = params
+ person.save()
]]>
- junit
-
- ignorePropertyNames
-
-
+ grails
-
+
+
- org.codenarc.rule.logging.PrintlnRule
+ org.codenarc.rule.groovyism.ExplicitArrayListInstantiationRuleMINOR
-
-
- Checks for calls to this.print(), this.println() or this.printf(). Consider using a standard logging facility instead.
+
+
+ This rule checks for explicit calls to the no-argument constructor of ArrayList. In Groovy, it is best to write new ArrayList() as [], which creates the same object.
]]>
- bug
+ groovyism
+
- org.codenarc.rule.logging.PrintStackTraceRule
+ org.codenarc.rule.groovyism.ExplicitCallToAndMethodRuleMINOR
-
-
- Checks for calls to Throwable.printStackTrace() or StackTraceUtils.printSanitizedStackTrace(Throwable). Consider using a standard logging facility instead.
+
+
+ This rule detects when the and(Object) method is called directly in code instead of using the & operator. A groovier way to express this: a.and(b) is this: a & b. This rule can be configured to ignore this.and(Object) using the property. It defaults to , so even and(x) will not trigger a violation. The default is because and appears commonly in Grails criteria.
+
This rule also ignores all calls to super.and(Object).
]]>
- bug
+ groovyism
+
- org.codenarc.rule.logging.SystemErrPrintRule
+ org.codenarc.rule.groovyism.ExplicitCallToCompareToMethodRuleMINOR
-
-
- Checks for calls to System.err.print(), System.err.println() or System.err.printf(). Consider using a standard logging facility instead.
- ]]>
- bug
+
+
+ This rule detects when the compareTo(Object) method is called directly in code instead of using the \<\=\>, \>, \>\=, \<, and \<\= operators. A groovier way to express this: a.compareTo(b) is this: a \<\=\> b, or using the other operators. Here are some other ways to write groovier code:
+
+ a.compareTo(b) == 0 // can be replaced by: a == b
+ a.compareTo(b) // can be replaced by: a <=> b
+ a.compareTo(b) > 0 // can be replaced by: a > b
+ a.compareTo(b) >= 0 // can be replaced by: a >= b
+ a.compareTo(b) < 0 // can be replaced by: a < b
+ a.compareTo(b) <= 0 // can be replaced by: a <= b
+
+]]>
+ groovyism
+
- org.codenarc.rule.logging.SystemOutPrintRule
+ org.codenarc.rule.groovyism.ExplicitCallToDivMethodRuleMINOR
-
-
- Checks for calls to System.out.print(), System.out.println() or System.out.printf(). Consider using a standard logging facility instead.
-]]>
- bug
+
+
+ This rule detects when the div(Object) method is called directly in code instead of using the / operator. A groovier way to express this: a.div(b) is this: a / b. This rule can be configured to ignore div.xor(Object) using the property. It defaults to , so even div(x) will trigger a violation.
+
This rule also ignores all calls to super.div(Object).
+ ]]>
+ groovyism
-
+
- org.codenarc.rule.logging.LoggerForDifferentClassRule
+ org.codenarc.rule.groovyism.ExplicitCallToEqualsMethodRuleMINOR
-
-
- Checks for instantiating a logger for a class other than the current class. Checks for logger instantiations for Log4J, SLF4J, Logback, Apache Commons Logging and Java Logging API (java.util.logging).
-
This rule contains a parameter allowDerivedClasses. When set, a logger may be created about this.getClass().
-
Limitations:
-]]>
- bug
+
+
+ This rule detects when the equals(Object) method is called directly in code instead of using the == or != operator. A groovier way to express this: a.equals(b) is this: a == b and a groovier way to express : !a.equals(b) is: a != b. This rule can be configured to ignore this.equals(Object) using the property. It defaults to , so even equals(x) will trigger a violation.
+
This rule also ignores all calls to super.equals(Object).
+ ]]>
+ groovyism
-
+
- org.codenarc.rule.logging.LoggingSwallowsStacktraceRule
+ org.codenarc.rule.groovyism.ExplicitCallToGetAtMethodRuleMINOR
-
-
- If you are logging an exception then the proper API is to call error(Object, Throwable), which will log the message and the exception stack trace. If you call error(Object) then the stacktrace may not be logged.
+
+
+ This rule detects when the getAt(Object) method is called directly in code instead of using the [] index operator. A groovier way to express this: a.getAt(b) is this: a[b]. This rule can be configured to ignore this.getAt(Object) using the property. It defaults to , so even getAt(x) will trigger a violation.
+
This rule also ignores all calls to super.getAt(Object).
]]>
- bug
+ groovyism
-
+
- org.codenarc.rule.logging.LoggerWithWrongModifiersRule
+ org.codenarc.rule.groovyism.ExplicitCallToLeftShiftMethodRuleMINOR
-
-
- Logger objects should be declared private, static and final.
-
This rule has a property: allowProtectedLogger, which defaults to false. Set it to true if you believe subclasses should have access to a Logger in a parent class and that Logger should be declared protected or public.
-
This rule has a property: allowNonStaticLogger, which defaults to false. Set it to true if you believe a logger should be allowed to be non-static.
+
+
+ This rule detects when the leftShift(Object) method is called directly in code instead of using the \<\< operator. A groovier way to express this: a.leftShift(b) is this: a \<\< b. This rule can be configured to ignore this.leftShift(Object) using the property. It defaults to , so even leftShift(x) will trigger a violation.
+
This rule also ignores all calls to super.leftShift(Object).
]]>
- bug
+ groovyism
-
+
- org.codenarc.rule.logging.MultipleLoggersRule
+ org.codenarc.rule.groovyism.ExplicitCallToMinusMethodRuleMINOR
-
-
- This rule catches classes that have more than one logger object defined. Typically, a class has zero or one logger objects.
+
+
+ This rule detects when the minus(Object) method is called directly in code instead of using the - operator. A groovier way to express this: a.minus(b) is this: a - b. This rule can be configured to ignore minus.xor(Object) using the property. It defaults to , so even minus(x) will trigger a violation.
+
This rule also ignores all calls to super.minus(Object).
]]>
- bug
+ groovyism
-
-
+
- org.codenarc.rule.naming.AbstractClassNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitCallToMultiplyMethodRuleMINOR
-
-
- Verifies that the name of an abstract class matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active. This rule ignores interfaces and is applied only to abstract classes.
+
+
+ This rule detects when the multiply(Object) method is called directly in code instead of using the * operator. A groovier way to express this: a.multiply(b) is this: a * b. This rule can be configured to ignore this.multiply(Object) using the property. It defaults to , so even multiply(x) will trigger a violation.
+
This rule also ignores all calls to super.multiply(Object).
]]>
- bug
-
- regex
-
-
+ groovyism
+
- org.codenarc.rule.naming.ClassNameRule
+ org.codenarc.rule.groovyism.ExplicitCallToModMethodRuleMINOR
-
-
- Verifies that the name of a class matches a regular expression. By default it checks that the class name starts with an uppercase letter and is followed by zero or more word characters (letters, numbers or underscores) or dollar signs ($).
+
+
+ This rule detects when the mod(Object) method is called directly in code instead of using the % operator. A groovier way to express this: a.mod(b) is this: a % b. This rule can be configured to ignore this.mod(Object) using the property. It defaults to , so even mod(x) will trigger a violation.
+
This rule also ignores all calls to super.mod(Object).
]]>
- bug
-
- regex
-
- ([A-Z]\w*\$?)*
-
+ groovyism
+
- org.codenarc.rule.naming.FieldNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitCallToOrMethodRuleMINOR
-
-
- Verifies that the name of each field matches a regular expression. By default it checks that fields that are not have field names that start with a lowercase letter and contains only letters or numbers. By default, field names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
-
NOTE: This rule checks only regular of a class, not . In Groovy, are fields declared with no access modifier (public, protected, private). Thus, this rule only checks fields that specify an access modifier. For naming of , see PropertyNameRule.
-
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the field is the one that is applied for the field name validation.
+
+
+ This rule detects when the or(Object) method is called directly in code instead of using the | operator. A groovier way to express this: a.or(b) is this: a | b. This rule can be configured to ignore this.or(Object) using the property. It defaults to , so even or(x) will not trigger a violation. This is the default because it is commonly used in Grails criteria.
+
This rule also ignores all calls to super.or(Object).
]]>
- bug
-
- finalRegex
-
-
-
- ignoreFieldNames
-
- serialVersionUID
-
-
- regex
-
- [a-z][a-zA-Z0-9]*
-
-
- staticFinalRegex
-
- [A-Z][A-Z0-9_]*
-
-
- staticRegex
-
-
+ groovyism
+
- org.codenarc.rule.naming.InterfaceNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitCallToPlusMethodRuleMINOR
-
-
- Verifies that the name of an interface matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active.
+
+
+ This rule detects when the plus(Object) method is called directly in code instead of using the + operator. A groovier way to express this: a.plus(b) is this: a + b. This rule can be configured to ignore this.plus(Object) using the property. It defaults to , so even plus(x) will trigger a violation.
+
This rule also ignores all calls to super.plus(Object).
]]>
- bug
-
- regex
-
-
+ groovyism
+
- org.codenarc.rule.naming.MethodNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitCallToPowerMethodRuleMINOR
-
-
- Verifies that the name of each method matches a regular expression. By default it checks that the method name starts with a lowercase letter. Implicit method names are ignored (i.e., 'main' and 'run' methods automatically created for Groovy scripts).
+
+
+ This rule detects when the power(Object) method is called directly in code instead of using the ** operator. A groovier way to express this: a.power(b) is this: a ** b. This rule can be configured to ignore this.power(Object) using the property. It defaults to , so even power(x) will trigger a violation.
+
This rule also ignores all calls to super.power(Object).
]]>
- bug
-
- ignoreMethodNames
-
-
-
- regex
-
- [a-z]\w*
-
+ groovyism
+
- org.codenarc.rule.naming.PackageNameRule
+ org.codenarc.rule.groovyism.ExplicitCallToRightShiftMethodRuleMINOR
-
-
- Verifies that the package name of a class matches a regular expression. By default it checks that the package name consists of only lowercase letters and numbers, separated by periods.
+
+
+ This rule detects when the rightShift(Object) method is called directly in code instead of using the \>\> operator. A groovier way to express this: a.rightShift(b) is this: a \>\> b. This rule can be configured to ignore this.rightShift(Object) using the property. It defaults to , so even rightShift(x) will trigger a violation.
+
This rule also ignores all calls to super.rightShift(Object).
]]>
- bug
-
- packageNameRequired
-
- false
-
-
- regex
-
- [a-z]+[a-z0-9]*(\.[a-z0-9]+)*
-
+ groovyism
+
- org.codenarc.rule.naming.ParameterNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitCallToXorMethodRuleMINOR
-
-
- Verifies that the name of each parameter matches a regular expression. This rule applies to method parameters, constructor parameters and closure parameters. By default it checks that parameter names start with a lowercase letter and contains only letters or numbers.
+
+
+ This rule detects when the xor(Object) method is called directly in code instead of using the ^ operator. A groovier way to express this: a.xor(b) is this: a ^ b. This rule can be configured to ignore this.xor(Object) using the property. It defaults to , so even xor(x) will trigger a violation.
+
This rule also ignores all calls to super.xor(Object).
]]>
- bug
-
- ignoreParameterNames
-
-
-
- regex
-
- [a-z][a-zA-Z0-9]*
-
+ groovyism
+
- org.codenarc.rule.naming.PropertyNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitHashMapInstantiationRuleMINOR
-
-
- Verifies that the name of each property matches a regular expression. By default it checks that property names (other than ) start with a lowercase letter and contains only letters or numbers. By default, property names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
-
NOTE: This rule checks only of a class, not regular . In Groovy, are fields declared with no access modifier (public, protected, private). For naming of regular , see FieldNameRule.
-
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the property is the one that is applied for the field name validation.
+
+
+ This rule checks for explicit calls to the no-argument constructor of HashMap. In Groovy, it is best to replace new HashMap() with [:], which creates (mostly) the same object. [:] is technically a LinkedHashMap but it is very rare that someone absolutely needs an instance of HashMap and not a subclass.
]]>
- bug
-
- finalRegex
-
-
-
- ignorePropertyNames
-
-
-
- regex
-
- [a-z][a-zA-Z0-9]*
-
-
- staticFinalRegex
-
- [A-Z][A-Z0-9_]*
-
-
- staticRegex
-
-
+ groovyism
+
- org.codenarc.rule.naming.VariableNameRule.fixed
+ org.codenarc.rule.groovyism.ExplicitHashSetInstantiationRuleMINOR
-
-
- Verifies that the name of each variable matches a regular expression. By default it checks that non-final variable names start with a lowercase letter and contains only letters or numbers. By default, final variable names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
-]]>
- bug
-
- finalRegex
-
- [A-Z][A-Z0-9_]*
-
-
- ignoreVariableNames
-
-
-
- regex
-
- [a-z][a-zA-Z0-9]*
-
+
+
+ This rule checks for explicit calls to the no-argument constructor of HashSet. In Groovy, it is best to replace new HashSet() with [] as Set, which creates the same object.
+ ]]>
+ groovyism
- org.codenarc.rule.naming.ConfusingMethodNameRule
+ org.codenarc.rule.groovyism.ExplicitLinkedListInstantiationRuleMINOR
-
-
- Checks for very confusing method names. The referenced methods have names that differ only by capitalization. This is very confusing because if the capitalization were identical then one of the methods would override the other.
-
Also, violations are triggered when methods and fields have very similar names.
-
- class MyClass {
- int total
- int total() {
- 1
- }
- }
-
-]]>
- bug
+
+
+ This rule checks for explicit calls to the no-argument constructor of LinkedList. In Groovy, it is best to replace new LinkedList() with [] as Queue, which creates the same object.
+ ]]>
+ groovyism
- org.codenarc.rule.naming.ObjectOverrideMisspelledMethodNameRule
+ org.codenarc.rule.groovyism.ExplicitStackInstantiationRuleMINOR
-
-
- Verifies that the names of the most commonly overridden methods of Object: equals, hashCode and toString, are correct.
-
Here are some examples of code that produces violations:
-
- boolean equal(Object o) {} // violation
- boolean equal(int other) {} // ok; wrong param type
- boolean equal(Object o, int other) {} // ok; too many params
-
- boolean equaLS(Object o) {} // violation
+
+
+ This rule checks for explicit calls to the no-argument constructor of Stack. In Groovy, it is best to replace new Stack() with [] as Stack, which creates the same object.
+ ]]>
+ groovyism
+
- int hashcode() {} // violation
- int hashCOde() {} // violation
- int hashcode(int value) {} // ok; not empty params
+
+
+ org.codenarc.rule.groovyism.ExplicitTreeSetInstantiationRule
+ MINOR
+
+
+ This rule checks for explicit calls to the no-argument constructor of TreeSet. In Groovy, it is best to replace new TreeSet() with [] as SortedSet, which creates the same object.
+ ]]>
+ groovyism
+
- String tostring() {} // violation
- String toSTring() {} // violation
- String tostring(int value) {} // ok; not empty params
+
+
+ org.codenarc.rule.groovyism.GStringAsMapKeyRule
+ MINOR
+
+
+ A GString should not be used as a map key since its is not guaranteed to be stable. Consider calling key.toString().
+
Here is an example of code that produces a violation:
]]>
- bug
+ groovyism
-
+
- org.codenarc.rule.naming.FactoryMethodNameRule
+ org.codenarc.rule.groovyism.GroovyLangImmutableRuleMINOR
-
-
- A factory method is a method that creates objects, and they are typically named either buildFoo(), makeFoo(), or createFoo(). This rule enforces that only one naming convention is used. It defaults to allowing makeFoo(), but that can be changed using the property regex. The regex is a negative expression; it specifically bans methods named build* or create*. However, methods named build or build* receive some special treatment because of the popular Builder Pattern. If the 'build' method is in a class named *Builder then it does not cause a violation.
-
Builder methods are slightly different than factory methods.
+
+
+ The groovy.lang.Immutable annotation has been deprecated and replaced by groovy.transform.Immutable. Do not use the Immutable in groovy.lang.
Example of violations:
- class MyClass {
-
- // violation. Factory methods should be named make()
- def create() {
- }
-
- // violation. Factory methods should be named make()
- def createSomething() {
- }
-
- // violation. Builder method not in class named *Builder
- def build() {
- }
-
- // violation. Builder method not in class named *Builder
- def buildSomething() {
- }
+ @Immutable
+ class Person { }
- // this is OK because it is called make
- def make() {
- }
+ @groovy.lang.Immutable
+ class Person { }
- // this is also OK
- def makeSomething() {
- }
+ import groovy.lang.Immutable as Imtl
+ @Imtl
+ class Person { }
- // OK, overriding a parent
- @Override
- build() { }
+ // the following code is OK
+ @groovy.transform.Immutable
+ class Person { }
- }
+ import groovy.transform.Immutable
+ @Immutable
+ class Person { }
- class WidgetBuilder {
+ import groovy.transform.*
+ @Immutable
+ class Person { }
- // OK, the class name ends in Builder
- def build() {
- }
- }
+ import groovy.transform.Immutable as Imtl
+ @Imtl
+ class Person { }
]]>
- bug
-
- regex
-
- (build.*\|create.*)
-
+ groovyism
-
+
- org.codenarc.rule.naming.ClassNameSameAsFilenameRule
+ org.codenarc.rule.groovyism.ExplicitLinkedHashMapInstantiationRuleMINOR
-
-
- Reports files containing only one top level class / enum / interface which is named differently than the file.
+
+
+ This rule checks for the explicit instantiation of a LinkedHashMap using the no-arg constructor. In Groovy, it is best to replace new LinkedHashMap() with [:], which creates the same object.
]]>
- bug
+ groovyism
-
+
- org.codenarc.rule.naming.PackageNameMatchesFilePathRule.fixed
- MINOR
-
-
- A package source file's path should match the package declaration.
- ]]>
- bug
-
- groupId
- part of a package name, that will appear within all checked package names. It must also map to the file path for the correspondin source file. For instance, a of <"org.sample"> means that for all classes that specify a package, that package name must include <"org.sample">, and the source file must exist under an "org/sample" directory. Then, a MyClass class in a org.sample.util package must be defined in a "MyClass.groovy" file within a <"org/sample/util"> directory. That directory can be the child of any arbitrary , e.g. "src/main/groovy". To find the sub-path relevant for the package the rule searches for the first appearance of in the file path. It's to configure this. If groupId is null or empty, this rule does nothing. ]]>
-
+ org.codenarc.rule.groovyism.ClosureAsLastMethodParameterRule
+ MAJOR
+
+
+ If a method is called and the last parameter is an inline closure then it can be declared outside of the method call parentheses.
+
Example of violations:
+
+ // creates violation: poor Groovy style
+ [1,2,3].each({ println it })
+
+ // no violation
+ [1,2,3].each { println it }
+
+]]>
+ groovyism
-
+
- org.codenarc.rule.naming.ClassNameSameAsSuperclassRule
+ org.codenarc.rule.groovyism.AssignCollectionUniqueRuleMINOR
-
-
- Checks for any class that has an identical name to its superclass, other than the package. This can be very confusing.
-
Also see FindBugs NM_SAME_SIMPLE_NAME_AS_SUPERCLASS rule.
+
+
+ The Collections.unique() method mutates the list and returns the list as a value. If you are assigning the result of unique() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a unique() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
Example of violations:
- class MyClass extends other.MyClass // violation
+ def a = myList.unique()
+ def b = myList.unique() { it }
+ def c = myList.unique().findAll { x < 1 }
+
]]>
- bug
+ groovyism
-
+
- org.codenarc.rule.naming.InterfaceNameSameAsSuperInterfaceRule
+ org.codenarc.rule.groovyism.AssignCollectionSortRuleMINOR
-
-
- Checks for any interface that has an identical name to its super-interface, other than the package. This can be very confusing.
+
+
+ The Collections.sort() method mutates the list and returns the list as a value. If you are assigning the result of sort() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a sort() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
Example of violations:
- interface MyInterface extends other.MyInterface { } // violation
+ def a = myList.sort()
+ def b = myList.sort() { it }
+ def c = myList.sort().findAll { x < 1 }
]]>
- bug
+ groovyism
-
-
+
- org.codenarc.rule.size.ClassSizeRule
- MAJOR
-
-
- Checks if the size of a class exceeds the number of lines specified by the maxLines property.
- ]]>
- bug
-
- maxLines
-
- 1000
-
+ org.codenarc.rule.groovyism.ConfusingMultipleReturnsRule
+ MINOR
+
+
+ Multiple return values can be used to set several variables at once. To use multiple return values, the left hand side of the assignment must be enclosed in parenthesis. If not, then you are not using multiple return values, you're only assigning the last element.
+
Example of violations:
+
+def a, b = [1, 2] // bad, b is null
+def c, d, e = [1, 2, 3] // bad, c and d are null
+class MyClass {
+ def a, b, c = [1, 2, 3] // bad, a and b are null
+}
+
+def x = 1 // ok
+def (f, g) = [1, 2] // ok
+(a, b, c) = [1, 2, 3] // ok
+
+]]>
+ groovyism
+
- org.codenarc.rule.size.CyclomaticComplexityRule.fixed
- MINOR
-
-
- Calculates the for methods/classes and checks against configured threshold values.
-
The maxMethodComplexity property holds the threshold value for the cyclomatic complexity value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
-
The maxClassAverageMethodComplexity property holds the threshold value for the average cyclomatic complexity value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
-
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
- The value is calculated as follows:
-
+ org.codenarc.rule.groovyism.GetterMethodCouldBePropertyRule
+ MAJOR
+
+
+ If a class defines a public method that follows the Java getter notation and that returns a constant, then it is cleaner to provide a Groovy property for the value rather than a Groovy method.
+
Example of violations:
+
+ interface Parent {
+ String getSomething()
+ String getSomethingElse()
+ }
+
+ class Child extends Parent {
+ static VALUE = 'value'
+
+ @Override
+ String getSomething() {
+ 'something' // this could be simplified
+ }
+
+ @Override
+ String getSomethingElse() {
+ VALUE // this could be simplified
+ }
+
+ int getOtherValue() {
+ 123
+ }
+
+ static String getName() {
+ 'MyName'
+ }
+ }
+
+ class Child2 extends Parent {
+ static VALUE = 'value'
+ final String something = 'something' // this is cleaner
+ final String somethingElse = VALUE // this is cleaner
+ final int otherValue = 123 // this is cleaner
+ static final String name = 'MyName' // this is cleaner
+ }
+
]]>
- bug
-
- ignoreMethodNames
-
-
-
- maxClassAverageMethodComplexity
- value allowed for a class, calculated as the average complexity of its methods or "closure fields". If zero or , then do not check average class-level complexity. ]]>
- 20
-
-
- maxClassComplexity
- value allowed for a class, calculated as the total complexity of its methods or "closure fields". If zero or , then do not check total class-level complexity. ]]>
- 0
-
-
- maxMethodComplexity
- value allowed for a single method (or "closure field"). If zero or , then do not check method-level complexity. ]]>
- 20
-
+ groovyism
+
- org.codenarc.rule.size.MethodCountRule
+ org.codenarc.rule.groovyism.UseCollectManyRuleMINOR
-
-
- Checks if the number of methods within a class exceeds the number of lines specified by the maxMethod property.
-
A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects.
- ]]>
- bug
-
- maxMethods
-
- 30
-
-
+
+
+ In many case collectMany() yields the same result as collect{}.flatten(). It is easier to understand and more clearly conveys the intent.
+
Example of violations:
+
+def l = [1, 2, 3, 4]
-
- org.codenarc.rule.size.MethodSizeRule.fixed
- MAJOR
-
-
- Checks if the size of a method exceeds the number of lines specified by the maxLines property.
-
]]>
- bug
-
- ignoreMethodNames
-
-
-
- maxLines
-
- 100
-
+ groovyism
+
- org.codenarc.rule.size.NestedBlockDepthRule
+ org.codenarc.rule.groovyism.CollectAllIsDeprecatedRuleMINOR
-
-
- Checks for blocks or closures nested more deeply than a configured maximum number. Blocks include if, for, while, switch, try, catch, finally and synchronized blocks/statements, as well as closures.
-
Methods calls, constructor calls, and property access through Builder objects are ignore. For instance, this code does not cause a violation:
+
+
+ The collectAll method is deprecated since Groovy 1.8.1. Use collectNested instead.
+
The metric score is based on the and test coverage for individual methods. A method with a value greater than the maxMethodCrapScore property causes a violation. Likewise, a class that has an (average method) value greater than the maxClassAverageMethodCrapScore property causes a violation.
-
NOTE: This rule requires the GMetrics[3] jar, version 0.5 (or later), on the classpath, as well as a Cobertura[4]-[6] XML coverage file. If either of these prerequisites is not available, this rule logs a warning messages and exits (i.e., does nothing).
-
The maxMethodCrapScore property holds the threshold value for the CRAP value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
-
The maxClassAverageMethodCrapScore property holds the threshold value for the average CRAP value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
-
NOTE: This rule does NOT treat as methods (unlike some of the other size/complexity rules).
-]]>
- bug
-
- coberturaXmlFile
-
-
-
- ignoreMethodNames
-
-
-
- maxClassAverageMethodCrapScore
- average metric value allowed for a class, calculated as the average CRAP value of its methods. If zero or , then do not check the average class-level CRAP value. ]]>
- 30
-
-
- maxClassCrapScore
- metric value allowed for a class, calculated as the total CRAP value of its methods. If zero or , then do not check class-level CRAP value. ]]>
- 0
-
-
- maxMethodCrapScore
- metric value allowed for a single method. If zero or , then do not check method-level complexity. ]]>
- 30
-
-
+
+
+ Instead of nested collect{} calls use collectNested{}.
+
Example of violations:
+
+def list = [1, 2, [3, 4, 5, 6], [7]]
-
-
- org.codenarc.rule.size.AbcMetricRule.fixed
- MINOR
-
-
- Calculates the size metric for methods/classes and checks against configured threshold values.
-
The maxMethodAbcScore property holds the threshold value for the ABC score for each method. If this value is non-zero, a method with an ABC score greater than this value is considered a violation. The value does not have to be an integer (e.g., 1.7 is allowed).
-
The maxClassAverageMethodAbcScore property holds the threshold value for the average ABC score for each class. If this value is non-zero, a class with an average ABC score value greater than this value is considered a violation. The value does not have to be an integer.
-
The maxClassAbcScore property holds the threshold value for the total ABC score value for each class. If this value is non-zero, a class with a total ABC score greater than this value is considered a violation. The value does not have to be an integer.
-
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
- The score is calculated as follows: The metric measures size by counting the number of Assignments (A), Branches (B) and Conditions (C) and assigns a single numerical score calculated as:
-
]]>
- bug
-
- ignoreMethodNames
-
-
-
- maxClassAbcScore
- score allowed for a class, calculated as the total ABC score of its methods or "closure fields". If zero or , then do not check class-level scores. ]]>
- 0
-
-
- maxClassAverageMethodAbcScore
- score allowed for a class, calculated as the average score of its methods or "closure fields". If zero or , then do not check class-level average scores. ]]>
- 60
-
-
- maxMethodAbcScore
- score allowed for a single method (or "closure field"). If zero or , then do not check method-level scores. ]]>
- 60
-
+ groovyism
-
+
- org.codenarc.rule.size.ParameterCountRule
+ org.codenarc.rule.groovyism.GStringExpressionWithinStringRuleMINOR
-
-
- Checks if the number of parameters in method/constructor exceeds the number of parameters specified by the maxParameters property.
+
+
+ Check for regular (single quote) strings containing a GString-type expression (${..}).
Example of violations:
- void someMethod(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6) { // violation
- }
+ def str1 = 'total: ${count}' // violation
+ def str2 = 'average: ${total / count}' // violation
- class SampleClass {
- SampleClass(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) { // violation
- }
- }
+ def str3 = "abc ${count}" // ok; GString
+ def str4 = '$123' // ok
+ def str5 = 'abc {123}' // ok
]]>
- bug
-
- maxParameters
-
- 5
-
+ groovyism
-
+
- org.codenarc.rule.unnecessary.UnnecessaryBooleanExpressionRule
+ org.codenarc.rule.imports.DuplicateImportRuleMAJOR
-
-
- Checks for unnecessary boolean expressions, including ANDing (&&) or ORing (||) with true, false, null, or a Map/List/String/Number literal.
-
This rule also checks for negation (!) of true, false, null, or a Map/List/String/Number literal.
-
Examples of violations include:
-
- result = value && true // AND or OR with boolean constants
- if (false || value) { .. }
- return value && Boolean.FALSE
-
- result = null && value // AND or OR with null
-
- result = value && "abc" // AND or OR with String literal
-
- result = value && 123 // AND or OR with Number literal
- result = 678.123 || true
-
- result = value && [x, y] // AND or OR with List literal
-
- result = [a:123] && value // AND or OR with Map literal
+
+
+ Checks for a duplicate statements.
+ ]]>
+ bug
+
- result = !true // Negation of boolean constants
- result = !false
- result = !Boolean.TRUE
+
+ org.codenarc.rule.imports.ImportFromSamePackageRule
+ MAJOR
+
+
+ Checks for an of a class that is within the same package as the importing class.
+ ]]>
+ bug
+
- result = !null // Negation of null
+
+ org.codenarc.rule.imports.UnnecessaryGroovyImportRule
+ MAJOR
+
+
+ Checks for an from any package that is already automatically imported for Groovy files. A Groovy file does not need to include an import for classes from , , , , and , as well as the classes and .
+ ]]>
+ bug
+
- result = !"abc" // Negation of String literal
+
+ org.codenarc.rule.imports.UnusedImportRule
+ MAJOR
+
+
+ Checks for statements for classes that are never referenced within the source file. Also checks static imports.
+
Known limitations:
+]]>
+ bug
+
- result = ![a:123] // Negation of Map literal
+
+
+ org.codenarc.rule.imports.ImportFromSunPackagesRule
+ MINOR
+
+
+ Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change.
+
Example of violations:
+
+ import sun.misc.foo
+ import sun.misc.foo as Foo
- result = ![a,b] // Negation of List literal
+ public class MyClass{}
]]>
- clumsy
+ bug
+
- org.codenarc.rule.unnecessary.UnnecessaryIfStatementRule
+ org.codenarc.rule.imports.MisorderedStaticImportsRuleMAJOR
-
-
- Checks for unnecessary if statements. The entire if statement, or at least the or block, are considered unnecessary for the four scenarios described below.
-
(1) When the and blocks contain only an explicit return of true and false constants. These cases can be replaced by a simple statement. Examples of violations include:
+
+
+ Checks for static statements which should never be after nonstatic imports.
+
This rule has one property comesBefore, which defaults to true. If you like your static imports to come after the others, then set this property to false.
+
Examples of violations:
- if (someExpression) // can be replaced by: return someExpression
- return true
- else
- return false
-
- if (someExpression) { // can be replaced by: return !someExpression
- return false
- } else {
- return true
- }
+ import my.something.another
+ import static foo.bar
- if (someExpression) { // can be replaced by: return someExpression
- return Boolean.TRUE
- } else {
- return Boolean.FALSE
- }
-
- def myMethod() {
- if (someExpression) { 123 }
- doSomething()
- }
+ public class MyClass{}
]]>
- clumsy
+ bug
+
+ comesBefore
+
+ true
+
+
- org.codenarc.rule.unnecessary.UnnecessaryTernaryExpressionRule
+ org.codenarc.rule.imports.NoWildcardImportsRuleMAJOR
-
-
- Checks for ternary expressions where the conditional expression always evaluates to a boolean and the and expressions are merely returning true and false constants. These cases can be replaced by a simple boolean expression. Examples of violations include:
+
+
+ Wildcard imports, static or otherwise, should not be used.
+
Example of violations:
- x==99 ? true : false // can be replaced by: x==99
- x && y ? true : false // can be replaced by: x && y
- x||y ? false : true // can be replaced by: !(x||y)
- x >= 1 ? true: false // can be replaced by: x >= 1
- x < 99 ? Boolean.TRUE : Boolean.FALSE // can be replaced by: x < 99
- !x ? true : false // can be replaced by: !x
+ import my.something.*
+ import static foo.bar.*
+
+ public class MyClass{}
+]]>
+ bug
+
+
+
+
+
+
+ org.codenarc.rule.jdbc.DirectConnectionManagementRule
+ MINOR
+
+
+ The J2EE standard requires that applications use the container's resource management facilities to obtain connections to resources. Every major web application container provides pooled database connection management as part of its resource management framework. Duplicating this functionality in an application is difficult and error prone, which is part of the reason it is forbidden under the J2EE standard.
+
- x ? '123' : '123' // can be replaced by: '123'
- x ? null : null // can be replaced by: null
- x ? 23 : 23 // can be replaced by: 23
- x ? MAX_VALUE : MAX_VALUE // can be replaced by: MAX_VALUE
- ready ? minValue : minValue // can be replaced by: minValue
+ DriverManager.getConnection()
+ java.sql.DriverManager.getConnection()
]]>
- clumsy
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryBigDecimalInstantiationRule
- MAJOR
-
-
- It is unnecessary to instantiate BigDecimal objects. Instead just use the decimal literal or the 'G' identifier to force the type, such as 123.45 or 123.45G.
-
This rule does not produce violations when the parameter evaluates to an integer/long, e.g. new BigDecimal(42), new BigDecimal(42L) or new BigDecimal("42"), because using the "G" suffix on an integer value produces a BigInteger, rather than a BigDecimal, e.g. 45G. So that means there is no way to produce a BigDecimal with exactly that value using a literal.
-
This rule also does not produce violations when the parameter is a double, e.g. new BigDecimal(12.3). That scenario is covered by the BigDecimalInstantiation rule, because that produces an unpredictable (double) value (and so it is , rather than ).
+ org.codenarc.rule.jdbc.JdbcConnectionReferenceRule
+ MINOR
+
+
+ Checks for direct use of java.sql.Connection, which is discouraged and almost never necessary in application code.
+
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
]]>
- clumsy
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryBigIntegerInstantiationRule
- MAJOR
-
-
- It is unnecessary to instantiate BigInteger objects. Instead just use the literal with the 'G' identifier to force the type, such as 8G or 42G.
+ org.codenarc.rule.jdbc.JdbcResultSetReferenceRule
+ MINOR
+
+
+ Checks for direct use of java.sql.ResultSet, which is not necessary if using the Groovy Sql facility or an ORM framework such as .
+
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
]]>
- clumsy
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryBooleanInstantiationRule
- MAJOR
-
-
- Checks for direct call to a Boolean constructor. Use Boolean.valueOf() or the Boolean.TRUE and Boolean.FALSE constants instead of calling the Boolean() constructor directly.
-
Also checks for Boolean.valueOf(true) or Boolean.valueOf(false). Use the Boolean.TRUE or Boolean.FALSE constants instead.
-
Here is an example of code that produces a violation:
+ org.codenarc.rule.jdbc.JdbcStatementReferenceRule
+ MINOR
+
+
+ Checks for direct use of java.sql.Statement, java.sql.PreparedStatement, or java.sql.CallableStatement, which is not necessary if using the Groovy Sql facility or an ORM framework such as .
+
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
]]>
- clumsy
+ bug
-
+
+
- org.codenarc.rule.unnecessary.UnnecessaryCallForLastElementRule
- MAJOR
-
-
- This rule checks for excessively verbose methods of accessing the last element of an array or list. For instance, it is possible to access the last element of an array by performing array[array.length - 1], in Groovy it is simpler to either call array.last() or array[-1]. The same is true for lists. This violation is triggered whenever a get, getAt, or array-style access is used with an object size check.
-
Code like this all cause violations.
-
- def x = [0, 1, 2]
- def a = x.get(x.size() -1)
- def b = x.get(x.length -1)
- def c = x.getAt(x.size() -1)
- def d = x.getAt(x.length -1)
- def f = x[(x.size() -1]
- def d = x[(x.length -1]
-
-
- def x = [0, 1, 2]
- def a = x.last()
- def b = x[-1]
- def c = x.getAt(-1)
- def d = x.get(z.size() -1) // different objects
- def e = x.get(z.length -1) // different objects
- def f = x.getAt(z.size() -1) // different objects
-
+ org.codenarc.rule.junit.JUnitAssertAlwaysFailsRule
+ MINOR
+
+
+ Rule that checks for JUnit <<>> method calls with constant or literal arguments such that theassertion always fails. This includes:
]]>
- clumsy
+ junit
-
- org.codenarc.rule.unnecessary.UnnecessaryCatchBlockRule
- MAJOR
-
-
- Violations are triggered when a block does nothing but throw the original exception. In this scenario there is usually no need for a block, just let the exception be thrown from the original code. This condition frequently occurs when catching an exception for debugging purposes but then forgetting to take the catch statement out.
- ]]>
- clumsy
+ org.codenarc.rule.junit.JUnitAssertAlwaysSucceedsRule
+ MINOR
+
+
+ Rule that checks for JUnit assert() method calls with constant arguments such that the assertion always succeeds. This includes:
+]]>
+ junit
-
- org.codenarc.rule.unnecessary.UnnecessaryCollectCallRule
- MAJOR
-
-
- Some method calls to Object.collect(Closure) can be replaced with the spread operator. For instance, list.collect { it.multiply(2) } can be replaced by list*.multiply(2).
-
- [1, 2, 3].collect { it * it } // OK, closure parameter is referenced twice
-
- [1, 2, 3].mapMethod { it.multiply(5) } // OK, method call is not collect
-
- [1, 2, 3].collect(5) // OK, collect parameter is not a closure
-
- // OK, the closure is not a simple one line statement
- [1, 2, 3].collect { println it; it.multiply(5) }
-
- // OK, closure has too many arguments
- [1, 2, 3].collect { a, b -> a.multiply(b) }
-
- // OK, closure statement references parameter multiple times
- [1, 2, 3].collect { it.multiply(it) }
-
- // OK, it is referenced several times in the closure
- [1, 2, 3].collect { it.multiply(2).multiply(it) }
- ["1", "2", "3"].collect { it.bytes.foo(it) }
-
- // OK, chained methods are too complex to analyze at this point
- [1, 2, 3].collect { it.multiply(2).multiply(4) }
-
- // in general the above examples can be rewritten like this:
- [1, 2, 3]*.multiply(2)
- ["1", "2", "3"]*.bytes
-
+ org.codenarc.rule.junit.JUnitPublicNonTestMethodRule
+ MINOR
+
+
+ Rule that checks if a JUnit test class contains public methods other than standard test methods, JUnit framework methods or methods with JUnit annotations.
+
The following public methods are ignored by this rule:
]]>
- clumsy
+ junit
-
- org.codenarc.rule.unnecessary.UnnecessaryCollectionCallRule
- MAJOR
-
-
- Checks for useless calls to collections. For any collection c, calling c.containsAll(c) should always be true, and c.retainAll(c) should have no effect.
+ org.codenarc.rule.junit.JUnitSetUpCallsSuperRule
+ MINOR
+
+
+ Rule that checks that if the JUnit setUp method is defined, that it includes a call to super.setUp().
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
- clumsy
+ junit
-
- org.codenarc.rule.unnecessary.UnnecessaryConstructorRule
+ org.codenarc.rule.junit.JUnitTearDownCallsSuperRule
+ MINOR
+
+
+ Rule that checks that if the JUnit tearDown method is defined, that it includes a call to super.tearDown().
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ ]]>
+ junit
+
+
+
+ org.codenarc.rule.junit.JUnitUnnecessarySetUpRuleMAJOR
-
-
- This rule detects when a constructor is not necessary; i.e., when there's only one constructor, it's public, has an empty body, and takes no arguments, or else contains only a single call to super().
-
Example of violations:
+
+
+ Rule that checks checks for JUnit setUp() methods that contain only a call to super.setUp(). The method is then unnecessary.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
Here is an example of a violation:
- class MyClass {
- public MyClass() { // violation; constructor is not necessary
- }
- }
-
- class MyClass2 extends OtherClass {
- MyClass2() { // violation; constructor is not necessary
- super()
+ class MyTest extends TestCase {
+ void setUp() { // violation
+ super.setUp()
}
}
]]>
- clumsy
+ junit
-
- org.codenarc.rule.unnecessary.UnnecessaryDoubleInstantiationRule
+ org.codenarc.rule.junit.JUnitUnnecessaryTearDownRuleMAJOR
-
-
- It is unnecessary to instantiate Double objects. Instead just use the double literal with 'D' identifier to force the type, such as 123.45d or 0.42d.
- ]]>
- clumsy
-
-
-
+
+
+ Rule that checks checks for JUnit tearDown() methods that contain only a call to super.tearDown(). The method is then unnecessary.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+]]>
+ junit
+
+
+
- org.codenarc.rule.unnecessary.UnnecessaryFloatInstantiationRule
+ org.codenarc.rule.junit.JUnitStyleAssertionsRuleMAJOR
-
-
- It is unnecessary to instantiate Float objects. Instead just use the float literal with the 'F' identifier to force the type, such as 123.45F or 0.42f.
+
+
+ This rule detects calling JUnit style assertions like assertEquals, assertTrue, assertFalse, assertNull, assertNotNull. Groovy 1.7 ships with a feature called the "power assert", which is an assert statement with better error reporting. This is preferable to the JUnit assertions.
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryGetterRule
+ org.codenarc.rule.junit.UseAssertEqualsInsteadOfAssertTrueRuleMAJOR
-
-
- Checks for explicit calls to getter/accessor methods which can, for the most part, be replaced by property access. A getter is defined as a method call that matches get[A-Z] but not getClass() or get[A-Z][A-Z] such as getURL(). Getters do not take method arguments.
-
-]]>
- clumsy
+
+
+ This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ ]]>
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryGStringRule
+ org.codenarc.rule.junit.UseAssertFalseInsteadOfNegationRule
+ MINOR
+
+
+ In unit tests, if a condition is expected to be false then there is no sense using assertTrue with the negation operator. For instance, assertTrue(!condition) can always be simplified to assertFalse(condition).
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ ]]>
+ junit
+
+
+
+
+ org.codenarc.rule.junit.UseAssertTrueInsteadOfAssertEqualsRuleMAJOR
-
-
- String objects should be created with single quotes, and GString objects created with double quotes. Creating normal String objects with double quotes is confusing to readers.
-
Example of violations:
+
+
+ This rule detects JUnit calling assertEquals where the first parameter is a boolean. These assertions should be made by more specific methods, like assertTrue or assertFalse.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ All of the following examples can be simplified to assertTrue or remove the true literal:
- def a = "I am a string" // violation
-
- // violation
- def b = """
- I am a string
- """
-
- def c = "I am a ' string" // OK
-
- def d = """I am a ' string""" // OK
-
- def e = """I am a ' string""" // OK
-
- def f = "I am a \$ string" // OK
-
- // OK
- def g = """
- I am a \$ string
- """
-
- // OK
- def h = """
- I am a $string
- """
+ assertEquals(true, foo())
+ assertEquals("message", true, foo())
+ assertEquals(foo(), true)
+ assertEquals("message", foo(), true)
+ assertEquals(false, foo())
+ assertEquals("message", false, foo())
+ assertEquals(foo(), false)
+ assertEquals("message", foo(), false)
- def i = 'i am a string'
- def j = '''i am a
- string
- '''
+ assert true == foo() // violation only if checkAssertStatements == true
+ assert foo() == true : "message" // violation only if checkAssertStatements == true
+ assert false == foo() // violation only if checkAssertStatements == true
+ assert foo() == false : "message" // violation only if checkAssertStatements == true
]]>
- clumsy
+ junit
+
+ checkAssertStatements
+
+ false
+
-
+
- org.codenarc.rule.unnecessary.UnnecessaryInstantiationToGetClassRule
+ org.codenarc.rule.junit.UseAssertNullInsteadOfAssertEqualsRuleMAJOR
-
-
- Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
-
- public class Foo {
- // Replace this
- Class c = new String().getClass();
+
+
+ This rule detects JUnit calling assertEquals where the first or second parameter is null. These assertion should be made against the assertNull method instead.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ ]]>
+ junit
+
- // with this:
- Class c = String.class;
- }
-
+
+
+ org.codenarc.rule.junit.UseAssertSameInsteadOfAssertTrueRule
+ MAJOR
+
+
+ This rule detects JUnit calling assertTrue or assertFalse where the first or second parameter is an Object#is() call testing for reference equality. These assertion should be made against the assertSame or assertNotSame method instead.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryIntegerInstantiationRule
- MAJOR
-
-
- It is unnecessary to instantiate Integer objects. Instead just use the literal with the 'I' identifier to force the type, such as 8I or 42i.
+ org.codenarc.rule.junit.JUnitFailWithoutMessageRule
+ MINOR
+
+
+ This rule detects JUnit calling the fail() method without an argument. For better error reporting you should always provide a message.
]]>
- clumsy
+ junit
- org.codenarc.rule.unnecessary.UnnecessaryLongInstantiationRule
- MAJOR
-
-
- It is unnecessary to instantiate Long objects. Instead just use the literal with the 'L' identifier to force the type, such as 8L or 42L.
+ org.codenarc.rule.junit.UseAssertTrueInsteadOfNegationRule
+ MINOR
+
+
+ In unit tests, if a condition is expected to be true then there is no sense using assertFalse with the negation operator. For instance, assertFalse(!condition) can always be simplified to assertTrue(condition).
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
- clumsy
+ junit
- org.codenarc.rule.unnecessary.UnnecessaryObjectReferencesRule
- MAJOR
-
-
- Violations are triggered when an excessive set of consecutive statements all reference the same variable. This can be made more readable by using a with or identity block. By default, 5 references are allowed. You can override this property using the maxReferencesAllowed property on the rule.
-
These two bits of code produce violations:
+ org.codenarc.rule.junit.JUnitTestMethodWithoutAssertRule
+ MINOR
+
+
+ This rule searches for test methods that do not contain assert statements. Either the test method is missing assert statements, which is an error, or the test method contains custom assert statements that do not follow a proper assert naming convention. Test methods are defined as public void methods that begin with the work test or have a @Test annotation. By default this rule applies to the default test class names, but this can be changed using the rule's applyToClassNames property. An assertion is defined as either using the assert keyword or invoking a method that starts with the work assert, like assertEquals, assertNull, or assertMyClassIsSimilar. Also, any method named should.* also counts as an assertion so that shouldFail methods do not trigger an assertion, any method that starts with fail counts as an assertion, and any method that starts with verify counts as an assertion. Since version 0.23 CodeNarc has support for JUnit's ExpectedException.
+
What counts as an assertion method can be overridden using the assertMethodPatterns property of the rule. The default value is this comma separated list of regular expressions:
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryNullCheckRule
- MAJOR
-
-
- Groovy contains the safe dereference operator. It can be used in boolean conditional statements to safely replace explicit x == null tests. Also, testing the 'this' or 'super' reference for null equality is pointless and can be removed.
-
Examples of violations:
+ org.codenarc.rule.junit.ChainedTestRule
+ MINOR
+
+
+ A test method that invokes another test method is a chained test; the methods are dependent on one another. Tests should be isolated, and not be dependent on one another.
+
Example of violations:
- if (obj != null && obj.method()) { }
-
- if (obj != null && obj.prop) { }
+ class MyTest extends GroovyTestCase {
+ public void testFoo() {
- // this is pointless and won't avoid NullPointerException
- if (obj.method() && obj != null ) { }
-
- if (this == null) { }
- if (null == this) { }
- if (this != null) { }
- if (null != this) { }
-
- if (super == null) { }
- if (null == super) { }
- if (super != null) { }
- if (null != super) { }
-
-
- // null check it OK
- if (obj != null) { }
-
- // null safe dereference in if is OK
- if (obj?.method()) { }
+ // violations, calls test method on self
+ 5.times { testBar() }
+ 5.times { this.testBar() }
- // null safe dereference in ternary is OK
- (obj?.prop && obj?.prop2) ? x : y
+ // OK, no violation: one arg method is not actually a test method
+ 5.times { testBar(it) }
+ }
- // obj is reused in a parameter list, so OK
- if (obj != null && obj.method() && isValid(obj)) { }
+ private static void assertSomething() {
+ testBar() // violation, even if in helper method
+ this.testBar() // violation, even if in helper method
+ }
- // rule is not so complex yet...
- (obj != null && obj.prop && obj.method()) ? x : y
+ public void testBar() {
+ // ...
+ }
+ }
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryNullCheckBeforeInstanceOfRule
- MAJOR
-
-
- There is no need to check for null before an instanceof; the instanceof keyword returns false when given a null argument.
-
Example:
+ org.codenarc.rule.junit.CoupledTestCaseRule
+ MINOR
+
+
+ This rule finds test cases that are coupled to other test cases, either by invoking static methods on another test case or by creating instances of another test case. If you require shared logic in test cases then extract that logic to a new class where it can properly be reused. Static references to methods on the current test class are ignored.
+
Example of violations:
- if (x != null && x instanceof MyClass) {
- // should drop the "x != null" check
- }
-
- if (x instanceof MyClass && x != null) {
- // should drop the "x != null" check
- }
+ class MyTest extends GroovyTestCase {
+ public void testMethod() {
+ // violation, static method call to other test
+ MyOtherTest.helperMethod()
- // should drop the "x != null" check
- (x != null && x instanceof MyClass) ? foo : bar
+ // violation, instantiation of another test class
+ new MyOtherTest()
- if (x != null && x instanceof MyClass && x.isValid()) {
- // this is OK and causes no violation because the x.isValid() requires a non null reference
+ // no violation; same class
+ def input = MyTest.getResourceAsStream('sample.txt')
+ }
}
]]>
- clumsy
-
-
-
-
- org.codenarc.rule.unnecessary.UnnecessaryOverridingMethodRule
- MAJOR
-
-
- Checks for an overriding method that merely calls the same method defined in a superclass. Remove it.
- ]]>
- clumsy
-
-
-
-
- org.codenarc.rule.unnecessary.UnnecessaryReturnKeywordRule
- MAJOR
-
-
- In Groovy, the return keyword is often optional. If a statement is the last line in a method or closure then you do not need to have the return keyword.
- ]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryStringInstantiationRule
- MAJOR
-
-
- Checks for direct call to the String constructor that accepts a String literal. In almost all cases, this is unnecessary. Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.
-
Here is an example of code that produces a violation:
+ org.codenarc.rule.junit.UnnecessaryFailRule
+ MINOR
+
+
+ In a unit test, catching an exception and immediately calling Assert.fail() is pointless and hides the stack trace. It is better to rethrow the exception or not catch the exception at all.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.AddEmptyStringRule
+ org.codenarc.rule.junit.SpockIgnoreRestUsedRule.fixedMINOR
-
-
- Finds empty string literals which are being added. This is an inefficient way to convert any type to a String.
-
Examples:
+
+
+ If Spock's @IgnoreRest annotation appears on any method, all non-annotated test methods are not executed. This behaviour is almost always unintended. It's fine to use @IgnoreRest locally during development, but when committing code, it should be removed.
+
The and properties determine which classes are considered Spock classes.
+
Example of violations:
- // do not add empty strings to things
- def a = '' + 123
- def b = method('' + property)
+ public class MySpec extends spock.lang.Specification {
+ @spock.lang.IgnoreRest
+ def "my first feature"() {
+ expect: false
+ }
- // these examples are OK and do not trigger violations
- def c = 456.toString()
- def d = property?.toString() ?: ""
+ def "my second feature"() {
+ given: def a = 2
+
+ when: a *= 2
+
+ then: a == 4
+ }
+ }
]]>
- clumsy
+ junit
+
+ specificationClassNames
+
+
+
+ specificationSuperclassNames
+
+ *Specification
+
-
+
- org.codenarc.rule.unnecessary.ConsecutiveLiteralAppendsRule
+ org.codenarc.rule.junit.JUnitLostTestRuleMINOR
-
-
- Violations occur when method calls to append(Object) are chained together with literals as parameters. The chained calls can be joined into one invocation.
+
+
+ This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named * that is not annotated with the JUnit 4 @Test annotation.
+
Note: This rule should be disabled for Grails 2.x projects, since the Grails test framework can use AST Transformations to automatically annotate test methods.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
Example of violations:
- writer.append('foo').append('bar') // strings can be joined
- writer.append('foo').append(5) // string and number can be joined
- writer.append('Hello').append("$World") // GString can be joined
-
-
- // usage not chained invocation
- writer.append('Hello')
- writer.append('World')
-
- writer.append(null).append(5) // nulls cannot be joined
+ import org.junit.Test
- writer.append().append('Hello') // no arg append is unknown
- writer.append('a', 'b').append('Hello') // two arg append is unknown
+ class MyTestCase {
+ void testMe() { } // missing @Test annotation
+ }
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.ConsecutiveStringConcatenationRule
+ org.codenarc.rule.junit.JUnitUnnecessaryThrowsExceptionRuleMAJOR
-
-
- Catches concatenation of two string literals on the same line. These can safely by joined. In Java, the Java compiler will join two String literals together and place them in the Constant Pool. However, Groovy will not because the plus() method may override the + operator.
-
Examples:
+
+
+ Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
Example of violations:
- // Violations
- def a = 'Hello' + 'World' // should be 'HelloWorld'
- def b = "$Hello" + 'World' // should be "${Hello}World"
- def c = 'Hello' + "$World" // should be "Hello${World}"
- def d = 'Hello' + 5 // should be 'Hello5'
- def e = 'Hello' + '''
- world // should be joined
- '''
- def f = '''Hello
- ''' + 'world' // should be joined
+ @Test
+ void shouldDoStuff() throws Exception { } // violation
+ @BeforeClass void initialize() throws Exception { } // violation
+ @Before void setUp() throws RuntimeException { } // violation
+ @After void tearDown() throws Exception { } // violation
+ @AfterClass void cleanUp() throws Exception { } // violation
+ @Ignore void ignored() throws Exception { } // violation
+
+ class MyTest extends GroovyTestCase {
+ void test1() throws Exception { } // violation
+ public void test2() throws IOException { } // violation
+ }
- // Not Violations
- def g = 'Hello' + // OK because of line break
- 'World'
- def h = 'Hello' + null // OK because not a string
- def i = 'Hello' + method() // OK because not a string
- def j = 'Hello' - "$World" // OK because not +
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryCallToSubstringRule
+ org.codenarc.rule.junit.JUnitPublicFieldRuleMAJOR
-
-
- Calling String.substring(0) always returns the original string. This code is meaningless.
-
Examples:
-
- string.substring(0) // violation
- method().substring(0) // violation
-
- prop.substring(1) // OK, not constant 0
- prop.substring(0, 1) // OK, end is specified
-
-]]>
- clumsy
-
-
-
-
- org.codenarc.rule.unnecessary.UnnecessaryDefInMethodDeclarationRule
- MAJOR
-
-
- If a method has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private method() {}' is redundant and can be simplified to 'private method() {}'.
-
Examples of violations:
+
+
+ Checks for public fields on a JUnit test class. There is usually no reason to have a public field (even a constant) on a test class.
+
Fields within interfaces and fields annotated with @Rule are ignored.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
Example of violations:
- // def and private is redundant
- def private method1() { return 4 }
-
- // def and protected is redundant
- def protected method2() { return 4 }
-
- // def and public is redundant
- def public method3() { return 4 }
-
- // def and static is redundant
- def static method4() { return 4 }
-
- // def and type is redundant
- def Object method5() { return 4 }
+ import org.junit.Test
+ class MyTestCase {
+ public int count // violation
+ public static final MAX_VALUE = 1000 // violation
- class MyClass {
- def MyClass() {} // def is redundant
+ @Test
+ void testMe() { }
}
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryModOneRule
- MAJOR
-
-
- Any expression mod 1 (exp % 1) is guaranteed to always return zero. This code is probably an error, and should be either (exp & 1) or (exp % 2).
-
Examples:
+ org.codenarc.rule.junit.JUnitAssertEqualsConstantActualValueRule
+ MINOR
+
+
+ Reports usages of org.junit.Assert.assertEquals([message,] expected, actual) where the actual parameter is a constant or a literal. Most likely it was intended to be the expected value.
+
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
+
Example of violations:
- if (exp % 1) {} // violation
- if (method() % 1) {} // violation
-
- if (exp & 1) {} // ok
- if (exp % 2) {} // ok
+ assertEquals(result, 2)
+ assertEquals("Message", result, 2)
+ assertEquals(result, 2.3d, 0.5d)
+ assertEquals("Message", result, 2.3d, 0.5d)
]]>
- clumsy
+ junit
-
+
- org.codenarc.rule.unnecessary.UnnecessaryPublicModifierRule
- MAJOR
-
-
- The 'public' modifier is not required on methods, constructors or classes.
+ org.codenarc.rule.junit.JUnitPublicPropertyRule.fixed
+ MINOR
+
+
+ Checks for public properties defined on JUnit test classes. There is typically no need to expose a public property (with public and methods) on a test class.
+
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
Example of violations:
- // violation on class
- public class MyClass {
- // violation on constructor
- public MyClass() {}
+ import org.junit.Test
+ class MyTestCase {
+ static String id // violation
+ def helper // violation
+ String name // violation
- // violation on method
- public void myMethod() {}
+ @Test
+ void testMe() { }
}
]]>
- clumsy
+ junit
+
+ ignorePropertyNames
+
+
-
-
- org.codenarc.rule.unnecessary.UnnecessarySelfAssignmentRule
- MAJOR
-
-
- Method contains a pointless self-assignment to a variable or property. Either the code is pointless or the equals()/get() method has been overridden to have a side effect, which is a terrible way to code getters and violates the contract of equals().
-
Examples:
-
- x = x // violation
- def method(y) {
- y = y // violation
- }
- a.b.c = a.b.c // violation
+
- x = y // acceptable
- a.b = a.zz // acceptable
- a.b = a().b // acceptable
-
-]]>
- clumsy
+
+ org.codenarc.rule.logging.PrintlnRule
+ MINOR
+
+
+ Checks for calls to this.print(), this.println() or this.printf(). Consider using a standard logging facility instead.
+ ]]>
+ bug
-
- org.codenarc.rule.unnecessary.UnnecessarySemicolonRule
- MAJOR
-
-
- Semicolons as line terminators are not required in Groovy: remove them. Do not use a semicolon as a replacement for empty braces on for and while loops; this is a confusing practice.
-
The rule contains a String property called 'excludePattern'. Any source code line matching this pattern will not trigger a violation. The default value is '\\s?\\*.*|/\\*.*|.*//.*|.*\\*/.*' This is to filter out comments. Any source line that even looks like it is a comment is ignored.
-
\s?\*.* == whitespace plus star character plus anything /\*.* == any line that contains the /* sequence .*//.* == any line that contains the // sequence .*\*/.* == any line that contains the */ sequence
-
Example of violations:
-
- package my.company.server; // violation
-
- import java.lang.String; // violation
-
- println(value) ; // violation
-
- for (def x : list); // violation
-
- // this code is OK
- println(value); println (otherValue)
-
-]]>
- clumsy
+ org.codenarc.rule.logging.PrintStackTraceRule
+ MINOR
+
+
+ Checks for calls to Throwable.printStackTrace() or StackTraceUtils.printSanitizedStackTrace(Throwable). Consider using a standard logging facility instead.
+ ]]>
+ bug
-
- org.codenarc.rule.unnecessary.UnnecessaryTransientModifierRule
- MAJOR
-
-
- The field is marked as transient, but the class isn't Serializable, so marking it as transient has no effect. This may be leftover marking from a previous version of the code in which the class was transient, or it may indicate a misunderstanding of how serialization works.
-
Some Java frameworks change the semantics of the transient keyword. For instance, when using Terracotta the transient keyword may have slightly different semantics. You may need to turn this rule off depending on which Java frameworks are in use.
- Examples:
-
- class MyClass {
- // class not serializable, violation occurs
- transient String property
- }
+ org.codenarc.rule.logging.SystemErrPrintRule
+ MINOR
+
+
+ Checks for calls to System.err.print(), System.err.println() or System.err.printf(). Consider using a standard logging facility instead.
+ ]]>
+ bug
+
- class MySerializableClass implements Serializable {
- // OK, class is serializable
- transient String property
- }
-
+
+ org.codenarc.rule.logging.SystemOutPrintRule
+ MINOR
+
+
+ Checks for calls to System.out.print(), System.out.println() or System.out.printf(). Consider using a standard logging facility instead.
]]>
- clumsy
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryFinalOnPrivateMethodRule
- MAJOR
-
-
- A private method is marked final. Private methods cannot be overridden, so marking it final is unnecessary.
-
Example of violations:
-
- private final method() {}
-
+ org.codenarc.rule.logging.LoggerForDifferentClassRule
+ MINOR
+
+
+ Checks for instantiating a logger for a class other than the current class. Checks for logger instantiations for Log4J, SLF4J, Logback, Apache Commons Logging and Java Logging API (java.util.logging).
+
This rule contains a parameter allowDerivedClasses. When set, a logger may be created about this.getClass().
+
Limitations:
]]>
- clumsy
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryElseStatementRule
- MAJOR
-
-
- When an if statement block ends with a return statement, then the else is unnecessary. The logic in the else branch can be run without being in a new scope.
-
-]]>
- clumsy
+ org.codenarc.rule.logging.LoggingSwallowsStacktraceRule
+ MINOR
+
+
+ If you are logging an exception then the proper API is to call error(Object, Throwable), which will log the message and the exception stack trace. If you call error(Object) then the stacktrace may not be logged.
+ ]]>
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryParenthesesForMethodCallWithClosureRule
- MAJOR
-
-
- If a method is called and the only parameter to that method is an inline closure then the parentheses of the method call can be omitted.
-
Example of violations:
-
- [1,2,3].each() { println it }
-
-]]>
- clumsy
-
-
-
-
- org.codenarc.rule.unnecessary.UnnecessaryPackageReferenceRule
- MAJOR
-
-
- Checks for explicit package reference for classes that Groovy imports by default, such as java.lang.String, java.util.Map and groovy.lang.Closure, as well as classes that were explicitly imported.
-
You do not need to specify the package for any classes from , , , , and , as well as the classes and .
-]]>
- clumsy
-
-
-
-
- org.codenarc.rule.unnecessary.UnnecessaryDefInVariableDeclarationRule
- MAJOR
-
-
- If a variable has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private n = 2' is redundant and can be simplified to 'private n = 2'.
-
Examples of violations:
-
- // def and private is redundant
- def private string1 = 'example'
-
- // def and protected is redundant
- def protected string2 = 'example'
-
- // def and public is redundant
- def public string3 = 'example'
-
- // def and static is redundant
- def static string4 = 'example'
-
- // def and final is redundant
- def final string5 = 'example'
-
- // def and a type is redundant
- def String string6 = 'example'
-
-]]>
- clumsy
-
-
-
-
- org.codenarc.rule.unnecessary.UnnecessaryDotClassRule
- MAJOR
-
-
- To make a reference to a class, it is unnecessary to specify the '.class' identifier. For instance String.class can be shortened to String.
-
Example of violations:
-
- // The '.class' identifier is unnecessary, violation occurs
- def x = String.class
-
- // Ok, unnecessary '.class' identifier has been excluded
- def x = String
-
-]]>
- clumsy
+ org.codenarc.rule.logging.LoggerWithWrongModifiersRule
+ MINOR
+
+
+ Logger objects should be declared private, static and final.
+
This rule has a property: allowProtectedLogger, which defaults to false. Set it to true if you believe subclasses should have access to a Logger in a parent class and that Logger should be declared protected or public.
+
This rule has a property: allowNonStaticLogger, which defaults to false. Set it to true if you believe a logger should be allowed to be non-static.
+ ]]>
+ bug
-
+
- org.codenarc.rule.unnecessary.UnnecessaryInstanceOfCheckRule
- MAJOR
-
-
- This rule finds instanceof checks that cannot possibly evaluate to true. For instance, checking that (!variable instanceof String) will never be true because the result of a not expression is always a boolean.
-
Example of violations:
-
- if (!variable instanceof String) { ... } // always false
- def x = !variable instanceof String // always false
-
- if (!variable instanceof Boolean) { ... } // always true
- def x = !variable instanceof Boolean // always true
-
- // this code is OK
- if (!(variable instanceof String)) { ... }
-
-]]>
- clumsy
+ org.codenarc.rule.logging.MultipleLoggersRule
+ MINOR
+
+
+ This rule catches classes that have more than one logger object defined. Typically, a class has zero or one logger objects.
+ ]]>
+ bug
-
-
- org.codenarc.rule.unnecessary.UnnecessarySubstringRule
- MAJOR
-
-
- This rule finds usages of String.substring(int) and String.substring(int, int) that can be replaced by use of the subscript operator. For instance, var.substring(5) can be replaced with var[5..-1].
-
Note that the String.substring(beginIndex,endIndex) method specifies a range of beginIndex..endIndex-1, while Groovy's String subscript specifies an inclusive range. So, "123456".substring(1, 5) is equivalent to "123456"[1..4].
-
Example of violations:
-
- myVar.substring(5) // can use myVar[5..-1] instead
- myVar.substring(1, 5) // can use myVar[1..4] instead
-
-]]>
- clumsy
-
+
-
- org.codenarc.rule.unnecessary.UnnecessaryDefInFieldDeclarationRule
- MAJOR
-
-
- If a field has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance, 'static def constraints = {}' is redundant and can be simplified to 'static constraints = {}.
-
Example of violations:
-
- class MyClass {
- // def is redundant
- static def constraints = { }
-
- // def and private is redundant
- def private field1 = { }
-
- // def and protected is redundant
- def protected field2 = { }
-
- // def and public is redundant
- def public field3 = { }
-
- // def and static is redundant
- def static field4 = { }
-
- // def and type is redundant
- def Object field5 = { }
- }
-
-]]>
- clumsy
+ org.codenarc.rule.naming.AbstractClassNameRule.fixed
+ MINOR
+
+
+ Verifies that the name of an abstract class matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active. This rule ignores interfaces and is applied only to abstract classes.
+ ]]>
+ bug
+
+ regex
+
+
-
- org.codenarc.rule.unnecessary.UnnecessaryCastRule
+ org.codenarc.rule.naming.ClassNameRuleMINOR
-
-
- Checks for unnecessary cast operations.
-
-]]>
- clumsy
+
+
+ Verifies that the name of a class matches a regular expression. By default it checks that the class name starts with an uppercase letter and is followed by zero or more word characters (letters, numbers or underscores) or dollar signs ($).
+ ]]>
+ bug
+
+ regex
+
+ ([A-Z]\w*\$?)*
+
-
- org.codenarc.rule.unnecessary.UnnecessaryToStringRule
+ org.codenarc.rule.naming.FieldNameRule.fixedMINOR
-
-
- Checks for unnecessary calls to toString(). This includes:
-]]>
- clumsy
+
+
+ Verifies that the name of each field matches a regular expression. By default it checks that fields that are not have field names that start with a lowercase letter and contains only letters or numbers. By default, field names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
+
NOTE: This rule checks only regular of a class, not . In Groovy, are fields declared with no access modifier (public, protected, private). Thus, this rule only checks fields that specify an access modifier. For naming of , see PropertyNameRule.
+
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the field is the one that is applied for the field name validation.
+ ]]>
+ bug
+
+ finalRegex
+
+
+
+ ignoreFieldNames
+
+ serialVersionUID
+
+
+ regex
+
+ [a-z][a-zA-Z0-9]*
+
+
+ staticFinalRegex
+
+ [A-Z][A-Z0-9_]*
+
+
+ staticRegex
+
+
-
- org.codenarc.rule.unnecessary.UnnecessarySafeNavigationOperatorRule
- MAJOR
-
-
- Check for the operator (?.) applied to constants and literals, or this or super, or constructor calls, all of which can never be null.
-
-]]>
- clumsy
+ org.codenarc.rule.naming.InterfaceNameRule.fixed
+ MINOR
+
+
+ Verifies that the name of an interface matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active.
+ ]]>
+ bug
+
+ regex
+
+
-
-
- org.codenarc.rule.unused.UnusedArrayRule
+ org.codenarc.rule.naming.MethodNameRule.fixedMINOR
-
-
- Checks for array allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
-
- int myMethod() {
- new String[3] // unused
- return -1
- }
-
- String[] myMethod() {
- new String[3] // OK (last statement in block)
- }
-
- def closure = {
- doStuff()
- new Date[3] // unused
- doOtherStuff()
- }
-
- def closure = { new Date[3] } // OK (last statement in block)
-
-]]>
+
+
+ Verifies that the name of each method matches a regular expression. By default it checks that the method name starts with a lowercase letter. Implicit method names are ignored (i.e., 'main' and 'run' methods automatically created for Groovy scripts).
+ ]]>bug
+
+ ignoreMethodNames
+
+
+
+ regex
+
+ [a-z]\w*
+
- org.codenarc.rule.unused.UnusedObjectRule
+ org.codenarc.rule.naming.PackageNameRuleMINOR
-
-
- Checks for object allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
-
By default, this rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'. Invoking constructors without using the result is a common pattern in tests.
-
- int myMethod() {
- new BigDecimal("23.45") // unused
- return -1
- }
-
- BigDecimal myMethod() {
- new BigDecimal("23.45") // OK (last statement in block)
- }
-
- def closure = {
- doStuff()
- new Date() // unused
- doOtherStuff()
- }
-
- def closure = { new Date() } // OK (last statement in block)
-
-]]>
+
+
+ Verifies that the package name of a class matches a regular expression. By default it checks that the package name consists of only lowercase letters and numbers, separated by periods.
+ ]]>bug
+
+ packageNameRequired
+
+ false
+
+
+ regex
+
+ [a-z]+[a-z0-9]*(\.[a-z0-9]+)*
+
- org.codenarc.rule.unused.UnusedPrivateFieldRule
+ org.codenarc.rule.naming.ParameterNameRule.fixedMINOR
-
-
- Checks for private fields that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes). By default, fields named serialVersionUID are ignored. The rule has a property named ignoreFieldNames, which can be set to ignore other field names as well. For instance, to ignore fields named 'fieldx', set the property to the 'fieldx, serialVersionUID'
-
Known limitations:
-]]>
+
+
+ Verifies that the name of each parameter matches a regular expression. This rule applies to method parameters, constructor parameters and closure parameters. By default it checks that parameter names start with a lowercase letter and contains only letters or numbers.
+ ]]>bug
- ignoreFieldNames
-
- serialVersionUID
+ ignoreParameterNames
+
+
+
+ regex
+
+ [a-z][a-zA-Z0-9]*
- org.codenarc.rule.unused.UnusedPrivateMethodRule
+ org.codenarc.rule.naming.PropertyNameRule.fixedMINOR
-
-
- Checks for private methods that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
-
Known limitations:
-]]>
+
+
+ Verifies that the name of each property matches a regular expression. By default it checks that property names (other than ) start with a lowercase letter and contains only letters or numbers. By default, property names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
+
NOTE: This rule checks only of a class, not regular . In Groovy, are fields declared with no access modifier (public, protected, private). For naming of regular , see FieldNameRule.
+
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the property is the one that is applied for the field name validation.
+ ]]>bug
+
+ finalRegex
+
+
+
+ ignorePropertyNames
+
+
+
+ regex
+
+ [a-z][a-zA-Z0-9]*
+
+
+ staticFinalRegex
+
+ [A-Z][A-Z0-9_]*
+
+
+ staticRegex
+
+
-
- org.codenarc.rule.unused.UnusedVariableRule.fixed
- MINOR
-
-
- Checks for variables that are never referenced.
-
The rule has a property named ignoreVariableNames, which can be set to ignore some variable names. For instance, to ignore fields named 'unused', set the property to 'unused'.
-
Known limitations:
+
+ org.codenarc.rule.naming.VariableNameRule.fixed
+ MINOR
+
+
+ Verifies that the name of each variable matches a regular expression. By default it checks that non-final variable names start with a lowercase letter and contains only letters or numbers. By default, final variable names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
]]>bug
+
+ finalRegex
+
+ [A-Z][A-Z0-9_]*
+
ignoreVariableNames
+
+ regex
+
+ [a-z][a-zA-Z0-9]*
+
-
+
- org.codenarc.rule.unused.UnusedPrivateMethodParameterRule
+ org.codenarc.rule.naming.ConfusingMethodNameRuleMINOR
-
-
- Checks for parameters to private methods that are not referenced within the method body. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
-
Known limitations:
+
+
+ Checks for very confusing method names. The referenced methods have names that differ only by capitalization. This is very confusing because if the capitalization were identical then one of the methods would override the other.
+
Also, violations are triggered when methods and fields have very similar names.
+
+ class MyClass {
+ int total
+ int total() {
+ 1
+ }
+ }
+
]]>bug
-
+
- org.codenarc.rule.unused.UnusedMethodParameterRule
+ org.codenarc.rule.naming.ObjectOverrideMisspelledMethodNameRuleMINOR
-
-
- This rule finds instances of method parameters not being used. It does not analyze private methods (that is done by the UnusedPrivateMethodParameter rule) or methods marked @Override.
+
+
+ Verifies that the names of the most commonly overridden methods of Object: equals, hashCode and toString, are correct.
+
Here are some examples of code that produces violations:
+
+ boolean equal(Object o) {} // violation
+ boolean equal(int other) {} // ok; wrong param type
+ boolean equal(Object o, int other) {} // ok; too many params
+
+ boolean equaLS(Object o) {} // violation
+
+ int hashcode() {} // violation
+ int hashCOde() {} // violation
+ int hashcode(int value) {} // ok; not empty params
+
+ String tostring() {} // violation
+ String toSTring() {} // violation
+ String tostring(int value) {} // ok; not empty params
+
]]>bug
-
-
-
+
- org.codenarc.rule.jdbc.DirectConnectionManagementRule
+ org.codenarc.rule.naming.FactoryMethodNameRuleMINOR
-
-
- The J2EE standard requires that applications use the container's resource management facilities to obtain connections to resources. Every major web application container provides pooled database connection management as part of its resource management framework. Duplicating this functionality in an application is difficult and error prone, which is part of the reason it is forbidden under the J2EE standard.
-
+
+
+ A factory method is a method that creates objects, and they are typically named either buildFoo(), makeFoo(), or createFoo(). This rule enforces that only one naming convention is used. It defaults to allowing makeFoo(), but that can be changed using the property regex. The regex is a negative expression; it specifically bans methods named build* or create*. However, methods named build or build* receive some special treatment because of the popular Builder Pattern. If the 'build' method is in a class named *Builder then it does not cause a violation.
+
Builder methods are slightly different than factory methods.
Example of violations:
- DriverManager.getConnection()
- java.sql.DriverManager.getConnection()
+ class MyClass {
+
+ // violation. Factory methods should be named make()
+ def create() {
+ }
+
+ // violation. Factory methods should be named make()
+ def createSomething() {
+ }
+
+ // violation. Builder method not in class named *Builder
+ def build() {
+ }
+
+ // violation. Builder method not in class named *Builder
+ def buildSomething() {
+ }
+
+ // this is OK because it is called make
+ def make() {
+ }
+
+ // this is also OK
+ def makeSomething() {
+ }
+
+ // OK, overriding a parent
+ @Override
+ build() { }
+
+ }
+
+ class WidgetBuilder {
+
+ // OK, the class name ends in Builder
+ def build() {
+ }
+ }
]]>bug
+
+ regex
+
+ (build.*\|create.*)
+
-
+
- org.codenarc.rule.jdbc.JdbcConnectionReferenceRule
+ org.codenarc.rule.naming.ClassNameSameAsFilenameRuleMINOR
-
-
- Checks for direct use of java.sql.Connection, which is discouraged and almost never necessary in application code.
-
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
+
+
+ Reports files containing only one top level class / enum / interface which is named differently than the file.
]]>bug
-
+
- org.codenarc.rule.jdbc.JdbcResultSetReferenceRule
+ org.codenarc.rule.naming.PackageNameMatchesFilePathRule.fixedMINOR
-
-
- Checks for direct use of java.sql.ResultSet, which is not necessary if using the Groovy Sql facility or an ORM framework such as .
-
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
+
+
+ A package source file's path should match the package declaration.
]]>bug
+
+ groupId
+ part of a package name, that will appear within all checked package names. It must also map to the file path for the correspondin source file. For instance, a of <"org.sample"> means that for all classes that specify a package, that package name must include <"org.sample">, and the source file must exist under an "org/sample" directory. Then, a MyClass class in a org.sample.util package must be defined in a "MyClass.groovy" file within a <"org/sample/util"> directory. That directory can be the child of any arbitrary , e.g. "src/main/groovy". To find the sub-path relevant for the package the rule searches for the first appearance of in the file path. It's to configure this. If groupId is null or empty, this rule does nothing. ]]>
+
-
+
- org.codenarc.rule.jdbc.JdbcStatementReferenceRule
+ org.codenarc.rule.naming.ClassNameSameAsSuperclassRuleMINOR
-
-
- Checks for direct use of java.sql.Statement, java.sql.PreparedStatement, or java.sql.CallableStatement, which is not necessary if using the Groovy Sql facility or an ORM framework such as .
-
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
+
+
+ Checks for any class that has an identical name to its superclass, other than the package. This can be very confusing.
+
Also see FindBugs NM_SAME_SIMPLE_NAME_AS_SUPERCLASS rule.
+
Example of violations:
+
+ class MyClass extends other.MyClass // violation
+
+]]>
+ bug
+
+
+
+
+ org.codenarc.rule.naming.InterfaceNameSameAsSuperInterfaceRule
+ MINOR
+
+
+ Checks for any interface that has an identical name to its super-interface, other than the package. This can be very confusing.
+
]]>bug
@@ -5985,25 +5720,87 @@ for (int i = 0; i < 100; ++i) {
- org.codenarc.rule.security.PublicFinalizeMethodRule
- MINOR
-
-
- Creates a violation when the program violates secure coding principles by declaring a finalize() method public.
-
A program should never call finalize explicitly, except to call super.finalize() inside an implementation of finalize(). In mobile code situations, the otherwise error prone practice of manual garbage collection can become a security threat if an attacker can maliciously invoke one of your finalize() methods because it is declared with public access. If you are using finalize() as it was designed, there is no reason to declare finalize() with anything other than protected access.
-
References:
-]]>
- bug
-
-
-
-
- org.codenarc.rule.security.NonFinalPublicFieldRule
+ org.codenarc.rule.security.PublicFinalizeMethodRule
+ MINOR
+
+
+ Creates a violation when the program violates secure coding principles by declaring a finalize() method public.
+
A program should never call finalize explicitly, except to call super.finalize() inside an implementation of finalize(). In mobile code situations, the otherwise error prone practice of manual garbage collection can become a security threat if an attacker can maliciously invoke one of your finalize() methods because it is declared with public access. If you are using finalize() as it was designed, there is no reason to declare finalize() with anything other than protected access.
+
References:
+]]>
+ bug
+
+
+
+
+ org.codenarc.rule.security.NonFinalPublicFieldRule
+ MINOR
+
+
+ Finds code that violates secure coding principles for mobile code by declaring a member variable public but not final.
+
All public member variables in an Applet and in classes used by an Applet should be declared final to prevent an attacker from manipulating or gaining unauthorized access to the internal state of the Applet.
+
References:
+]]>
+ bug
+
+
+
+
+ org.codenarc.rule.security.UnsafeImplementationAsMapRule
+ MINOR
+
+
+ Reports incomplete interface implementations created by map-to-interface coercions.
+
By default, this rule does not apply to test files.
+
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
+
Example of violations:
+
+ [mouseClicked: { ... }] as MouseListener
+ //not all MouseListener methods are implemented which can lead to UnsupportedOperationException-s
+
+]]>
+ bug
+
+
+
+
+
+
+ org.codenarc.rule.serialization.SerialVersionUIDRule
+ MINOR
+
+
+ A serialVersionUID is normally intended to be used with Serialization. It needs to be of type long, static, and final. Also, it should be declared private. Providing no modifier creates a and Groovy generates a , which is probably not intended.
+
From API javadoc for java.io.Serializable:
+ ]]>
+ bug
+
+
+
+
+ org.codenarc.rule.serialization.SerializableClassMustDefineSerialVersionUIDRule
+ MINOR
+
+
+ Classes that implement Serializable should define a serialVersionUID. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If you don't define serialVersionUID, the system will make one by hashing most of your class's features. Then if you change anything, the UID will change and Java won't let you reload old data.
+
+]]>
+ bug
+
+
+
+
+ org.codenarc.rule.serialization.SerialPersistentFieldsRuleMINOR
-
-
- Finds code that violates secure coding principles for mobile code by declaring a member variable public but not final.
-
All public member variables in an Applet and in classes used by an Applet should be declared final to prevent an attacker from manipulating or gaining unauthorized access to the internal state of the Applet.
+
+
+ To use a Serializable object's serialPersistentFields correctly, it must be declared private, static, and final.
+
The Java Object Serialization Specification allows developers to manually define Serializable fields for a class by specifying them in the serialPersistentFields array. This feature will only work if serialPersistentFields is declared as private, static, and final. Also, specific to Groovy, the field must be of type ObjectStreamField[], and cannot be Object.
References:
]]>bug
@@ -6011,1292 +5808,1495 @@ for (int i = 0; i < 100; ++i) {
- org.codenarc.rule.security.UnsafeImplementationAsMapRule
+ org.codenarc.rule.serialization.EnumCustomSerializationIgnoredRuleMINOR
-
-
- Reports incomplete interface implementations created by map-to-interface coercions.
-
By default, this rule does not apply to test files.
-
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
+
+
+ Checks for enums that define writeObject() or writeReplace() methods, or declare serialPersistentFields or serialVersionUID fields, all of which are ignored for enums.
+
From the javadoc for ObjectOutputStream:
+
Example of violations:
- [mouseClicked: { ... }] as MouseListener
- //not all MouseListener methods are implemented which can lead to UnsupportedOperationException-s
+ enum MyEnum {
+ ONE, TWO, THREE
+ private static final long serialVersionUID = 1234567L // violation
+ private static final ObjectStreamField[] serialPersistentFields = // violation
+ { new ObjectStreamField("name", String.class) }
+ String name;
+
+ Object writeReplace() throws ObjectStreamException { .. } // violation
+ private void writeObject(ObjectOutputStream stream) { .. } // violation
+ }
]]>bug
-
+
-
- org.codenarc.rule.formatting.BracesForClassRule
- MINOR
-
-
- Checks the location of the opening brace (\{) for classes. By default, requires them on the same line, but the sameLine property can be set to false to override this.
-
NOTE: This rule ignores annotation types, e.g. @interface MyAnnotation {}.
+ org.codenarc.rule.size.ClassSizeRule
+ MAJOR
+
+
+ Checks if the size of a class exceeds the number of lines specified by the maxLines property.
]]>
- convention
+ bug
- sameLine
- true
+ maxLines
+
+ 1000
-
- org.codenarc.rule.formatting.LineLengthRule
+ org.codenarc.rule.size.CyclomaticComplexityRule.fixedMINOR
-
-
- Checks the maximum length for each line of source code. It checks for number of characters, so lines that include tabs may appear longer than the allowed number when viewing the file. The maximum line length can be configured by setting the length property, which defaults to 120.
-
NOTE: This rule does not support the @SuppressAnnotations annotation or the classname-based rule properties (applyToClassNames, doNotApplyToClassNames) to enable/disable the rule. If you want to specify or restrict where this rule is applied, you must use the file-based rule properties: applyToFileNames, doNotApplyToFileNames, applyToFilesMatching and doNotApplyToFilesMatching.
- ]]>
- convention
+
+
+ Calculates the for methods/classes and checks against configured threshold values.
+
The maxMethodComplexity property holds the threshold value for the cyclomatic complexity value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
+
The maxClassAverageMethodComplexity property holds the threshold value for the average cyclomatic complexity value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
+
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
+ The value is calculated as follows:
+
+]]>
+ bug
- ignoreImportStatements
-
- true
+ ignoreMethodNames
+
- ignoreLineRegex
-
+ maxClassAverageMethodComplexity
+ value allowed for a class, calculated as the average complexity of its methods or "closure fields". If zero or , then do not check average class-level complexity. ]]>
+ 20
- ignorePackageStatements
-
- true
+ maxClassComplexity
+ value allowed for a class, calculated as the total complexity of its methods or "closure fields". If zero or , then do not check total class-level complexity. ]]>
+ 0
- length
-
- 120
+ maxMethodComplexity
+ value allowed for a single method (or "closure field"). If zero or , then do not check method-level complexity. ]]>
+ 20
-
- org.codenarc.rule.formatting.BracesForForLoopRule
+ org.codenarc.rule.size.MethodCountRuleMINOR
-
-
- Checks the location of the opening brace (\{) for for loops. By default, requires them on the same line, but the sameLine property can be set to false to override this.
+
+
+ Checks if the number of methods within a class exceeds the number of lines specified by the maxMethod property.
+
A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects.
]]>
- convention
+ bug
- sameLine
- true
+ maxMethods
+
+ 30
-
- org.codenarc.rule.formatting.BracesForIfElseRule
- MINOR
-
-
- Checks the location of the opening brace (\{) for if statements. By default, requires them on the same line, but the sameLine property can be set to false to override this.
+ org.codenarc.rule.size.MethodSizeRule.fixed
+ MAJOR
+
+
+ Checks if the size of a method exceeds the number of lines specified by the maxLines property.
+
Known Limitations:
]]>
- convention
-
- elseOnSameLineAsClosingBrace
-
- true
-
-
- elseOnSameLineAsOpeningBrace
-
- true
-
+ bug
- sameLine
-
- true
+ ignoreMethodNames
+
- validateElse
-
- false
+ maxLines
+
+ 100
-
- org.codenarc.rule.formatting.BracesForMethodRule
+ org.codenarc.rule.size.NestedBlockDepthRuleMINOR
-
-
- Checks the location of the opening brace (\{) for constructors and methods. By default, requires them on the same line, but the sameLine property can be set to false to override this.
- ]]>
- convention
+
+
+ Checks for blocks or closures nested more deeply than a configured maximum number. Blocks include if, for, while, switch, try, catch, finally and synchronized blocks/statements, as well as closures.
+
Methods calls, constructor calls, and property access through Builder objects are ignore. For instance, this code does not cause a violation:
+]]>
+ bug
- sameLine
- true
+ ignoreRegex
+
+ .*(b|B)uilder
-
-
-
-
- org.codenarc.rule.formatting.BracesForTryCatchFinallyRule
- MINOR
-
-
- Checks the location of the opening brace (\{) for try statements. By default, requires them on the line, but the sameLine property can be set to false to override this.
- ]]>
- convention
- sameLine
- true
+ maxNestedBlockDepth
+
+ 5
-
+
- org.codenarc.rule.formatting.ClassJavadocRule
+ org.codenarc.rule.size.CrapMetricRule.fixedMINOR
-
-
- Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.
- ]]>
- convention
-
-
-
-
- org.codenarc.rule.formatting.SpaceAfterCommaRule
- MAJOR
-
-
- Checks that there is at least one space or whitespace following each comma. That includes checks for method and closure declaration parameter lists, method call parameter lists, Map literals and List literals.
-
Known limitations:
+
+
+ Calculates the C.R.A.P. (Change Risk Anti-Patterns) metric score for methods/classes and checks against configured threshold values.
+
The metric score is based on the and test coverage for individual methods. A method with a value greater than the maxMethodCrapScore property causes a violation. Likewise, a class that has an (average method) value greater than the maxClassAverageMethodCrapScore property causes a violation.
+
NOTE: This rule requires the GMetrics[3] jar, version 0.5 (or later), on the classpath, as well as a Cobertura[4]-[6] XML coverage file. If either of these prerequisites is not available, this rule logs a warning messages and exits (i.e., does nothing).
+
The maxMethodCrapScore property holds the threshold value for the CRAP value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
+
The maxClassAverageMethodCrapScore property holds the threshold value for the average CRAP value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
+
NOTE: This rule does NOT treat as methods (unlike some of the other size/complexity rules).
]]>
- convention
+ bug
+
+ coberturaXmlFile
+
+
+
+ ignoreMethodNames
+
+
+
+ maxClassAverageMethodCrapScore
+ average metric value allowed for a class, calculated as the average CRAP value of its methods. If zero or , then do not check the average class-level CRAP value. ]]>
+ 30
+
+
+ maxClassCrapScore
+ metric value allowed for a class, calculated as the total CRAP value of its methods. If zero or , then do not check class-level CRAP value. ]]>
+ 0
+
+
+ maxMethodCrapScore
+ metric value allowed for a single method. If zero or , then do not check method-level complexity. ]]>
+ 30
+
- org.codenarc.rule.formatting.SpaceAfterSemicolonRule
- MAJOR
-
-
- Check that there is at least one space (blank) or whitespace following a semicolon that separates:
+ org.codenarc.rule.size.AbcMetricRule.fixed
+ MINOR
+
+
+ Calculates the size metric for methods/classes and checks against configured threshold values.
+
The maxMethodAbcScore property holds the threshold value for the ABC score for each method. If this value is non-zero, a method with an ABC score greater than this value is considered a violation. The value does not have to be an integer (e.g., 1.7 is allowed).
+
The maxClassAverageMethodAbcScore property holds the threshold value for the average ABC score for each class. If this value is non-zero, a class with an average ABC score value greater than this value is considered a violation. The value does not have to be an integer.
+
The maxClassAbcScore property holds the threshold value for the total ABC score value for each class. If this value is non-zero, a class with a total ABC score greater than this value is considered a violation. The value does not have to be an integer.
+
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
+ The score is calculated as follows: The metric measures size by counting the number of Assignments (A), Branches (B) and Conditions (C) and assigns a single numerical score calculated as:
+
|ABC| = sqrt((A*A)+(B*B)+(C*C))
+
The calculation rules for Groovy:
]]>
- convention
+ bug
+
+ ignoreMethodNames
+
+
+
+ maxClassAbcScore
+ score allowed for a class, calculated as the total ABC score of its methods or "closure fields". If zero or , then do not check class-level scores. ]]>
+ 0
+
+
+ maxClassAverageMethodAbcScore
+ score allowed for a class, calculated as the average score of its methods or "closure fields". If zero or , then do not check class-level average scores. ]]>
+ 60
+
+
+ maxMethodAbcScore
+ score allowed for a single method (or "closure field"). If zero or , then do not check method-level scores. ]]>
+ 60
+
-
+
- org.codenarc.rule.formatting.SpaceAroundOperatorRule
- MAJOR
-
-
- Check that there is at least one space (blank) or whitespace around each binary operator, including: +, -, *, /, \>\>, \<\<, &&, ||, &, |, ?:, =, "as".
-
Do not check dot ('.') operator. Do not check unary operators (!, +, -, ++, --, ?.). Do not check array ('[') operator.
-
Known limitations:
-]]>
- convention
-
+ org.codenarc.rule.size.ParameterCountRule
+ MINOR
+
+
+ Checks if the number of parameters in method/constructor exceeds the number of parameters specified by the maxParameters property.
+
Example of violations:
+
+ void someMethod(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6) { // violation
+ }
-
-
- org.codenarc.rule.formatting.SpaceBeforeOpeningBraceRule
- MAJOR
-
-
- Check that there is at least one space (blank) or whitespace before each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
-
Known limitations:
+ class SampleClass {
+ SampleClass(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) { // violation
+ }
+ }
+
]]>
- convention
+ bug
- checkClosureMapEntryValue
-
- true
+ maxParameters
+
+ 5
-
+
+
- org.codenarc.rule.formatting.SpaceAfterOpeningBraceRule
+ org.codenarc.rule.unnecessary.UnnecessaryBooleanExpressionRuleMAJOR
-
-
- Check that there is at least one space (blank) or whitespace after each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
- Examples of violations:
+
+
+ Checks for unnecessary boolean expressions, including ANDing (&&) or ORing (||) with true, false, null, or a Map/List/String/Number literal.
+
This rule also checks for negation (!) of true, false, null, or a Map/List/String/Number literal.
+
Examples of violations include:
- class MyClass{int count } // violation
+ result = value && true // AND or OR with boolean constants
+ if (false || value) { .. }
+ return value && Boolean.FALSE
- interface MyInterface {static final OK = 1 }// violation
+ result = null && value // AND or OR with null
- enum MyEnum {OK, BAD } // violation
+ result = value && "abc" // AND or OR with String literal
- def myMethod() {int count } // violation
+ result = value && 123 // AND or OR with Number literal
+ result = 678.123 || true
- if (ready) {println 9 } // violation
+ result = value && [x, y] // AND or OR with List literal
- if (ready) {
- } else {println 99} // violation
+ result = [a:123] && value // AND or OR with Map literal
- for (int i=0; i<10; i++) {println i } // violation
+ result = !true // Negation of boolean constants
+ result = !false
+ result = !Boolean.TRUE
- for (String name in names) {println name } // violation
+ result = !null // Negation of null
- for (String name: names) {println name } // violation
+ result = !"abc" // Negation of String literal
- while (ready) {println time } // violation
+ result = ![a:123] // Negation of Map literal
- try {doStuff() // violation
- } catch(Exception e) {x=77 } // violation
- } finally {println 'error' } // violation
+ result = ![a,b] // Negation of List literal
+
+]]>
+ clumsy
+
- list.each {name -> } // violation
+
+ org.codenarc.rule.unnecessary.UnnecessaryIfStatementRule
+ MAJOR
+
+
+ Checks for unnecessary if statements. The entire if statement, or at least the or block, are considered unnecessary for the four scenarios described below.
+
(1) When the and blocks contain only an explicit return of true and false constants. These cases can be replaced by a simple statement. Examples of violations include:
+
+ if (someExpression) // can be replaced by: return someExpression
+ return true
+ else
+ return false
- shouldFail(Exception) {doStuff() } // violation
+ if (someExpression) { // can be replaced by: return !someExpression
+ return false
+ } else {
+ return true
+ }
+
+ if (someExpression) { // can be replaced by: return someExpression
+ return Boolean.TRUE
+ } else {
+ return Boolean.FALSE
+ }
+
]]>
- convention
-
- checkClosureMapEntryValue
-
- true
-
-
- ignoreEmptyBlock
-
- false
-
+ clumsy
-
- org.codenarc.rule.formatting.SpaceAfterClosingBraceRule
+ org.codenarc.rule.unnecessary.UnnecessaryTernaryExpressionRuleMAJOR
-
-
- Check that there is at least one space (blank) or whitespace after each closing brace ("\{") for method/class/interface declarations, closure expressions and block statements.
-
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
- Known limitations:
+
+
+ Checks for ternary expressions where the conditional expression always evaluates to a boolean and the and expressions are merely returning true and false constants. These cases can be replaced by a simple boolean expression. Examples of violations include:
+
+ x==99 ? true : false // can be replaced by: x==99
+ x && y ? true : false // can be replaced by: x && y
+ x||y ? false : true // can be replaced by: !(x||y)
+ x >= 1 ? true: false // can be replaced by: x >= 1
+ x < 99 ? Boolean.TRUE : Boolean.FALSE // can be replaced by: x < 99
+ !x ? true : false // can be replaced by: !x
+
+
+ x ? '123' : '123' // can be replaced by: '123'
+ x ? null : null // can be replaced by: null
+ x ? 23 : 23 // can be replaced by: 23
+ x ? MAX_VALUE : MAX_VALUE // can be replaced by: MAX_VALUE
+ ready ? minValue : minValue // can be replaced by: minValue
+
]]>
- convention
-
- checkClosureMapEntryValue
-
- true
-
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceBeforeClosingBraceRule
+ org.codenarc.rule.unnecessary.UnnecessaryBigDecimalInstantiationRuleMAJOR
-
-
- Check that there is at least one space (blank) or whitespace before each closing brace ("\}") for method/class/interface declarations, closure expressions and block statements.
-
Known limitations:
-]]>
- convention
-
- checkClosureMapEntryValue
-
- true
-
-
- ignoreEmptyBlock
-
- false
-
+
+
+ It is unnecessary to instantiate BigDecimal objects. Instead just use the decimal literal or the 'G' identifier to force the type, such as 123.45 or 123.45G.
+
This rule does not produce violations when the parameter evaluates to an integer/long, e.g. new BigDecimal(42), new BigDecimal(42L) or new BigDecimal("42"), because using the "G" suffix on an integer value produces a BigInteger, rather than a BigDecimal, e.g. 45G. So that means there is no way to produce a BigDecimal with exactly that value using a literal.
+
This rule also does not produce violations when the parameter is a double, e.g. new BigDecimal(12.3). That scenario is covered by the BigDecimalInstantiation rule, because that produces an unpredictable (double) value (and so it is , rather than ).
+ ]]>
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAfterIfRule
+ org.codenarc.rule.unnecessary.UnnecessaryBigIntegerInstantiationRuleMAJOR
-
-
- Check that there is exactly one space (blank) after the if keyword and before the opening parenthesis.
-
-]]>
- convention
+
+
+ It is unnecessary to instantiate BigInteger objects. Instead just use the literal with the 'G' identifier to force the type, such as 8G or 42G.
+ ]]>
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAfterWhileRule
+ org.codenarc.rule.unnecessary.UnnecessaryBooleanInstantiationRuleMAJOR
-
-
- Check that there is exactly one space (blank) after the while keyword and before the opening parenthesis.
-
Examples of violations:
+
+
+ Checks for direct call to a Boolean constructor. Use Boolean.valueOf() or the Boolean.TRUE and Boolean.FALSE constants instead of calling the Boolean() constructor directly.
+
Also checks for Boolean.valueOf(true) or Boolean.valueOf(false). Use the Boolean.TRUE or Boolean.FALSE constants instead.
+
Here is an example of code that produces a violation:
]]>
- convention
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAfterForRule
+ org.codenarc.rule.unnecessary.UnnecessaryCallForLastElementRuleMAJOR
-
-
- Check that there is exactly one space (blank) after the for keyword and before the opening parenthesis.
-
Examples of violations:
+
+
+ This rule checks for excessively verbose methods of accessing the last element of an array or list. For instance, it is possible to access the last element of an array by performing array[array.length - 1], in Groovy it is simpler to either call array.last() or array[-1]. The same is true for lists. This violation is triggered whenever a get, getAt, or array-style access is used with an object size check.
+
Code like this all cause violations.
- for(name in names) { } // violation
- for (int i=0; i < 10; i++) { } // violation
+ def x = [0, 1, 2]
+ def a = x.get(x.size() -1)
+ def b = x.get(x.length -1)
+ def c = x.getAt(x.size() -1)
+ def d = x.getAt(x.length -1)
+ def f = x[(x.size() -1]
+ def d = x[(x.length -1]
+
+
+ def x = [0, 1, 2]
+ def a = x.last()
+ def b = x[-1]
+ def c = x.getAt(-1)
+ def d = x.get(z.size() -1) // different objects
+ def e = x.get(z.length -1) // different objects
+ def f = x.getAt(z.size() -1) // different objects
]]>
- convention
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAfterSwitchRule
+ org.codenarc.rule.unnecessary.UnnecessaryCatchBlockRuleMAJOR
-
-
- Check that there is exactly one space (blank) after the switch keyword and before the opening parenthesis.
-
-]]>
- convention
+
+
+ Violations are triggered when a block does nothing but throw the original exception. In this scenario there is usually no need for a block, just let the exception be thrown from the original code. This condition frequently occurs when catching an exception for debugging purposes but then forgetting to take the catch statement out.
+ ]]>
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAfterCatchRule
+ org.codenarc.rule.unnecessary.UnnecessaryCollectCallRuleMAJOR
-
-
- Check that there is exactly one space (blank) after the catch keyword and before the opening parenthesis.
-
Examples of violations:
+
+
+ Some method calls to Object.collect(Closure) can be replaced with the spread operator. For instance, list.collect { it.multiply(2) } can be replaced by list*.multiply(2).
+
+ [1, 2, 3].collect { it * it } // OK, closure parameter is referenced twice
+
+ [1, 2, 3].mapMethod { it.multiply(5) } // OK, method call is not collect
+
+ [1, 2, 3].collect(5) // OK, collect parameter is not a closure
+
+ // OK, the closure is not a simple one line statement
+ [1, 2, 3].collect { println it; it.multiply(5) }
+
+ // OK, closure has too many arguments
+ [1, 2, 3].collect { a, b -> a.multiply(b) }
+
+ // OK, closure statement references parameter multiple times
+ [1, 2, 3].collect { it.multiply(it) }
+
+ // OK, it is referenced several times in the closure
+ [1, 2, 3].collect { it.multiply(2).multiply(it) }
+ ["1", "2", "3"].collect { it.bytes.foo(it) }
+
+ // OK, chained methods are too complex to analyze at this point
+ [1, 2, 3].collect { it.multiply(2).multiply(4) }
+
+ // in general the above examples can be rewritten like this:
+ [1, 2, 3]*.multiply(2)
+ ["1", "2", "3"]*.bytes
]]>
- convention
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAroundClosureArrowRule
+ org.codenarc.rule.unnecessary.UnnecessaryCollectionCallRuleMAJOR
-
-
- Checks that there is at least one space (blank) or whitespace around each closure arrow (->) symbol.
-
Known limitations:
-]]>
- convention
+
+
+ Checks for useless calls to collections. For any collection c, calling c.containsAll(c) should always be true, and c.retainAll(c) should have no effect.
+ ]]>
+ clumsy
-
+
- org.codenarc.rule.formatting.SpaceAroundMapEntryColonRule
+ org.codenarc.rule.unnecessary.UnnecessaryConstructorRuleMAJOR
-
-
- Check for proper formatting of whitespace around colons for literal Map entries. By default, no whitespace is allowed either before or after the Map entry colon, but you can change that through the configuration properties below.
+
+
+ This rule detects when a constructor is not necessary; i.e., when there's only one constructor, it's public, has an empty body, and takes no arguments, or else contains only a single call to super().
Example of violations:
- Map m1 = [myKey : 12345] // violation (both before and after the colon)
- println [a :[1:11, 2:22], // violation on a (before colon)
- b:[(Integer): 33]] // violation on Integer (after colon)
+ class MyClass {
+ public MyClass() { // violation; constructor is not necessary
+ }
+ }
+
+ class MyClass2 extends OtherClass {
+ MyClass2() { // violation; constructor is not necessary
+ super()
+ }
+ }
]]>
- convention
-
- characterAfterColonRegex
- entry. For example, /\\S/ matches any non-whitespace character and /\\s/ matches any whitespace character (thus requiring a space or whitespace). ]]>
- \\S
-
-
- characterBeforeColonRegex
- entry. For example, /\\S/ matches any non-whitespace character and /\\s/ matches any whitespace character (thus requiring a space or whitespace). ]]>
- \\S
-
+ clumsy
-
+
- org.codenarc.rule.formatting.ClosureStatementOnOpeningLineOfMultipleLineClosureRule
+ org.codenarc.rule.unnecessary.UnnecessaryDoubleInstantiationRuleMAJOR
-
-
- Checks for closure logic on first line (after -\) for a multi-line closure. That breaks the symmetry of indentation (if the subsequent statements are indented normally), and that first statement can be easily missed when reading the code.
-
Example of violations:
+
+
+ It is unnecessary to instantiate Double objects. Instead just use the double literal with 'D' identifier to force the type, such as 123.45d or 0.42d.
+ ]]>
+ clumsy
+
+
+
+
+ org.codenarc.rule.unnecessary.UnnecessaryFloatInstantiationRule
+ MAJOR
+
+
+ It is unnecessary to instantiate Float objects. Instead just use the float literal with the 'F' identifier to force the type, such as 123.45F or 0.42f.
+ ]]>
+ clumsy
+
+
+
+
+ org.codenarc.rule.unnecessary.UnnecessaryGetterRule
+ MAJOR
+
+
+ Checks for explicit calls to getter/accessor methods which can, for the most part, be replaced by property access. A getter is defined as a method call that matches get[A-Z] but not getClass() or get[A-Z][A-Z] such as getURL(). Getters do not take method arguments.
+
]]>
- convention
+ clumsy
-
+
- org.codenarc.rule.formatting.ConsecutiveBlankLinesRule
+ org.codenarc.rule.unnecessary.UnnecessaryGStringRuleMAJOR
-
-
- Makes sure there are no consecutive lines that are either blank or whitespace only. This reduces the need to scroll further than necessary when reading code, and increases the likelihood that a logical block of code will fit on one screen for easier comprehension.
-
Example of violation:
+
+
+ String objects should be created with single quotes, and GString objects created with double quotes. Creating normal String objects with double quotes is confusing to readers.
+
Example of violations:
- def name
+ def a = "I am a string" // violation
+ // violation
+ def b = """
+ I am a string
+ """
- def value
+ def c = "I am a ' string" // OK
+ def d = """I am a ' string""" // OK
+ def e = """I am a ' string""" // OK
- def id
-
-]]>
- convention
-
+ def f = "I am a \$ string" // OK
-
-
- org.codenarc.rule.formatting.BlankLineBeforePackageRule
- MAJOR
-
-
- Makes sure there are no blank lines before the package declaration of a source code file.
- ]]>
- convention
-
+ // OK
+ def g = """
+ I am a \$ string
+ """
-
-
- org.codenarc.rule.formatting.FileEndsWithoutNewlineRule
- MAJOR
-
-
- Makes sure each source file ends with a newline character.
- ]]>
- convention
-
+ // OK
+ def h = """
+ I am a $string
+ """
-
-
- org.codenarc.rule.formatting.MissingBlankLineAfterImportsRule
- MAJOR
-
-
- Makes sure there is a blank line after the imports of a source code file.
-
Example of violation:
-
- import org.apache.commons.lang.StringUtils
- class MyClass { } // violation
+ def i = 'i am a string'
+ def j = '''i am a
+ string
+ '''
]]>
- convention
+ clumsy
-
+
- org.codenarc.rule.formatting.MissingBlankLineAfterPackageRule
+ org.codenarc.rule.unnecessary.UnnecessaryInstantiationToGetClassRuleMAJOR
-
-
- Makes sure there is a blank line after the package statement of a source code file.
-
Example of violation:
+
+
+ Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
- package org.codenarc
- import java.util.Date // violation
+ public class Foo {
+ // Replace this
+ Class c = new String().getClass();
- class MyClass {
- void go() { /* ... */ }
- }
+ // with this:
+ Class c = String.class;
+ }
]]>
- convention
+ clumsy
-
+
- org.codenarc.rule.formatting.TrailingWhitespaceRule
+ org.codenarc.rule.unnecessary.UnnecessaryIntegerInstantiationRuleMAJOR
-
-
- Checks that no lines of source code end with whitespace characters.
-]]>
- convention
+
+
+ It is unnecessary to instantiate Integer objects. Instead just use the literal with the 'I' identifier to force the type, such as 8I or 42i.
+ ]]>
+ clumsy
-
-
-
+
- org.codenarc.rule.convention.InvertedIfElseRule
+ org.codenarc.rule.unnecessary.UnnecessaryLongInstantiationRuleMAJOR
-
-
- An inverted statement is one in which there is a single if statement with a single else branch and the boolean test of the if is negated. For instance if (!x) false else true. It is usually clearer to write this as if (x) true else false.
+
+
+ It is unnecessary to instantiate Long objects. Instead just use the literal with the 'L' identifier to force the type, such as 8L or 42L.
]]>
- bug
+ clumsy
- org.codenarc.rule.convention.ConfusingTernaryRule
+ org.codenarc.rule.unnecessary.UnnecessaryObjectReferencesRuleMAJOR
-
-
- In a ternary expression avoid negation in the test. For example, rephrase: (x != y) ? diff : same as: (x == y) ? same : diff. Consistent use of this rule makes the code easier to read. Also, this resolves trivial ordering problems, such as "does the error case go first?" or "does the common case go first?".
-
Example:
+
+
+ Violations are triggered when an excessive set of consecutive statements all reference the same variable. This can be made more readable by using a with or identity block. By default, 5 references are allowed. You can override this property using the maxReferencesAllowed property on the rule.
+
These two bits of code produce violations:
- (x != y) ? diff : same // triggers violation
- (!x) ? diff : same // triggers violation
-
- (x == y) ? same : diff // OK
- (x) ? same : diff // OK
-
- // this is OK, because of GroovyTruth there is no inverse of != null
- (x != null) ? diff : same
+ def p1 = new Person()
+ p1.firstName = 'Hamlet'
+ p1.lastName = "D'Arcy"
+ p1.employer = 'Canoo'
+ p1.street = 'Kirschgaraten 5'
+ p1.city = 'Basel'
+ p1.zipCode = '4051'
- // this is OK, because of GroovyTruth there is no inverse of != true
- (x != true) ? diff : same
+ def p2 = new Person()
+ p2.setFirstName('Hamlet')
+ p2.setLastName("D'Arcy")
+ p2.setEmployer('Canoo')
+ p2.setStreet('Kirschgaraten 5')
+ p2.setCity('Basel')
+ p2.setZipCode('4051')
+
+
+ def p1 = new Person().with {
+ firstName = 'Hamlet'
+ lastName = "D'Arcy"
+ employer = 'Canoo'
+ street = 'Kirschgaraten 5'
+ city = 'Basel'
+ zipCode = '4051'
+ }
- // this is OK, because of GroovyTruth there is no inverse of != false
- (x != false) ? diff : same
+ def p2 = new Person().identity {
+ firstName = 'Hamlet'
+ lastName = "D'Arcy"
+ employer = 'Canoo'
+ street = 'Kirschgaraten 5'
+ city = 'Basel'
+ zipCode = '4051'
+ }
]]>
- bug
+ clumsy
-
+
- org.codenarc.rule.convention.CouldBeElvisRule
+ org.codenarc.rule.unnecessary.UnnecessaryNullCheckRuleMAJOR
-
-
- Catch an if block that could be written as an elvis expression.
-
Example of violations:
+
+
+ Groovy contains the safe dereference operator. It can be used in boolean conditional statements to safely replace explicit x == null tests. Also, testing the 'this' or 'super' reference for null equality is pointless and can be removed.
+
Examples of violations:
- if (!x) { // violation
- x = 'some value'
- }
+ if (obj != null && obj.method()) { }
- if (!x) // violation
- x = "some value"
+ if (obj != null && obj.prop) { }
- if (!params.max) { // violation
- params.max = 10
- }
+ // this is pointless and won't avoid NullPointerException
+ if (obj.method() && obj != null ) { }
- x ?: 'some value' // OK
-
-]]>
- bug
-
+ if (this == null) { }
+ if (null == this) { }
+ if (this != null) { }
+ if (null != this) { }
-
-
- org.codenarc.rule.convention.LongLiteralWithLowerCaseLRule
- MINOR
-
-
- In Java and Groovy, you can specify long literals with the L or l character, for instance 55L or 24l. It is best practice to always use an uppercase L and never a lowercase l. This is because 11l rendered in some fonts may look like 111 instead of 11L.
-
Example of violations:
+ if (super == null) { }
+ if (null == super) { }
+ if (super != null) { }
+ if (null != super) { }
+
- def x = 1l
- def y = 55l
+ // null check it OK
+ if (obj != null) { }
+
+ // null safe dereference in if is OK
+ if (obj?.method()) { }
+
+ // null safe dereference in ternary is OK
+ (obj?.prop && obj?.prop2) ? x : y
+
+ // obj is reused in a parameter list, so OK
+ if (obj != null && obj.method() && isValid(obj)) { }
+
+ // rule is not so complex yet...
+ (obj != null && obj.prop && obj.method()) ? x : y
]]>
- bug
+ clumsy
-
+
- org.codenarc.rule.convention.ParameterReassignmentRule
+ org.codenarc.rule.unnecessary.UnnecessaryNullCheckBeforeInstanceOfRuleMAJOR
-
-
- Checks for a method or closure parameter being reassigned to a new value within the body of the method/closure, which is a confusing and questionable practice. Use a temporary variable instead.
-
Example of violations:
+
+
+ There is no need to check for null before an instanceof; the instanceof keyword returns false when given a null argument.
+
Example:
- void myMethod(int a, String b) {
- println a
- b = 'new value' // violation
+ if (x != null && x instanceof MyClass) {
+ // should drop the "x != null" check
+ }
+
+ if (x instanceof MyClass && x != null) {
+ // should drop the "x != null" check
}
- def myClosure1 = { int a, b ->
- a = 123 // violation
+ // should drop the "x != null" check
+ (x != null && x instanceof MyClass) ? foo : bar
+
+ if (x != null && x instanceof MyClass && x.isValid()) {
+ // this is OK and causes no violation because the x.isValid() requires a non null reference
}
]]>
- bug
+ clumsy
-
+
- org.codenarc.rule.convention.TernaryCouldBeElvisRule
+ org.codenarc.rule.unnecessary.UnnecessaryOverridingMethodRuleMAJOR
-
-
- Checks for ternary expressions where the and expressions are the same. These can be simplified to an expression.
-
Example of violations:
-
- x ? x : false // violation; can simplify to x ?: false
-
- foo() ? foo() : bar() // violation; can simplify to foo() ?: bar()
- foo(1) ? foo(1) : 123 // violation; can simplify to foo(1) ?: 123
+
+
+ Checks for an overriding method that merely calls the same method defined in a superclass. Remove it.
+ ]]>
+ clumsy
+
- (x == y) ? same : diff // OK
- x ? y : z // OK
- x ? x + 1 : x + 2 // OK
- x ? 1 : 0 // OK
- x ? !x : x // OK
- !x ? x : null // OK
+
+
+ org.codenarc.rule.unnecessary.UnnecessaryReturnKeywordRule
+ MAJOR
+
+
+ In Groovy, the return keyword is often optional. If a statement is the last line in a method or closure then you do not need to have the return keyword.
+ ]]>
+ clumsy
+
- foo() ? bar() : 123 // OK
- foo() ? foo(99) : 123 // OK
- foo(x) ? foo() : 123 // OK
- foo(1) ? foo(2) : 123 // OK
+
+
+ org.codenarc.rule.unnecessary.UnnecessaryStringInstantiationRule
+ MAJOR
+
+
+ Checks for direct call to the String constructor that accepts a String literal. In almost all cases, this is unnecessary. Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.
+
Here is an example of code that produces a violation:
+
+ def s = new String('abc')
]]>
- bug
+ clumsy
-
+
- org.codenarc.rule.convention.VectorIsObsoleteRule
+ org.codenarc.rule.unnecessary.AddEmptyStringRuleMINOR
-
-
- Checks for references to the () obsolete java.util.Vector class. Use the Java Collections Framework classes instead, including ArrayList or Collections.synchronizedList(). See the JDK javadoc.
-
Example of violations:
+
+
+ Finds empty string literals which are being added. This is an inefficient way to convert any type to a String.
+
Examples:
- def myList = new Vector() // violation
+ // do not add empty strings to things
+ def a = '' + 123
+ def b = method('' + property)
+
+ // these examples are OK and do not trigger violations
+ def c = 456.toString()
+ def d = property?.toString() ?: ""
]]>
- bug
+ clumsy
-
+
- org.codenarc.rule.convention.HashtableIsObsoleteRule
+ org.codenarc.rule.unnecessary.ConsecutiveLiteralAppendsRuleMINOR
-
-
- Checks for references to the () obsolete java.util.Hashtable class. Use the Java Collections Framework classes instead, including HashMap or ConcurrentHashMap. See the JDK javadoc.
+
+
+ Violations occur when method calls to append(Object) are chained together with literals as parameters. The chained calls can be joined into one invocation.
Example of violations:
- def myMap = new Hashtable() // violation
+ writer.append('foo').append('bar') // strings can be joined
+ writer.append('foo').append(5) // string and number can be joined
+ writer.append('Hello').append("$World") // GString can be joined
-]]>
- bug
-
+
+ // usage not chained invocation
+ writer.append('Hello')
+ writer.append('World')
-
-
- org.codenarc.rule.convention.IfStatementCouldBeTernaryRule
- MINOR
-
-
- Checks for:
+ writer.append(null).append(5) // nulls cannot be joined
+
+ writer.append().append('Hello') // no arg append is unknown
+ writer.append('a', 'b').append('Hello') // two arg append is unknown
+
]]>
- bug
+ clumsy
-
+
- org.codenarc.rule.convention.NoDefRule
+ org.codenarc.rule.unnecessary.ConsecutiveStringConcatenationRuleMAJOR
-
-
- Do not allow using the def keyword in code. Use a specific type instead.
-
NOTE: This rule applies to the text contents of a rather than a specific , so it does not support the and configuration properties.
+
+
+ Catches concatenation of two string literals on the same line. These can safely by joined. In Java, the Java compiler will join two String literals together and place them in the Constant Pool. However, Groovy will not because the plus() method may override the + operator.
+
Examples:
+
+ // Violations
+ def a = 'Hello' + 'World' // should be 'HelloWorld'
+ def b = "$Hello" + 'World' // should be "${Hello}World"
+ def c = 'Hello' + "$World" // should be "Hello${World}"
+ def d = 'Hello' + 5 // should be 'Hello5'
+ def e = 'Hello' + '''
+ world // should be joined
+ '''
+ def f = '''Hello
+ ''' + 'world' // should be joined
+
+
+ // Not Violations
+ def g = 'Hello' + // OK because of line break
+ 'World'
+ def h = 'Hello' + null // OK because not a string
+ def i = 'Hello' + method() // OK because not a string
+ def j = 'Hello' - "$World" // OK because not +
+
]]>
- bug
-
- excludeRegex
-
-
+ clumsy
-
+
- org.codenarc.rule.convention.TrailingCommaRule
+ org.codenarc.rule.unnecessary.UnnecessaryCallToSubstringRuleMAJOR
-
-
- Check whether list and map literals contain optional trailing comma. Rationale: Putting this comma in make is easier to change the order of the elements or add new elements on the end.
-
This is valid code:
-
- int[] array1 = [] // one line declaration
- int[] array2 = [ // empty list
- ]
- int[] array3 = [1,2,3] // one line declaration
- int[] array4 = [1,
- 2,
- 3, // contains trailing comma
- ]
-
+
+
+ Calling String.substring(0) always returns the original string. This code is meaningless.
+
Examples:
- int[] array2 = [1,
- 2 // there is no trailing comma
- ]
+ string.substring(0) // violation
+ method().substring(0) // violation
+
+ prop.substring(1) // OK, not constant 0
+ prop.substring(0, 1) // OK, end is specified
]]>
- bug
-
- checkList
-
- true
-
-
- checkMap
-
- true
-
+ clumsy
-
+
- org.codenarc.rule.convention.NoTabCharacterRule
+ org.codenarc.rule.unnecessary.UnnecessaryDefInMethodDeclarationRuleMAJOR
-
-
- Checks that all source files do not contain the tab character.
-]]>
- bug
-
+
+
+ If a method has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private method() {}' is redundant and can be simplified to 'private method() {}'.
+
Examples of violations:
+
+ // def and private is redundant
+ def private method1() { return 4 }
-
+ // def and protected is redundant
+ def protected method2() { return 4 }
-
-
- org.codenarc.rule.groovyism.ExplicitArrayListInstantiationRule
- MINOR
-
-
- This rule checks for explicit calls to the no-argument constructor of ArrayList. In Groovy, it is best to write new ArrayList() as [], which creates the same object.
- ]]>
- groovyism
-
+ // def and public is redundant
+ def public method3() { return 4 }
-
-
- org.codenarc.rule.groovyism.ExplicitCallToAndMethodRule
- MINOR
-
-
- This rule detects when the and(Object) method is called directly in code instead of using the & operator. A groovier way to express this: a.and(b) is this: a & b. This rule can be configured to ignore this.and(Object) using the property. It defaults to , so even and(x) will not trigger a violation. The default is because and appears commonly in Grails criteria.
-
This rule also ignores all calls to super.and(Object).
- ]]>
- groovyism
-
+ // def and static is redundant
+ def static method4() { return 4 }
-
-
- org.codenarc.rule.groovyism.ExplicitCallToCompareToMethodRule
- MINOR
-
-
- This rule detects when the compareTo(Object) method is called directly in code instead of using the \<\=\>, \>, \>\=, \<, and \<\= operators. A groovier way to express this: a.compareTo(b) is this: a \<\=\> b, or using the other operators. Here are some other ways to write groovier code:
-
- a.compareTo(b) == 0 // can be replaced by: a == b
- a.compareTo(b) // can be replaced by: a <=> b
- a.compareTo(b) > 0 // can be replaced by: a > b
- a.compareTo(b) >= 0 // can be replaced by: a >= b
- a.compareTo(b) < 0 // can be replaced by: a < b
- a.compareTo(b) <= 0 // can be replaced by: a <= b
+ // def and type is redundant
+ def Object method5() { return 4 }
+
+ class MyClass {
+ def MyClass() {} // def is redundant
+ }
]]>
- groovyism
-
-
-
-
- org.codenarc.rule.groovyism.ExplicitCallToDivMethodRule
- MINOR
-
-
- This rule detects when the div(Object) method is called directly in code instead of using the / operator. A groovier way to express this: a.div(b) is this: a / b. This rule can be configured to ignore div.xor(Object) using the property. It defaults to , so even div(x) will trigger a violation.
-
This rule also ignores all calls to super.div(Object).
- ]]>
- groovyism
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitCallToEqualsMethodRule
- MINOR
-
-
- This rule detects when the equals(Object) method is called directly in code instead of using the == or != operator. A groovier way to express this: a.equals(b) is this: a == b and a groovier way to express : !a.equals(b) is: a != b. This rule can be configured to ignore this.equals(Object) using the property. It defaults to , so even equals(x) will trigger a violation.
-
This rule also ignores all calls to super.equals(Object).
- ]]>
- groovyism
-
+ org.codenarc.rule.unnecessary.UnnecessaryModOneRule
+ MAJOR
+
+
+ Any expression mod 1 (exp % 1) is guaranteed to always return zero. This code is probably an error, and should be either (exp & 1) or (exp % 2).
+
Examples:
+
+ if (exp % 1) {} // violation
+ if (method() % 1) {} // violation
-
-
- org.codenarc.rule.groovyism.ExplicitCallToGetAtMethodRule
- MINOR
-
-
- This rule detects when the getAt(Object) method is called directly in code instead of using the [] index operator. A groovier way to express this: a.getAt(b) is this: a[b]. This rule can be configured to ignore this.getAt(Object) using the property. It defaults to , so even getAt(x) will trigger a violation.
-
This rule also ignores all calls to super.getAt(Object).
- ]]>
- groovyism
+ if (exp & 1) {} // ok
+ if (exp % 2) {} // ok
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitCallToLeftShiftMethodRule
- MINOR
-
-
- This rule detects when the leftShift(Object) method is called directly in code instead of using the \<\< operator. A groovier way to express this: a.leftShift(b) is this: a \<\< b. This rule can be configured to ignore this.leftShift(Object) using the property. It defaults to , so even leftShift(x) will trigger a violation.
-
This rule also ignores all calls to super.leftShift(Object).
- ]]>
- groovyism
-
+ org.codenarc.rule.unnecessary.UnnecessaryPublicModifierRule
+ MAJOR
+
+
+ The 'public' modifier is not required on methods, constructors or classes.
+
Example of violations:
+
+ // violation on class
+ public class MyClass {
+ // violation on constructor
+ public MyClass() {}
-
-
- org.codenarc.rule.groovyism.ExplicitCallToMinusMethodRule
- MINOR
-
-
- This rule detects when the minus(Object) method is called directly in code instead of using the - operator. A groovier way to express this: a.minus(b) is this: a - b. This rule can be configured to ignore minus.xor(Object) using the property. It defaults to , so even minus(x) will trigger a violation.
-
This rule also ignores all calls to super.minus(Object).
- ]]>
- groovyism
+ // violation on method
+ public void myMethod() {}
+ }
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitCallToMultiplyMethodRule
- MINOR
-
-
- This rule detects when the multiply(Object) method is called directly in code instead of using the * operator. A groovier way to express this: a.multiply(b) is this: a * b. This rule can be configured to ignore this.multiply(Object) using the property. It defaults to , so even multiply(x) will trigger a violation.
-
This rule also ignores all calls to super.multiply(Object).
- ]]>
- groovyism
-
+ org.codenarc.rule.unnecessary.UnnecessarySelfAssignmentRule
+ MAJOR
+
+
+ Method contains a pointless self-assignment to a variable or property. Either the code is pointless or the equals()/get() method has been overridden to have a side effect, which is a terrible way to code getters and violates the contract of equals().
+
Examples:
+
+ x = x // violation
+ def method(y) {
+ y = y // violation
+ }
+ a.b.c = a.b.c // violation
-
-
- org.codenarc.rule.groovyism.ExplicitCallToModMethodRule
- MINOR
-
-
- This rule detects when the mod(Object) method is called directly in code instead of using the % operator. A groovier way to express this: a.mod(b) is this: a % b. This rule can be configured to ignore this.mod(Object) using the property. It defaults to , so even mod(x) will trigger a violation.
-
This rule also ignores all calls to super.mod(Object).
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitCallToOrMethodRule
- MINOR
-
-
- This rule detects when the or(Object) method is called directly in code instead of using the | operator. A groovier way to express this: a.or(b) is this: a | b. This rule can be configured to ignore this.or(Object) using the property. It defaults to , so even or(x) will not trigger a violation. This is the default because it is commonly used in Grails criteria.
-
This rule also ignores all calls to super.or(Object).
- ]]>
- groovyism
-
+ org.codenarc.rule.unnecessary.UnnecessarySemicolonRule
+ MAJOR
+
+
+ Semicolons as line terminators are not required in Groovy: remove them. Do not use a semicolon as a replacement for empty braces on for and while loops; this is a confusing practice.
+
The rule contains a String property called 'excludePattern'. Any source code line matching this pattern will not trigger a violation. The default value is '\\s?\\*.*|/\\*.*|.*//.*|.*\\*/.*' This is to filter out comments. Any source line that even looks like it is a comment is ignored.
+
\s?\*.* == whitespace plus star character plus anything /\*.* == any line that contains the /* sequence .*//.* == any line that contains the // sequence .*\*/.* == any line that contains the */ sequence
+
Example of violations:
+
+ package my.company.server; // violation
-
-
- org.codenarc.rule.groovyism.ExplicitCallToPlusMethodRule
- MINOR
-
-
- This rule detects when the plus(Object) method is called directly in code instead of using the + operator. A groovier way to express this: a.plus(b) is this: a + b. This rule can be configured to ignore this.plus(Object) using the property. It defaults to , so even plus(x) will trigger a violation.
-
This rule also ignores all calls to super.plus(Object).
- ]]>
- groovyism
-
+ import java.lang.String; // violation
-
-
- org.codenarc.rule.groovyism.ExplicitCallToPowerMethodRule
- MINOR
-
-
- This rule detects when the power(Object) method is called directly in code instead of using the ** operator. A groovier way to express this: a.power(b) is this: a ** b. This rule can be configured to ignore this.power(Object) using the property. It defaults to , so even power(x) will trigger a violation.
-
This rule also ignores all calls to super.power(Object).
- ]]>
- groovyism
-
+ println(value) ; // violation
-
-
- org.codenarc.rule.groovyism.ExplicitCallToRightShiftMethodRule
- MINOR
-
-
- This rule detects when the rightShift(Object) method is called directly in code instead of using the \>\> operator. A groovier way to express this: a.rightShift(b) is this: a \>\> b. This rule can be configured to ignore this.rightShift(Object) using the property. It defaults to , so even rightShift(x) will trigger a violation.
-
This rule also ignores all calls to super.rightShift(Object).
- ]]>
- groovyism
-
+ for (def x : list); // violation
-
-
- org.codenarc.rule.groovyism.ExplicitCallToXorMethodRule
- MINOR
-
-
- This rule detects when the xor(Object) method is called directly in code instead of using the ^ operator. A groovier way to express this: a.xor(b) is this: a ^ b. This rule can be configured to ignore this.xor(Object) using the property. It defaults to , so even xor(x) will trigger a violation.
-
This rule also ignores all calls to super.xor(Object).
- ]]>
- groovyism
+ // this code is OK
+ println(value); println (otherValue)
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitHashMapInstantiationRule
- MINOR
-
-
- This rule checks for explicit calls to the no-argument constructor of HashMap. In Groovy, it is best to replace new HashMap() with [:], which creates (mostly) the same object. [:] is technically a LinkedHashMap but it is very rare that someone absolutely needs an instance of HashMap and not a subclass.
- ]]>
- groovyism
-
+ org.codenarc.rule.unnecessary.UnnecessaryTransientModifierRule
+ MAJOR
+
+
+ The field is marked as transient, but the class isn't Serializable, so marking it as transient has no effect. This may be leftover marking from a previous version of the code in which the class was transient, or it may indicate a misunderstanding of how serialization works.
+
Some Java frameworks change the semantics of the transient keyword. For instance, when using Terracotta the transient keyword may have slightly different semantics. You may need to turn this rule off depending on which Java frameworks are in use.
+ Examples:
+
+ class MyClass {
+ // class not serializable, violation occurs
+ transient String property
+ }
-
-
- org.codenarc.rule.groovyism.ExplicitHashSetInstantiationRule
- MINOR
-
-
- This rule checks for explicit calls to the no-argument constructor of HashSet. In Groovy, it is best to replace new HashSet() with [] as Set, which creates the same object.
- ]]>
- groovyism
+ class MySerializableClass implements Serializable {
+ // OK, class is serializable
+ transient String property
+ }
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitLinkedListInstantiationRule
- MINOR
-
-
- This rule checks for explicit calls to the no-argument constructor of LinkedList. In Groovy, it is best to replace new LinkedList() with [] as Queue, which creates the same object.
- ]]>
- groovyism
+ org.codenarc.rule.unnecessary.UnnecessaryFinalOnPrivateMethodRule
+ MAJOR
+
+
+ A private method is marked final. Private methods cannot be overridden, so marking it final is unnecessary.
+
Example of violations:
+
+ private final method() {}
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitStackInstantiationRule
- MINOR
-
-
- This rule checks for explicit calls to the no-argument constructor of Stack. In Groovy, it is best to replace new Stack() with [] as Stack, which creates the same object.
- ]]>
- groovyism
+ org.codenarc.rule.unnecessary.UnnecessaryElseStatementRule
+ MAJOR
+
+
+ When an if statement block ends with a return statement, then the else is unnecessary. The logic in the else branch can be run without being in a new scope.
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitTreeSetInstantiationRule
- MINOR
-
-
- This rule checks for explicit calls to the no-argument constructor of TreeSet. In Groovy, it is best to replace new TreeSet() with [] as SortedSet, which creates the same object.
- ]]>
- groovyism
+ org.codenarc.rule.unnecessary.UnnecessaryParenthesesForMethodCallWithClosureRule
+ MAJOR
+
+
+ If a method is called and the only parameter to that method is an inline closure then the parentheses of the method call can be omitted.
+
Example of violations:
+
+ [1,2,3].each() { println it }
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.GStringAsMapKeyRule
- MINOR
-
-
- A GString should not be used as a map key since its is not guaranteed to be stable. Consider calling key.toString().
-
Here is an example of code that produces a violation:
+ org.codenarc.rule.unnecessary.UnnecessaryPackageReferenceRule
+ MAJOR
+
+
+ Checks for explicit package reference for classes that Groovy imports by default, such as java.lang.String, java.util.Map and groovy.lang.Closure, as well as classes that were explicitly imported.
+
You do not need to specify the package for any classes from , , , , and , as well as the classes and .
]]>
- groovyism
+ clumsy
-
+
- org.codenarc.rule.groovyism.GroovyLangImmutableRule
- MINOR
-
-
- The groovy.lang.Immutable annotation has been deprecated and replaced by groovy.transform.Immutable. Do not use the Immutable in groovy.lang.
-
Example of violations:
+ org.codenarc.rule.unnecessary.UnnecessaryDefInVariableDeclarationRule
+ MAJOR
+
+
+ If a variable has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private n = 2' is redundant and can be simplified to 'private n = 2'.
+
Examples of violations:
- @Immutable
- class Person { }
-
- @groovy.lang.Immutable
- class Person { }
+ // def and private is redundant
+ def private string1 = 'example'
- import groovy.lang.Immutable as Imtl
- @Imtl
- class Person { }
+ // def and protected is redundant
+ def protected string2 = 'example'
- // the following code is OK
- @groovy.transform.Immutable
- class Person { }
+ // def and public is redundant
+ def public string3 = 'example'
- import groovy.transform.Immutable
- @Immutable
- class Person { }
+ // def and static is redundant
+ def static string4 = 'example'
- import groovy.transform.*
- @Immutable
- class Person { }
+ // def and final is redundant
+ def final string5 = 'example'
- import groovy.transform.Immutable as Imtl
- @Imtl
- class Person { }
+ // def and a type is redundant
+ def String string6 = 'example'
]]>
- groovyism
+ clumsy
-
+
- org.codenarc.rule.groovyism.ExplicitLinkedHashMapInstantiationRule
- MINOR
-
-
- This rule checks for the explicit instantiation of a LinkedHashMap using the no-arg constructor. In Groovy, it is best to replace new LinkedHashMap() with [:], which creates the same object.
- ]]>
- groovyism
+ org.codenarc.rule.unnecessary.UnnecessaryDotClassRule
+ MAJOR
+
+
+ To make a reference to a class, it is unnecessary to specify the '.class' identifier. For instance String.class can be shortened to String.
+
Example of violations:
+
+ // The '.class' identifier is unnecessary, violation occurs
+ def x = String.class
+
+ // Ok, unnecessary '.class' identifier has been excluded
+ def x = String
+
+]]>
+ clumsy
-
+
- org.codenarc.rule.groovyism.ClosureAsLastMethodParameterRule
+ org.codenarc.rule.unnecessary.UnnecessaryInstanceOfCheckRuleMAJOR
-
-
- If a method is called and the last parameter is an inline closure then it can be declared outside of the method call parentheses.
+
+
+ This rule finds instanceof checks that cannot possibly evaluate to true. For instance, checking that (!variable instanceof String) will never be true because the result of a not expression is always a boolean.
Example of violations:
- // creates violation: poor Groovy style
- [1,2,3].each({ println it })
+ if (!variable instanceof String) { ... } // always false
+ def x = !variable instanceof String // always false
- // no violation
- [1,2,3].each { println it }
+ if (!variable instanceof Boolean) { ... } // always true
+ def x = !variable instanceof Boolean // always true
+
+ // this code is OK
+ if (!(variable instanceof String)) { ... }
]]>
- groovyism
+ clumsy
- org.codenarc.rule.groovyism.AssignCollectionUniqueRule
- MINOR
-
-
- The Collections.unique() method mutates the list and returns the list as a value. If you are assigning the result of unique() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a unique() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
+ org.codenarc.rule.unnecessary.UnnecessarySubstringRule
+ MAJOR
+
+
+ This rule finds usages of String.substring(int) and String.substring(int, int) that can be replaced by use of the subscript operator. For instance, var.substring(5) can be replaced with var[5..-1].
+
Note that the String.substring(beginIndex,endIndex) method specifies a range of beginIndex..endIndex-1, while Groovy's String subscript specifies an inclusive range. So, "123456".substring(1, 5) is equivalent to "123456"[1..4].
Example of violations:
- def a = myList.unique()
- def b = myList.unique() { it }
- def c = myList.unique().findAll { x < 1 }
+ myVar.substring(5) // can use myVar[5..-1] instead
+ myVar.substring(1, 5) // can use myVar[1..4] instead
+
+]]>
+ clumsy
+
+
+
+
+ org.codenarc.rule.unnecessary.UnnecessaryDefInFieldDeclarationRule
+ MAJOR
+
+
+ If a field has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance, 'static def constraints = {}' is redundant and can be simplified to 'static constraints = {}.
+
Example of violations:
+
+ class MyClass {
+ // def is redundant
+ static def constraints = { }
+
+ // def and private is redundant
+ def private field1 = { }
+
+ // def and protected is redundant
+ def protected field2 = { }
+
+ // def and public is redundant
+ def public field3 = { }
+
+ // def and static is redundant
+ def static field4 = { }
+ // def and type is redundant
+ def Object field5 = { }
+ }
]]>
- groovyism
+ clumsy
-
+
- org.codenarc.rule.groovyism.AssignCollectionSortRule
+ org.codenarc.rule.unnecessary.UnnecessaryCastRuleMINOR
-
-
- The Collections.sort() method mutates the list and returns the list as a value. If you are assigning the result of sort() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a sort() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
+
+
+ Checks for unnecessary cast operations.
Example of violations:
- def a = myList.sort()
- def b = myList.sort() { it }
- def c = myList.sort().findAll { x < 1 }
+ int count = (int)123 // violation
+ def longValue = (long)123456L // violation
+ def bigDecimal = (BigDecimal)1234.56 // violation
+ String name = (String) "Joe" // violation
+ def list = (List)[1, 2, 3] // violation
+ def map = (Map)[a:1] // violation
]]>
- groovyism
+ clumsy
-
+
- org.codenarc.rule.groovyism.ConfusingMultipleReturnsRule
+ org.codenarc.rule.unnecessary.UnnecessaryToStringRuleMINOR
-
-
- Multiple return values can be used to set several variables at once. To use multiple return values, the left hand side of the assignment must be enclosed in parenthesis. If not, then you are not using multiple return values, you're only assigning the last element.
-
Example of violations:
-
-def a, b = [1, 2] // bad, b is null
-def c, d, e = [1, 2, 3] // bad, c and d are null
-class MyClass {
- def a, b, c = [1, 2, 3] // bad, a and b are null
-}
-
-def x = 1 // ok
-def (f, g) = [1, 2] // ok
-(a, b, c) = [1, 2, 3] // ok
-
+
+
+ Checks for unnecessary calls to toString(). This includes:
]]>
- groovyism
+ clumsy
-
+
- org.codenarc.rule.groovyism.GetterMethodCouldBePropertyRule
+ org.codenarc.rule.unnecessary.UnnecessarySafeNavigationOperatorRuleMAJOR
-
-
- If a class defines a public method that follows the Java getter notation and that returns a constant, then it is cleaner to provide a Groovy property for the value rather than a Groovy method.
+
+
+ Check for the operator (?.) applied to constants and literals, or this or super, or constructor calls, all of which can never be null.
+]]>
+ clumsy
+
- class Child extends Parent {
- static VALUE = 'value'
-
- @Override
- String getSomething() {
- 'something' // this could be simplified
- }
-
- @Override
- String getSomethingElse() {
- VALUE // this could be simplified
- }
+
- int getOtherValue() {
- 123
- }
+
+ org.codenarc.rule.unused.UnusedArrayRule
+ MINOR
+
+
+ Checks for array allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
+
+ int myMethod() {
+ new String[3] // unused
+ return -1
+ }
- static String getName() {
- 'MyName'
- }
+ String[] myMethod() {
+ new String[3] // OK (last statement in block)
}
- class Child2 extends Parent {
- static VALUE = 'value'
- final String something = 'something' // this is cleaner
- final String somethingElse = VALUE // this is cleaner
- final int otherValue = 123 // this is cleaner
- static final String name = 'MyName' // this is cleaner
+ def closure = {
+ doStuff()
+ new Date[3] // unused
+ doOtherStuff()
}
+
+ def closure = { new Date[3] } // OK (last statement in block)
]]>
- groovyism
+ bug
-
- org.codenarc.rule.groovyism.UseCollectManyRule
+ org.codenarc.rule.unused.UnusedObjectRuleMINOR
-
-
- In many case collectMany() yields the same result as collect{}.flatten(). It is easier to understand and more clearly conveys the intent.
-
Example of violations:
+
+
+ Checks for object allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
+
By default, this rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'. Invoking constructors without using the result is a common pattern in tests.
-def l = [1, 2, 3, 4]
+ int myMethod() {
+ new BigDecimal("23.45") // unused
+ return -1
+ }
-l.collect{ [it, it*2] }.flatten() // suboptimal
+ BigDecimal myMethod() {
+ new BigDecimal("23.45") // OK (last statement in block)
+ }
-l.collectMany{ [it, it*2] } // same functionality, better readability
+ def closure = {
+ doStuff()
+ new Date() // unused
+ doOtherStuff()
+ }
+
+ def closure = { new Date() } // OK (last statement in block)
]]>
- groovyism
+ bug
-
- org.codenarc.rule.groovyism.CollectAllIsDeprecatedRule
+ org.codenarc.rule.unused.UnusedPrivateFieldRuleMINOR
-
-
- The collectAll method is deprecated since Groovy 1.8.1. Use collectNested instead.
-
Example of violations:
-
-def list = [1, 2, [3, 4, [5, 6]], 7]
-
-list.collectAll { it * 2 } // deprecated
-
-list.collectNested { it * 2 } // replacement
-
+
+
+ Checks for private fields that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes). By default, fields named serialVersionUID are ignored. The rule has a property named ignoreFieldNames, which can be set to ignore other field names as well. For instance, to ignore fields named 'fieldx', set the property to the 'fieldx, serialVersionUID'
+
-def list = [1, 2, [3, 4, 5, 6], [7]]
-
-println list.collect { elem ->
- if (elem instanceof List)
- elem.collect {it *2} // violation
- else elem * 2
-}
-
-println list.collect([8]) {
- if (it instanceof List)
- it.collect {it *2} // violation
- else it * 2
-}
+
+
+ Checks for private methods that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
+
Known limitations:
+]]>
+ bug
+
-println list.collectNested { it * 2 } // same functionality, better readability
-
+
+ org.codenarc.rule.unused.UnusedVariableRule.fixed
+ MINOR
+
+
+ Checks for variables that are never referenced.
+
The rule has a property named ignoreVariableNames, which can be set to ignore some variable names. For instance, to ignore fields named 'unused', set the property to 'unused'.
- def str1 = 'total: ${count}' // violation
- def str2 = 'average: ${total / count}' // violation
+
+
+ Checks for parameters to private methods that are not referenced within the method body. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
+
Known limitations:
+]]>
+ bug
+
- def str3 = "abc ${count}" // ok; GString
- def str4 = '$123' // ok
- def str5 = 'abc {123}' // ok
-
+
+
+ org.codenarc.rule.unused.UnusedMethodParameterRule
+ MINOR
+
+
+ This rule finds instances of method parameters not being used. It does not analyze private methods (that is done by the UnusedPrivateMethodParameter rule) or methods marked @Override.
]]>
- groovyism
+ bug
From a62fab15466ab08ae8b0580d2f1c5669fcf26750 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Mon, 24 Jun 2019 22:41:26 +0200
Subject: [PATCH 57/89] Add "support" for SonarQube 7.8
This would be much easier if SonarSource wouldn't drop testing APIs all
the time :(
---
.travis.yml | 1 +
.../plugins/groovy/GroovyPluginTest.java | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index ad7b7992..905ae517 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,7 @@ env:
- SONAR_VERSION=7.5
- SONAR_VERSION=7.6
- SONAR_VERSION=7.7
+- SONAR_VERSION=7.8
# Install step is redundant
install: true
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java
index b913ceae..7168780c 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java
@@ -21,6 +21,8 @@
import static org.assertj.core.api.Assertions.assertThat;
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
import org.junit.Test;
import org.sonar.api.Plugin;
import org.sonar.api.SonarQubeSide;
@@ -35,7 +37,22 @@ public class GroovyPluginTest {
public void testExtensions() {
GroovyPlugin plugin = new GroovyPlugin();
- SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(VERSION_6_7, SonarQubeSide.SCANNER);
+ Binding b = new Binding();
+ Class> edition = null;
+ String call = "rt.forSonarQube(ver, scanner)";
+ try {
+ edition = Class.forName("org.sonar.api.SonarEdition");
+ call = "rt.forSonarQube(ver, scanner, ed.COMMUNITY)";
+ } catch (ClassNotFoundException e) {
+ // SKIP on old SonarQube
+ }
+ b.setVariable("ver", VERSION_6_7);
+ b.setVariable("scanner", SonarQubeSide.SCANNER);
+ b.setVariable("ed", edition);
+ b.setVariable("rt", SonarRuntimeImpl.class);
+ GroovyShell sh = new GroovyShell(b);
+
+ SonarRuntime runtime = (SonarRuntime) sh.evaluate(call);
Plugin.Context context = new Plugin.Context(runtime);
plugin.define(context);
assertThat(context.getExtensions()).hasSize(14);
From 9ab4aa977eef1587adbe8c822e87d15e2f6f02ba Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Mon, 24 Jun 2019 23:39:17 +0200
Subject: [PATCH 58/89] Add SonarSource bintray repository
This allows us to use versions which haven't made it to Maven Central
yet.
---
pom.xml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/pom.xml b/pom.xml
index fa3e7e25..1a78c3c9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,6 +143,14 @@
+
+
+ sonarsource-bintray
+ SonarSource Bintray Release repository
+ https://dl.bintray.com/sonarsource/SonarQube
+
+
+
From 2aab148c5da49f0a7de701935ddf2d3bf8456203 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Fri, 28 Jun 2019 10:53:48 +0200
Subject: [PATCH 59/89] Improve rule descriptions
- Don't swallow lists
- Make sure paragraph content doesn't contain unescaped HTML "tags"
- Represent different syntax with different HTML tags
---
README.md | 8 +
.../groovy/codenarc/RuleParameter.java | 4 +-
.../groovy/codenarc/apt/AptParser.java | 79 +-
.../groovy/codenarc/apt/AptResult.java | 2 +-
.../groovy/codenarc/ConverterTest.java | 3 +-
.../org/sonar/plugins/groovy/rules.xml | 2979 +++++++++--------
6 files changed, 1607 insertions(+), 1468 deletions(-)
diff --git a/README.md b/README.md
index 16b786d5..18f3f094 100644
--- a/README.md
+++ b/README.md
@@ -90,3 +90,11 @@ cd ..
git add CodeNarc
```
+You should then run the `codenarc-converter` (Running `mvn verify` should be
+enough if the project is set up correctly) and merge descriptions from
+`codenarc-converter/target/results/rules.xml` into
+`sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml`.
+The converter does a pretty crude job converting CodeNarc's [APT] documentation
+into SonarQube rule descriptions.
+
+[APT]: https://maven.apache.org/doxia/references/apt-format.html
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleParameter.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleParameter.java
index 1074603f..b444ca85 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleParameter.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleParameter.java
@@ -72,7 +72,9 @@ public RuleParameter withNewDefaultValue(String newDefaultValue) {
}
public RuleParameter withExpandedDescription(String descAdd) {
- return create(key(), description() + descAdd, defaultValue());
+ String newDesc = description();
+ newDesc += (newDesc.isEmpty() ? "" : " ") + descAdd;
+ return create(key(), newDesc, defaultValue());
}
private static String selectValue(String currentValue, String newValue) {
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptParser.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptParser.java
index 074d016b..379bbef6 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptParser.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptParser.java
@@ -68,7 +68,7 @@ private Map readFile(File file) throws IOException {
for (int index = 0; index < lines.size(); index++) {
String fullLine = lines.get(index);
String line = fullLine.trim();
- if (line.startsWith(NEW_RULE_PREFIX) && !line.startsWith(LIST_PREFIX) && inRule) {
+ if (fullLine.startsWith(NEW_RULE_PREFIX) && !line.startsWith(LIST_PREFIX) && inRule) {
results.put(currentRule, currentResult);
inRule = false;
inDescription = false;
@@ -95,7 +95,7 @@ private Map readFile(File file) throws IOException {
&& isValidDescriptionLine(line)) {
inDescription = true;
if (StringUtils.isNotBlank(line)) {
- currentResult.description += "
"
+ : " ")
+ + cleanLine;
}
private static boolean isEndOfParagraph(AptResult currentResult, String line) {
@@ -202,20 +204,42 @@ private static boolean isParameterSeparator(String line) {
return line.matches(PARAMETER_SEPARATOR) || line.matches(PARAMETER_START_SEPARATOR);
}
- private static String cleanDescription(String description, boolean isForParameter) {
- String result = description;
- if (!isForParameter) {
- result = result.replaceAll("<<<", "");
- result = result.replaceAll("<<", "");
- result = result.replaceAll(">>>", "");
- result = result.replaceAll(">>", "");
- } else {
- result = result.replaceAll("<<<", "");
- result = result.replaceAll("<<", "");
- result = result.replaceAll(">>>", "");
- result = result.replaceAll(">>", "");
- }
- return result;
+ private static String cleanDescription(String description) {
+ String result = " " + description + " ";
+ // This is a bit stupid
+ result = result.replaceAll("&", "&");
+ result = result.replaceAll(" <=> ", " <=> ");
+ result = result.replaceAll(" <<<= ", " <<<= ");
+ result = result.replaceAll(" >>>= ", " >>>= ");
+ result = result.replaceAll(" <<= ", " <<= ");
+ result = result.replaceAll(" >>= ", " >>= ");
+ result = result.replaceAll(" <= ", " <= ");
+ result = result.replaceAll(" >= ", " >= ");
+ result = result.replaceAll(" < ", " < ");
+ result = result.replaceAll(" > ", " > ");
+ result = result.replaceAll("->", "->");
+ result = result.replaceAll("\\\\=", "=");
+ result = result.replaceAll("\\\\<", "<");
+ result = result.replaceAll("\\\\>", ">");
+
+ result = result.replaceAll("<", "\uE000");
+ result = result.replaceAll(">", "\uE001");
+
+ result = result.replaceAll("\uE000\uE000\uE000", "");
+ result = result.replaceAll("\uE000\uE000", "");
+ result = result.replaceAll("\uE000", "");
+ result = result.replaceAll("\uE001\uE001\uE001", "");
+ result = result.replaceAll("\uE001\uE001", "");
+ result = result.replaceAll("\uE001", "");
+ return result.trim();
+ }
+
+ private static String cleanParameter(String param) {
+ return param.replaceAll("<", "").replaceAll(">", "");
+ }
+
+ private String cleanExample(String line) {
+ return line.replaceAll("&", "&").replaceAll("\\\\?<", "<").replaceAll("\\\\?>", ">");
}
private static String cleanDefaultValue(String defaultValue) {
@@ -290,4 +314,5 @@ private static void mergeParameters(
results.put(rule, currentRuleResult);
}
}
+
}
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptResult.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptResult.java
index c67abc09..65550bd6 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptResult.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/apt/AptResult.java
@@ -65,7 +65,7 @@ public Set getParameters() {
}
public String getDescription() {
- return description;
+ return description.trim();
}
public boolean hasParameters() {
diff --git a/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java b/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
index 70a7575e..5970378f 100644
--- a/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
+++ b/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
@@ -147,8 +147,9 @@ private static void assertSimilarXml(Path generatedRulesXML, Path rulesFromPlugi
* - MisorderedStaticImportsRule : description of 'comesBefore' parameter missing in apt files
* - FileCreateTempFileRule: link to website
* - BracesForIfElseRule: default value of parameters should be true, not 'the same as sameLine'
+ * - JUnitTestMethodWithoutAssertRule, UnnecessaryObjectReferencesRule: Non-matching open & close tags
*/
- Assert.assertEquals(3, nbrDiff);
+ Assert.assertEquals(5, nbrDiff);
}
private static String getRuleKey(Node rule) {
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index 5e45ce81..d302240b 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -7,14 +7,13 @@
MINOR
- Checks for calls to the java.math.BigDecimal constructors that take a double value as the first parameter. As described in the BigDecimal javadoc, the results from these constructors can be somewhat unpredictable, and their use is generally not recommended. This is because some numbers, such as 0.1, cannot be represented exactly as a double.
-
For instance, executing println new BigDecimal(0.1) prints out 0.1000000000000000055511151231257827021181583404541015625.
-
Here is an example of code that produces a violation:
+ Checks for calls to the java.math.BigDecimal constructors that take a double value as the first parameter. As described in the BigDecimal javadoc, the results from these constructors can be somewhat unpredictable, and their use is generally not recommended. This is because some numbers, such as 0.1, cannot be represented exactly as a double.
+
For instance, executing println new BigDecimal(0.1) prints out 0.1000000000000000055511151231257827021181583404541015625.
+
Here is an example of code that produces a violation:
def b1 = new BigDecimal(0.1) // violation
def b2 = new java.math.BigDecimal(23.45d) // violation
-
-]]>
+]]>
bug
@@ -23,7 +22,7 @@
MINOR
- Checks for statements with a constant value for the boolean expression, such as true, false, null, or a literal constant value. These statements can be simplified or avoided altogether. Examples of violations include:
+ Checks for if statements with a constant value for the if boolean expression, such as true, false, null, or a literal constant value. These if statements can be simplified or avoided altogether. Examples of violations include:
if (true) { .. }
if (false) { .. }
@@ -37,8 +36,7 @@
if ([:]) { .. }
if ([a:123, b:456]) { .. }
if ([a, b, c]) { .. }
-
-]]>
+]]>bug
@@ -47,7 +45,7 @@
MINOR
- Checks for ternary expressions with a constant value for the boolean expression, such as true, false, null, or a literal constant value. Examples of violations include:
+ Checks for ternary expressions with a constant value for the boolean expression, such as true, false, null, or a literal constant value. Examples of violations include:
true ? x : y
false ? x : y
@@ -69,8 +67,7 @@
"abc" ?: y
[:] ?: y
[a, b, c] ?: y
-
-]]>
+]]>bug
@@ -79,9 +76,9 @@
MINOR
- Checks for empty blocks. In most cases, exceptions should not be caught and ignored (swallowed).
-
The rule has a property named ignoreRegex that defaults to the value 'ignore|ignored'. If the name of the exception matches this regex then no violations are produced.
-
Here is an example of code that produces a violation:
+ Checks for empty catch blocks. In most cases, exceptions should not be caught and ignored (swallowed).
+
The rule has a property named ignoreRegex that defaults to the value 'ignore|ignored'. If the name of the exception matches this regex then no violations are produced.
+
Here is an example of code that produces a violation:
def myMethod() {
try {
@@ -98,12 +95,11 @@
//no violations because the parameter name is ignored
}
}
-
-]]>
+]]>unusedignoreRegex
-
+ ignore|ignored
@@ -113,8 +109,8 @@
MINOR
- Checks for empty blocks. Empty blocks are confusing and serve no purpose.
-
Here is an example of code that produces a violation:
+ Checks for empty else blocks. Empty else blocks are confusing and serve no purpose.
+
Here is an example of code that produces a violation:
-]]>
+]]>unused
@@ -264,8 +252,8 @@
MINOR
- Checks that if either the boolean equals(Object) or the int hashCode() methods are overridden within a class, then both must be overridden.
-
Here is an example of code that produces a violation:
+ Checks that if either the boolean equals(Object) or the int hashCode() methods are overridden within a class, then both must be overridden.
+
Here is an example of code that produces a violation:
-]]>
+]]>pitfall
@@ -289,8 +276,8 @@
MINOR
- Checks for a return from within a block. Returning from a block is confusing and can hide the original exception.
-
Here is an example of code that produces a violation:
+ Checks for a return from within a finally block. Returning from a finally block is confusing and can hide the original exception.
+
Here is an example of code that produces a violation:
-]]>
+]]>error-handling
@@ -312,8 +298,8 @@
MINOR
- Checks for throwing an exception from within a block. Throwing an exception from a block is confusing and can hide the original exception.
-
Here is an example of code that produces a violation:
+ Checks for throwing an exception from within a finally block. Throwing an exception from a finally block is confusing and can hide the original exception.
+
Here is an example of code that produces a violation:
int myMethod() {
try {
@@ -324,8 +310,7 @@
throw new Exception() // violation
}
}
-
-]]>
+]]>error-handling
@@ -335,8 +320,7 @@
MINOR
- Dead code appears after a return statement or an exception is thrown. If code appears after one of these statements then it will never be executed and can be safely deleted.
- ]]>
+ Dead code appears after a return statement or an exception is thrown. If code appears after one of these statements then it will never be executed and can be safely deleted.]]>unused
@@ -346,8 +330,7 @@
MINOR
- There is no point in using a double negative, it is always positive. For instance !!x can always be simplified to x. And !(!x) can as well.
- ]]>
+ There is no point in using a double negative, it is always positive. For instance !!x can always be simplified to x. And !(!x) can as well.]]>bug
@@ -357,7 +340,7 @@
MINOR
- Check for duplicate case statements in a switch block, such as two equal integers or strings. Here are some examples of code that produces violations:
+ Check for duplicate case statements in a switch block, such as two equal integers or strings. Here are some examples of code that produces violations:
switch( 0 ) {
case 1: break;
@@ -372,8 +355,7 @@
case "ab": break; // violation
case "abc": break;
}
-
-]]>
+]]>bug
@@ -383,8 +365,7 @@
MINOR
- Don't use removeAll to clear a collection. If you want to remove all elements from a collection c, use c.clear, not c.removeAll(c). Calling c.removeAll(c) to clear a collection is less clear, susceptible to errors from typos, less efficient and for some collections, might throw a ConcurrentModificationException.
- ]]>
+ Don't use removeAll to clear a collection. If you want to remove all elements from a collection c, use c.clear, not c.removeAll(c). Calling c.removeAll(c) to clear a collection is less clear, susceptible to errors from typos, less efficient and for some collections, might throw a ConcurrentModificationException.]]>bug
@@ -394,8 +375,7 @@
MINOR
- Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Code should have the same behavior whether the garbage collection is disabled using the option -Xdisableexplicitgc or not. Moreover, "modern" JVMs do a very good job handling garbage collections. If memory usage issues unrelated to memory leaks develop within an application, it should be dealt with JVM options rather than within the code itself.
- ]]>
+ Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Code should have the same behavior whether the garbage collection is disabled using the option -Xdisableexplicitgc or not. Moreover, "modern" JVMs do a very good job handling garbage collections. If memory usage issues unrelated to memory leaks develop within an application, it should be dealt with JVM options rather than within the code itself.]]>unpredictable
@@ -405,8 +385,8 @@
MINOR
- An assignment operator (=) was used in a conditional test. This is usually a typo, and the comparison operator (==) was intended.
-
Example of violations:
+ An assignment operator (=) was used in a conditional test. This is usually a typo, and the comparison operator (==) was intended.
+
Example of violations:
if ((value = true)) {
// should be ==
@@ -425,8 +405,7 @@
value == true ? x : y
value == true ?: x
-
-]]>
+]]>bug
@@ -436,8 +415,8 @@
MINOR
- This rule catches usages of java.lang.Boolean.getBoolean(String) which reads a boolean from the System properties. It is often mistakenly used to attempt to read user input or parse a String into a boolean. It is a poor piece of API to use; replace it with System.properties['prop̈́'].
-
Example of violations:
+ This rule catches usages of java.lang.Boolean.getBoolean(String) which reads a boolean from the System properties. It is often mistakenly used to attempt to read user input or parse a String into a boolean. It is a poor piece of API to use; replace it with System.properties['prop̈́'].
+
Example of violations:
// produces violation
Boolean.getBoolean(value)
@@ -445,8 +424,7 @@
// zero or two parameters is OK, must be different method
Boolean.getBoolean(value, 1)
Boolean.getBoolean()
-
-]]>
+]]>bug
@@ -456,16 +434,15 @@
MINOR
- The code uses x % 2 == 1 to check to see if a value is odd, but this won't work for negative numbers (e.g., (-5) % 2 == -1). If this code is intending to check for oddness, consider using x & 1 == 1, or x % 2 != 0.
-
Examples:
+ The code uses x % 2 == 1 to check to see if a value is odd, but this won't work for negative numbers (e.g., (-5) % 2 == -1). If this code is intending to check for oddness, consider using x & 1 == 1, or x % 2 != 0.
+
Examples:
if (x % 2 == 1) { } // violation
if (method() % 2 == 1) { } // violation
- if (x & 1 == 1) { } // OK
+ if (x & 1 == 1) { } // OK
if (x % 2 != 0) { } // OK
-
-]]>
+]]>bug
@@ -475,13 +452,12 @@
MINOR
- An empty class instance initializer was found. It is safe to remove it. Example:
+ An empty class instance initializer was found. It is safe to remove it. Example:
class MyClass {
{ } // empty instance initializer, not a closure
}
-
-]]>
+]]>unused
@@ -491,8 +467,8 @@
MINOR
- A method was found without an implementation. If the method is overriding or implementing a parent method, then mark it with the @Override annotation. This rule should not be used with Java 5 code because you cannot put @Override on a method implementing an interface. Use with Java 6 and higher.
-
Example of violations:
+ A method was found without an implementation. If the method is overriding or implementing a parent method, then mark it with the @Override annotation. This rule should not be used with Java 5 code because you cannot put @Override on a method implementing an interface. Use with Java 6 and higher.
+
Example of violations:
class MyClass {
@@ -511,8 +487,7 @@
// OK, handled by EmptyMethodInAbstractClass Rule
public void method() {}
}
-
-]]>
+]]>unused
@@ -522,13 +497,12 @@
MINOR
- An empty static initializer was found. It is safe to remove it. Example:
+ An empty static initializer was found. It is safe to remove it. Example:
class MyClass {
static { }
}
-
-]]>
+]]>unused
@@ -538,8 +512,8 @@
MINOR
- This rule catches usages of java.lang.Integer.getInteger(String, ...) which reads an Integer from the System properties. It is often mistakenly used to attempt to read user input or parse a String into an Integer. It is a poor piece of API to use; replace it with System.properties['prop'].
-
Example of violations:
+ This rule catches usages of java.lang.Integer.getInteger(String, ...) which reads an Integer from the System properties. It is often mistakenly used to attempt to read user input or parse a String into an Integer. It is a poor piece of API to use; replace it with System.properties['prop'].
+
Example of violations:
// violations
Integer.getInteger(value)
@@ -548,8 +522,7 @@
// zero or more than 2 parameters is OK, must be different method
Integer.getInteger()
Integer.getInteger(value, radix, locale)
-
-]]>
+]]>bug
@@ -559,8 +532,8 @@
MINOR
- A literal is created with duplicated key. The map entry will be overwritten.
-
Example of violations:
+ A Map literal is created with duplicated key. The map entry will be overwritten.
+
-]]>
+]]>bug
@@ -581,8 +553,8 @@
MINOR
- A literal is created with duplicate constant value. A set cannot contain two elements with the same value.
-
Example of violations:
+ A Set literal is created with duplicate constant value. A set cannot contain two elements with the same value.
+
Example of violations:
def a = [1, 2, 2, 4] as Set
def b = [1, 2, 2, 4] as HashSet
@@ -597,8 +569,7 @@
def a = [1, 2, 3, 4] as Set
def b = ['1', '2', '3', '4'] as Set
def c = [1, '1'] as Set
-
-]]>
+]]>bug
@@ -608,8 +579,8 @@
MINOR
- The class has an equals method, but the parameter of the method is not of type Object. It is not overriding equals but instead overloading it.
-
Example of violations:
+ The class has an equals method, but the parameter of the method is not of type Object. It is not overriding equals but instead overloading it.
+
Example of violations:
class Object1 {
//parameter should be Object not String
@@ -644,8 +615,7 @@
class Object7 {
boolean equals(other) { true }
}
-
-]]>
+]]>pitfall
@@ -655,11 +625,11 @@
MAJOR
- A for loop without an init and update statement can be simplified to a while loop.
-
Example of violations:
+ A for loop without an init and update statement can be simplified to a while loop.
+
Example of violations:
int i = 0;
- for(; i < 5;) { // Violation
+ for(; i < 5;) { // Violation
println i++
}
@@ -667,18 +637,17 @@
for(i in [1,2]) // OK
println i
- for(int i = 0; i<5;) // OK
+ for(int i = 0; i<5;) // OK
println i++
int i = 0;
- for(; i < 5; i++) // OK
+ for(; i < 5; i++) // OK
println i
for (Plan p : plans) { // OK
println "Plan=$p"
}
-
-]]>
+]]>clumsy
@@ -688,16 +657,15 @@
MINOR
- Using Class.forName(...) is a common way to add dynamic behavior to a system. However, using this method can cause resource leaks because the classes can be pinned in memory for long periods of time. If you're forced to do dynamic class loading then use ClassLoader.loadClass instead. All variations of the Class.forName(...) method suffer from the same problem.
-
- Example of violations:
+ Using Class.forName(...) is a common way to add dynamic behavior to a system. However, using this method can cause resource leaks because the classes can be pinned in memory for long periods of time. If you're forced to do dynamic class loading then use ClassLoader.loadClass instead. All variations of the Class.forName(...) method suffer from the same problem.
+
-]]>
+]]>leakowasp-a1
@@ -708,24 +676,23 @@
MINOR
- Checks for expressions where a or equals() or compareTo() is used to compare two constants to each other or two literals that contain only constant values.
-
Here are examples of code that produces a violation:
+ Checks for expressions where a comparison operator or equals() or compareTo() is used to compare two constants to each other or two literals that contain only constant values.
+
Here are examples of code that produces a violation:
-]]>
+]]>bug
@@ -735,20 +702,19 @@
MINOR
- Checks for expressions where a or equals() or compareTo() is used to compare a variable to itself, e.g.: x == x, x != x, x \<=\> x, x \< x, x \>= x, x.equals(x) or x.compareTo(x), where x is a variable.
-
Here are examples of code that produces a violation:
+ Checks for expressions where a comparison operator or equals() or compareTo() is used to compare a variable to itself, e.g.: x == x, x != x, x <=> x, x < x, x >= x, x.equals(x) or x.compareTo(x), where x is a variable.
+
Here are examples of code that produces a violation:
-]]>
+]]>bug
@@ -758,13 +724,12 @@
MINOR
- Checks for bitwise operations in conditionals. For instance, the condition if (a | b) is almost always a mistake and should be if (a || b). If you need to do a bitwise operation then it is best practice to extract a temp variable.
-
Example of violations:
+ Checks for bitwise operations in conditionals. For instance, the condition if (a | b) is almost always a mistake and should be if (a || b). If you need to do a bitwise operation then it is best practice to extract a temp variable.
+
Example of violations:
if (a | b) { }
- if (a & b) { }
-
-]]>
+ if (a & b) { }
+]]>bug
@@ -774,14 +739,13 @@
MINOR
- This rule finds usages of a Windows file separator within the constructor call of a File object. It is better to use the Unix file separator or use the File.separator constant.
-
Example of violations:
+ This rule finds usages of a Windows file separator within the constructor call of a File object. It is better to use the Unix file separator or use the File.separator constant.
+
Example of violations:
new File('.\\foo\\')
new File('c:\\dir')
new File('../foo\\')
-
-]]>
+]]>pitfall
@@ -791,8 +755,8 @@
MINOR
- The Math.random() method returns a double result greater than or equal to 0.0 and less than 1.0. If you coerce this result into an Integer, Long, int, or long then it is coerced to zero. Casting the result to int, or assigning it to an int field is probably a bug.
-
Example of violations:
+ The Math.random() method returns a double result greater than or equal to 0.0 and less than 1.0. If you coerce this result into an Integer, Long, int, or long then it is coerced to zero. Casting the result to int, or assigning it to an int field is probably a bug.
+
Example of violations:
(int) Math.random()
(Integer) Math.random()
@@ -802,8 +766,7 @@
Integer m() { Math.random() }
(Math.random()) as int
(Math.random()) as Integer
-
-]]>
+]]>bug
@@ -813,14 +776,13 @@
MINOR
- This rule find cases where a File object is constructed with a windows-based path. This is not portable across operating systems or different machines, and using the File.listRoots() method is a better alternative.
-
Example of violations:
+ This rule find cases where a File object is constructed with a windows-based path. This is not portable across operating systems or different machines, and using the File.listRoots() method is a better alternative.
+
Example of violations:
new File('c:\\')
new File('c:\\dir')
new File('E:\\dir')
-
-]]>
+]]>pitfall
@@ -830,18 +792,17 @@
MINOR
- Checks for statements within a block. An can throw an exception, hiding the original exception, if there is one.
-
Here is an example of code that produces a violation:
+ Checks for assert statements within a finally block. An assert can throw an exception, hiding the original exception, if there is one.
+
Here is an example of code that produces a violation:
-]]>
+]]>error-handling
@@ -851,7 +812,7 @@
MAJOR
- Checks for statements with a constant value for the boolean expression, such as true, false, null, or a literal constant value. These statements will always pass or always fail, depending on the constant/literal value. Examples of violations include:
+ Checks for assert statements with a constant value for the assert boolean expression, such as true, false, null, or a literal constant value. These assert statements will always pass or always fail, depending on the constant/literal value. Examples of violations include:
-]]>
+]]>bug
@@ -901,9 +860,8 @@
MINOR
- Reports classes without methods, fields or properties. Why would you need a class like this?
-
This rule ignores interfaces, abstract classes, enums, anonymous inner classes, subclasses (extends), and classes with annotations.
- ]]>
+ Reports classes without methods, fields or properties. Why would you need a class like this?
+
This rule ignores interfaces, abstract classes, enums, anonymous inner classes, subclasses (extends), and classes with annotations.
]]>unused
@@ -913,16 +871,15 @@
MINOR
- Checks for multiple consecutive unary operators. These are confusing, and are likely typos and bugs.
-
Example of violations:
+ Checks for multiple consecutive unary operators. These are confusing, and are likely typos and bugs.
+
Example of violations:
int z = ~~2 // violation
boolean b = !!true // violation
boolean c = !!!false // 2 violations
int j = -~7 // violation
int k = +~8 // violation
-
-]]>
+]]>bug
@@ -933,8 +890,7 @@
MINOR
- Checks that statements use braces, even for a single statement.
- ]]>
+ Checks that if statements use braces, even for a single statement.]]>bug
@@ -943,13 +899,12 @@
MINOR
- Checks that blocks use braces, even for a single statement.
-
By default, braces are not required for an if it is followed immediately by an . Set the property to true to require braces is that situation as well.
- ]]>
+ Checks that else blocks use braces, even for a single statement.
+
By default, braces are not required for an else if it is followed immediately by an if. Set the bracesRequiredForElseIf property to true to require braces is that situation as well.
]]>bugbracesRequiredForElseIf
- block followed immediately by an statement. ]]>
+ false
@@ -959,8 +914,7 @@
MINOR
- Checks that statements use braces, even for a single statement.
- ]]>
+ Checks that for statements use braces, even for a single statement.]]>bug
@@ -969,8 +923,7 @@
MINOR
- Checks that while statements use braces, even for a single statement.
-]]>
+ Checks that while statements use braces, even for a single statement.]]>bug
@@ -981,10 +934,10 @@
MINOR
- This rule reports occurrences of nested synchronized statements.
-
Nested synchronized statements should be avoided. Nested synchronized statements are either useless (if the lock objects are identical) or prone to deadlock.
-
Note that a or an carries its own context (scope). A synchronized statement within a or an defined within an outer synchronized statement does not cause a violation (though nested synchronized statements within either of those will).
-
Here is an example of code that produces a violation:
+ This rule reports occurrences of nested synchronized statements.
+
Nested synchronized statements should be avoided. Nested synchronized statements are either useless (if the lock objects are identical) or prone to deadlock.
+
Note that a closure or an anonymous inner class carries its own context (scope). A synchronized statement within a closure or an anonymous inner class defined within an outer synchronized statement does not cause a violation (though nested synchronized statements within either of those will).
+
Here is an example of code that produces a violation:
-]]>
+]]>multi-threading
@@ -1004,14 +956,13 @@
MINOR
- This rule reports uses of the synchronized keyword on methods. Synchronized methods are the same as synchronizing on 'this', which effectively make your synchronization policy public and modifiable by other objects. To avoid possibilities of deadlock, it is better to synchronize on internal objects.
-
Here is an example of code that produces a violation:
+ This rule reports uses of the synchronized keyword on methods. Synchronized methods are the same as synchronizing on 'this', which effectively make your synchronization policy public and modifiable by other objects. To avoid possibilities of deadlock, it is better to synchronize on internal objects.
+
Here is an example of code that produces a violation:
synchronized def myMethod() {
// do stuff ...
}
-
-]]>
+]]>multi-threading
@@ -1020,16 +971,15 @@
MINOR
- This rule reports uses of the synchronized blocks where the synchronization reference is 'this'. Doing this effectively makes your synchronization policy public and modifiable by other objects. To avoid possibilities of deadlock, it is better to synchronize on internal objects.
-
Here is an example of code that produces a violation:
+ This rule reports uses of the synchronized blocks where the synchronization reference is 'this'. Doing this effectively makes your synchronization policy public and modifiable by other objects. To avoid possibilities of deadlock, it is better to synchronize on internal objects.
+
Here is an example of code that produces a violation:
-]]>
+]]>multi-threading
@@ -1038,15 +988,14 @@
MINOR
- This rule reports uses of the System.runFinalizersOnExit() method.
-
Method calls to System.runFinalizersOnExit() should not be allowed. This method is inherently non-thread-safe, may result in data corruption, deadlock, and may affect parts of the program far removed from it's call point. It is deprecated, and it's use strongly discouraged.
-
Here is an example of code that produces a violation:
+ This rule reports uses of the System.runFinalizersOnExit() method.
+
Method calls to System.runFinalizersOnExit() should not be allowed. This method is inherently non-thread-safe, may result in data corruption, deadlock, and may affect parts of the program far removed from it's call point. It is deprecated, and it's use strongly discouraged.
+
Here is an example of code that produces a violation:
-]]>
+]]>multi-threading
@@ -1055,15 +1004,14 @@
MINOR
- Avoid using ThreadGroup; although it is intended to be used in a threaded environment it contains methods that are not thread safe.
-
Here is an example of code that produces a violation:
+ Avoid using ThreadGroup; although it is intended to be used in a threaded environment it contains methods that are not thread safe.
+
Here is an example of code that produces a violation:
new ThreadGroup("...")
new ThreadGroup(tg, "my thread group")
Thread.currentThread().getThreadGroup()
System.getSecurityManager().getThreadGroup()
-
-]]>
+]]>multi-threading
@@ -1072,16 +1020,15 @@
MINOR
- This rule reports definition of the ThreadLocal fields that are not static and final.
-
fields should be static and final. In the most common case a java.lang.ThreadLocal instance associates state with a thread. A non-static non-finaljava.lang.ThreadLocal field associates state with an instance-thread combination. This is seldom necessary and often a bug which can cause memory leaks and possibly incorrect behavior.
-
Here is an example of code that produces a violation:
+ This rule reports definition of the ThreadLocal fields that are not static and final.
+
ThreadLocal fields should be static and final. In the most common case a java.lang.ThreadLocal instance associates state with a thread. A non-static non-finaljava.lang.ThreadLocal field associates state with an instance-thread combination. This is seldom necessary and often a bug which can cause memory leaks and possibly incorrect behavior.
+
Here is an example of code that produces a violation:
private static ThreadLocal local1 = new ThreadLocal()
private final ThreadLocal local2 = new ThreadLocal()
protected ThreadLocal local3 = new ThreadLocal()
ThreadLocal local4 = new ThreadLocal()
-
-]]>
+]]>multi-threading
@@ -1090,15 +1037,14 @@
MINOR
- This rule reports uses of the Thread.yield() method.
-
Method calls to Thread.yield() should not be allowed. This method has no useful guaranteed semantics, and is often used by inexperienced programmers to mask race conditions.
-
Here is an example of code that produces a violation:
+ This rule reports uses of the Thread.yield() method.
+
Method calls to Thread.yield() should not be allowed. This method has no useful guaranteed semantics, and is often used by inexperienced programmers to mask race conditions.
+
Here is an example of code that produces a violation:
def method() {
Thread.yield()
}
-
-]]>
+]]>multi-threading
@@ -1107,16 +1053,15 @@
MINOR
- This rule reports on long or double fields that are declared volatile.
-
Long or double fields should not be declared as volatile. Java specifies that reads and writes from such fields are atomic, but many JVM's have violated this specification. Unless you are certain of your JVM, it is better to synchronize access to such fields rather than declare them volatile. This rule flags fields marked volatile when their type is double or long or the name of their type is "Double" or "Long".
-
Here is an example of code that produces a violation:
+ This rule reports on long or double fields that are declared volatile.
+
Long or double fields should not be declared as volatile. Java specifies that reads and writes from such fields are atomic, but many JVM's have violated this specification. Unless you are certain of your JVM, it is better to synchronize access to such fields rather than declare them volatile. This rule flags fields marked volatile when their type is double or long or the name of their type is "Double" or "Long".
+
Here is an example of code that produces a violation:
def method() {
private volatile double d
private volatile long f
}
-
-]]>
+]]>multi-threading
@@ -1126,8 +1071,7 @@
MINOR
- Checks for synchronization on getClass() rather than class literal. This instance method synchronizes on this.getClass(). If this class is subclassed, subclasses will synchronize on the class object for the subclass, which isn't likely what was intended.
- ]]>
+ Checks for synchronization on getClass() rather than class literal. This instance method synchronizes on this.getClass(). If this class is subclassed, subclasses will synchronize on the class object for the subclass, which isn't likely what was intended.]]>multi-threading
@@ -1137,9 +1081,8 @@
MINOR
- Checks for code that calls notify() rather than notifyAll(). Java monitors are often used for multiple conditions. Calling notify() only wakes up one thread, meaning that the awakened thread might not be the one waiting for the condition that the caller just satisfied.
-
- ]]>
+ Checks for code that calls notify() rather than notifyAll(). Java monitors are often used for multiple conditions. Calling notify() only wakes up one thread, meaning that the awakened thread might not be the one waiting for the condition that the caller just satisfied.
+
]]>multi-threading
@@ -1149,8 +1092,8 @@
MINOR
- Busy waiting (forcing a Thread.sleep() while waiting on a condition) should be avoided. Prefer using the gate and barrier objects in the java.util.concurrent package.
-
Example of violations:
+ Busy waiting (forcing a Thread.sleep() while waiting on a condition) should be avoided. Prefer using the gate and barrier objects in the java.util.concurrent package.
+
-]]>
+]]>multi-threading
@@ -1183,9 +1125,9 @@
MINOR
- This rule detects double checked locking, where a 'lock hint' is tested for null before initializing an object within a synchronized block. Double checked locking does not guarantee correctness and is an anti-pattern.
-
+ This rule detects double checked locking, where a 'lock hint' is tested for null before initializing an object within a synchronized block. Double checked locking does not guarantee correctness and is an anti-pattern.
+
-]]>
+]]>multi-threading
@@ -1227,8 +1168,8 @@
MINOR
- Class contains similarly-named get and set methods where one method of the pair is marked either @WithReadLock or @WithWriteLock and the other is not locked at all. This may result in incorrect behavior at runtime, as callers of the get and set methods will not necessarily lock correctly and my see an inconsistent state for the object. The get and set method should both be guarded by @WithReadLock/@WithWriteLock or neither should be guarded.
-
Example of violations:
+ Class contains similarly-named get and set methods where one method of the pair is marked either @WithReadLock or @WithWriteLock and the other is not locked at all. This may result in incorrect behavior at runtime, as callers of the get and set methods will not necessarily lock correctly and my see an inconsistent state for the object. The get and set method should both be guarded by @WithReadLock/@WithWriteLock or neither should be guarded.
+
Example of violations:
class Person {
String name
@@ -1271,8 +1212,7 @@
parent
}
}
-
-]]>
+]]>multi-threading
@@ -1282,8 +1222,8 @@
MINOR
- Class contains similarly-named get and set methods where the set method is synchronized and the get method is not, or the get method is synchronized and the set method is not. This may result in incorrect behavior at runtime, as callers of the get and set methods will not necessarily see a consistent state for the object. The get and set method should both be synchronized or neither should be synchronized.
-
Example of violations:
+ Class contains similarly-named get and set methods where the set method is synchronized and the get method is not, or the get method is synchronized and the set method is not. This may result in incorrect behavior at runtime, as callers of the get and set methods will not necessarily see a consistent state for the object. The get and set method should both be synchronized or neither should be synchronized.
+
Example of violations:
class Person {
String name
@@ -1333,8 +1273,7 @@
weight = value
}
}
-
-]]>
+]]>multi-threading
@@ -1344,9 +1283,9 @@
MINOR
- Calendar objects should not be used as static fields. Calendars are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application. Under 1.4 problems seem to surface less often than under Java 5 where you will probably see random ArrayIndexOutOfBoundsException or IndexOutOfBoundsException in sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(). You may also experience serialization problems. Using an instance field or a ThreadLocal is recommended.
-
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
-
Examples:
+ Calendar objects should not be used as static fields. Calendars are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application. Under 1.4 problems seem to surface less often than under Java 5 where you will probably see random ArrayIndexOutOfBoundsException or IndexOutOfBoundsException in sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(). You may also experience serialization problems. Using an instance field or a ThreadLocal is recommended.
+
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
+
Examples:
// Violations
class MyClass {
@@ -1362,10 +1301,9 @@
// These usages are OK
class MyCorrectClass {
private final Calendar calendar1
- static ThreadLocal calendar2
+ static ThreadLocal<Calendar> calendar2
}
-
-]]>
+]]>multi-threading
@@ -1375,9 +1313,9 @@
MINOR
- DateFormat objects should not be used as static fields. DateFormats are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application. Under 1.4 problems seem to surface less often than under Java 5 where you will probably see random ArrayIndexOutOfBoundsException or IndexOutOfBoundsException in sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(). You may also experience serialization problems. Using an instance field or a ThreadLocal is recommended.
-
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
-
Examples:
+ DateFormat objects should not be used as static fields. DateFormats are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application. Under 1.4 problems seem to surface less often than under Java 5 where you will probably see random ArrayIndexOutOfBoundsException or IndexOutOfBoundsException in sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(). You may also experience serialization problems. Using an instance field or a ThreadLocal is recommended.
+
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
+
Examples:
// Violations
class MyClass {
@@ -1400,10 +1338,9 @@
// These usages are OK
class MyCorrectClass {
private DateFormat calendar1
- static ThreadLocal calendar2
+ static ThreadLocal<DateFormat> calendar2
}
-
-]]>
+]]>multi-threading
@@ -1413,8 +1350,8 @@
MINOR
- Matcher objects should not be used as static fields. Calendars are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application.
-
Example of violations:
+ Matcher objects should not be used as static fields. Calendars are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application.
+
Example of violations:
// two violations
class MyClass {
@@ -1425,10 +1362,9 @@
// these usages are OK
class MyCorrectClass {
private Matcher matcher1
- static ThreadLocal matcher2
+ static ThreadLocal<Matcher> matcher2
}
-
-]]>
+]]>multi-threading
@@ -1438,8 +1374,8 @@
MINOR
- The code synchronizes on a boxed primitive constant, such as an Integer. Since Integer objects can be cached and shared, this code could be synchronizing on the same object as other, unrelated code, leading to unresponsiveness and possible deadlock.
-
Example of violations:
+ The code synchronizes on a boxed primitive constant, such as an Integer. Since Integer objects can be cached and shared, this code could be synchronizing on the same object as other, unrelated code, leading to unresponsiveness and possible deadlock.
+
-]]>
+]]>multi-threading
@@ -1614,9 +1549,9 @@
MINOR
- Synchronization on a String field can lead to deadlock. Constant Strings are interned and shared across all other classes loaded by the JVM. Thus, this could is locking on something that other code might also be locking. This could result in very strange and hard to diagnose blocking and deadlock behavior.
-
+ Synchronization on a String field can lead to deadlock. Constant Strings are interned and shared across all other classes loaded by the JVM. Thus, this could is locking on something that other code might also be locking. This could result in very strange and hard to diagnose blocking and deadlock behavior.
+
-]]>
+]]>multi-threading
@@ -1688,8 +1622,8 @@
MINOR
- Catches Serializable classes that define a synchronized readObject method. By definition, an object created by deserialization is only reachable by one thread, and thus there is no need for readObject() to be synchronized. If the readObject() method itself is causing the object to become visible to another thread, that is an example of very dubious coding style.
-
Examples:
+ Catches Serializable classes that define a synchronized readObject method. By definition, an object created by deserialization is only reachable by one thread, and thus there is no need for readObject() to be synchronized. If the readObject() method itself is causing the object to become visible to another thread, that is an example of very dubious coding style.
+
-]]>
+]]>multi-threading
@@ -1740,9 +1673,9 @@
MINOR
- Synchronizing on a ReentrantLock field is almost never the intended usage. A ReentrantLock should be obtained using the lock() method and released in a finally block using the unlock() method.
-
+ Synchronizing on a ReentrantLock field is almost never the intended usage. A ReentrantLock should be obtained using the lock() method and released in a finally block using the unlock() method.
+
import java.util.concurrent.locks.ReentrantLock;
final lock = new ReentrantLock();
@@ -1817,8 +1750,7 @@
}
}
}
-
-]]>
+]]>multi-threading
@@ -1828,17 +1760,16 @@
MINOR
- Volatile array fields are unsafe because the contents of the array are not treated as volatile. Changing the entire array reference is visible to other threads, but changing an array element is not.
-
+ Volatile array fields are unsafe because the contents of the array are not treated as volatile. Changing the entire array reference is visible to other threads, but changing an array element is not.
+
class MyClass {
private volatile Object[] field1 = value()
volatile field2 = value as Object[]
volatile field3 = (Object[])foo
}
-
-]]>
+]]>multi-threading
@@ -1848,9 +1779,9 @@
MINOR
- Calls to Object.wait() must be within a while loop. This ensures that the awaited condition has not already been satisfied by another thread before the wait() is invoked. It also ensures that the proper thread was resumed and guards against incorrect notification. See [1] and [3].
-
As a more modern and flexible alternative, consider using the Java instead of wait() and notify(). See discussion in [2].
-
Example of violation:
+ Calls to Object.wait() must be within a while loop. This ensures that the awaited condition has not already been satisfied by another thread before the wait() is invoked. It also ensures that the proper thread was resumed and guards against incorrect notification. See [1] and [3].
+
As a more modern and flexible alternative, consider using the Java concurrency utilities instead of wait() and notify(). See discussion in Effective Java [2].
+
Example of violation:
class MyClass {
private data
@@ -1878,8 +1809,7 @@
}
}
}
-
-]]>
+]]>multi-threading
@@ -1889,10 +1819,14 @@
MINOR
- Creates violations when a java.sql.Connection object is used as a static field. Database connections stored in static fields will be shared between threads, which is unsafe and can lead to race conditions.
-
A transactional resource object such as database connection can only be associated with one transaction at a time. For this reason, a connection should not be shared between threads and should not be stored in a static field. See Section 4.2.3 of the for more details.
-
References:
-]]>
+ Creates violations when a java.sql.Connection object is used as a static field. Database connections stored in static fields will be shared between threads, which is unsafe and can lead to race conditions.
+
A transactional resource object such as database connection can only be associated with one transaction at a time. For this reason, a connection should not be shared between threads and should not be stored in a static field. See Section 4.2.3 of the J2EE Specification for more details.
+
References:
+
* Standards Mapping - Security Technical Implementation Guide Version 3 - (STIG 3) APP3630.1 CAT II
+
* Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 362, CWE ID 567
+
* Standards Mapping - SANS Top 25 2009 - (SANS 2009) Insecure Interaction - CWE ID 362
+
* Standards Mapping - SANS Top 25 2010 - (SANS 2010) Insecure Interaction - CWE ID 362
+
* Java 2 Platform Enterprise Edition Specification, v1.4 Sun Microsystems
]]>multi-threading
@@ -1902,9 +1836,9 @@
MINOR
- SimpleDateFormat objects should not be used as static fields. SimpleDateFormats are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application. Under 1.4 problems seem to surface less often than under Java 5 where you will probably see random ArrayIndexOutOfBoundsException or IndexOutOfBoundsException in sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(). You may also experience serialization problems. Using an instance field or a ThreadLocal is recommended.
-
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
-
Examples:
+ SimpleDateFormat objects should not be used as static fields. SimpleDateFormats are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application. Under 1.4 problems seem to surface less often than under Java 5 where you will probably see random ArrayIndexOutOfBoundsException or IndexOutOfBoundsException in sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(). You may also experience serialization problems. Using an instance field or a ThreadLocal is recommended.
+
For more information on this see Sun Bug #6231579 and Sun Bug #6178997.
+
Examples:
// Violations
class MyClass {
@@ -1921,10 +1855,9 @@
// These usages are OK
class MyCorrectClass {
private SimpleDateFormat calendar1
- static ThreadLocal calendar2
+ static ThreadLocal<SimpleDateFormat> calendar2
}
-
-]]>
+]]>multi-threading
@@ -1934,8 +1867,8 @@
MINOR
- Reports constructors passing the 'this' reference to other methods. This equals exposing a half-baked objects and can lead to race conditions during initialization. For reference, see Java Concurrency in Practice by Alex Miller and Java theory and practice: Safe construction techniques by Brian Goetz.
-
class EventListener {
EventListener(EventPublisher publisher) {
@@ -1944,8 +1877,7 @@
new AnotherWorkThread(listener: this)
}
}
-
-]]>
+]]>multi-threading
@@ -1957,8 +1889,7 @@
MAJOR
- An inverted statement is one in which there is a single if statement with a single else branch and the boolean test of the if is negated. For instance if (!x) false else true. It is usually clearer to write this as if (x) true else false.
- ]]>
+ An inverted if-else statement is one in which there is a single if statement with a single else branch and the boolean test of the if is negated. For instance if (!x) false else true. It is usually clearer to write this as if (x) true else false.]]>bug
@@ -1968,8 +1899,8 @@
MAJOR
- In a ternary expression avoid negation in the test. For example, rephrase: (x != y) ? diff : same as: (x == y) ? same : diff. Consistent use of this rule makes the code easier to read. Also, this resolves trivial ordering problems, such as "does the error case go first?" or "does the common case go first?".
-
Example:
+ In a ternary expression avoid negation in the test. For example, rephrase: (x != y) ? diff : same as: (x == y) ? same : diff. Consistent use of this rule makes the code easier to read. Also, this resolves trivial ordering problems, such as "does the error case go first?" or "does the common case go first?".
+
Example:
(x != y) ? diff : same // triggers violation
(!x) ? diff : same // triggers violation
@@ -1985,8 +1916,7 @@
// this is OK, because of GroovyTruth there is no inverse of != false
(x != false) ? diff : same
-
-]]>
+]]>bug
@@ -1996,8 +1926,8 @@
MAJOR
- Catch an if block that could be written as an elvis expression.
-
Example of violations:
+ Catch an if block that could be written as an elvis expression.
+
Example of violations:
if (!x) { // violation
x = 'some value'
@@ -2011,8 +1941,7 @@
}
x ?: 'some value' // OK
-
-]]>
+]]>bug
@@ -2022,13 +1951,12 @@
MINOR
- In Java and Groovy, you can specify long literals with the L or l character, for instance 55L or 24l. It is best practice to always use an uppercase L and never a lowercase l. This is because 11l rendered in some fonts may look like 111 instead of 11L.
-
Example of violations:
+ In Java and Groovy, you can specify long literals with the L or l character, for instance 55L or 24l. It is best practice to always use an uppercase L and never a lowercase l. This is because 11l rendered in some fonts may look like 111 instead of 11L.
+
Example of violations:
def x = 1l
def y = 55l
-
-]]>
+]]>bug
@@ -2038,19 +1966,18 @@
MAJOR
- Checks for a method or closure parameter being reassigned to a new value within the body of the method/closure, which is a confusing and questionable practice. Use a temporary variable instead.
-
Example of violations:
+ Checks for a method or closure parameter being reassigned to a new value within the body of the method/closure, which is a confusing and questionable practice. Use a temporary variable instead.
+
Example of violations:
void myMethod(int a, String b) {
println a
b = 'new value' // violation
}
- def myClosure1 = { int a, b ->
+ def myClosure1 = { int a, b ->
a = 123 // violation
}
-
-]]>
+]]>bug
@@ -2060,8 +1987,8 @@
MAJOR
- Checks for ternary expressions where the and expressions are the same. These can be simplified to an expression.
-
Example of violations:
+ Checks for ternary expressions where the boolean and true expressions are the same. These can be simplified to an Elvis expression.
+
Example of violations:
x ? x : false // violation; can simplify to x ?: false
@@ -2079,8 +2006,7 @@
foo() ? foo(99) : 123 // OK
foo(x) ? foo() : 123 // OK
foo(1) ? foo(2) : 123 // OK
-
-]]>
+]]>bug
@@ -2090,12 +2016,11 @@
MINOR
- Checks for references to the () obsolete java.util.Vector class. Use the Java Collections Framework classes instead, including ArrayList or Collections.synchronizedList(). See the JDK javadoc.
-
Example of violations:
+ Checks for references to the (effectively) obsolete java.util.Vector class. Use the Java Collections Framework classes instead, including ArrayList or Collections.synchronizedList(). See the JDK javadoc.
+
Example of violations:
def myList = new Vector() // violation
-
-]]>
+]]>bug
@@ -2105,12 +2030,11 @@
MINOR
- Checks for references to the () obsolete java.util.Hashtable class. Use the Java Collections Framework classes instead, including HashMap or ConcurrentHashMap. See the JDK javadoc.
-
Example of violations:
+ Checks for references to the (effectively) obsolete java.util.Hashtable class. Use the Java Collections Framework classes instead, including HashMap or ConcurrentHashMap. See the JDK javadoc.
+
* An if statement where both the if and else blocks contain only a single return statement returning a constant or literal value.
+
* A block where the second-to-last statement in a block is an if statement with no else, where the block contains a single return statement, and the last statement in the block is a return statement, and both return statements return a constant or literal value. This check is disabled by setting checkLastStatementImplicitElse to false.
]]>bug
@@ -2131,13 +2072,12 @@
MAJOR
- Do not allow using the def keyword in code. Use a specific type instead.
-
NOTE: This rule applies to the text contents of a rather than a specific , so it does not support the and configuration properties.
-]]>
+ Do not allow using the def keyword in code. Use a specific type instead.
+
NOTE: This rule applies to the text contents of a file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>bugexcludeRegex
-
+
@@ -2147,8 +2087,8 @@
MAJOR
- Check whether list and map literals contain optional trailing comma. Rationale: Putting this comma in make is easier to change the order of the elements or add new elements on the end.
-
This is valid code:
+ Check whether list and map literals contain optional trailing comma. Rationale: Putting this comma in make is easier to change the order of the elements or add new elements on the end.
+
This is valid code:
int[] array1 = [] // one line declaration
int[] array2 = [ // empty list
@@ -2163,17 +2103,16 @@
int[] array2 = [1,
2 // there is no trailing comma
]
-
-]]>
+]]>bugcheckList
-
+ truecheckMap
-
+ true
@@ -2184,8 +2123,7 @@
MAJOR
- Checks that all source files do not contain the tab character.
-]]>
+ Checks that all source files do not contain the tab character.]]>bug
@@ -2196,14 +2134,13 @@
MINOR
- Checks for classes that implement the java.lang.Cloneable interface without implementing the clone() method.
-
Here is an example of code that produces a violation:
+ Checks for classes that implement the java.lang.Cloneable interface without implementing the clone() method.
+
Here is an example of code that produces a violation:
class BadClass implements Cloneable {
def someMethod()
}
-
-]]>
+]]>design
@@ -2212,8 +2149,55 @@
MINOR
- Checks for use of the following concrete classes when specifying the type of a method parameter, closure parameter, constructor parameter, method return type or field type. The corresponding interfaces should be used to specify the type instead.
-]]>
+ Checks for use of the following concrete classes when specifying the type of a method parameter, closure parameter, constructor parameter, method return type or field type. The corresponding interfaces should be used to specify the type instead.
+
* java.util.ArrayList
+
* java.util.GregorianCalendar
+
* java.util.HashMap
+
* java.util.HashSet
+
* java.util.Hashtable
+
* java.util.LinkedHashMap
+
* java.util.LinkedHashSet
+
* java.util.LinkedList
+
* java.util.TreeMap
+
* java.util.TreeSet
+
* java.util.Vector
+
* java.util.concurrent.ArrayBlockingQueue
+
* java.util.concurrent.ConcurrentHashMap
+
* java.util.concurrent.ConcurrentLinkedQueue
+
* java.util.concurrent.CopyOnWriteArrayList
+
* java.util.concurrent.CopyOnWriteArraySet
+
* java.util.concurrent.DelayQueue
+
* java.util.concurrent.LinkedBlockingQueue
+
* java.util.concurrent.PriorityBlockingQueue
+
* java.util.concurrent.PriorityQueue
+
* java.util.concurrent.SynchronousQueue
+
Here are examples of code that produces violations:
]]>design
@@ -2223,8 +2207,7 @@
MINOR
- Checks for a method with Boolean return type that returns an explicit null. A method that returns either Boolean.TRUE, Boolean.FALSE or null is an accident waiting to happen. This method can be invoked as though it returned a value of type boolean, and the compiler will insert automatic of the Boolean value. If a null value is returned, this will result in a NullPointerException.
- ]]>
+ Checks for a method with Boolean return type that returns an explicit null. A method that returns either Boolean.TRUE, Boolean.FALSE or null is an accident waiting to happen. This method can be invoked as though it returned a value of type boolean, and the compiler will insert automatic unboxing of the Boolean value. If a null value is returned, this will result in a NullPointerException.]]>design
@@ -2234,8 +2217,7 @@
MINOR
- If you have a method or closure that returns an array, then when there are no results return a zero-length (empty) array rather than null. It is often a better design to return a zero-length array rather than a null reference to indicate that there are no results (i.e., an list of results). This way, no explicit check for null is needed by clients of the method.
- ]]>
+ If you have a method or closure that returns an array, then when there are no results return a zero-length (empty) array rather than null. It is often a better design to return a zero-length array rather than a null reference to indicate that there are no results (i.e., an empty list of results). This way, no explicit check for null is needed by clients of the method.]]>design
@@ -2245,8 +2227,7 @@
MINOR
- If you have a method or closure that returns a collection, then when there are no results return a zero-length (empty) collection rather than null. It is often a better design to return a zero-length collection rather than a null reference to indicate that there are no results (i.e., an list of results). This way, no explicit check for null is needed by clients of the method.
- ]]>
+ If you have a method or closure that returns a collection, then when there are no results return a zero-length (empty) collection rather than null. It is often a better design to return a zero-length collection rather than a null reference to indicate that there are no results (i.e., an empty list of results). This way, no explicit check for null is needed by clients of the method.]]>design
@@ -2256,14 +2237,13 @@
MINOR
- If you implement a compareTo method then you should also implement the Comparable interface. If you don't then you could possibly get an exception if the Groovy == operator is invoked on your object. This is an issue fixed in Groovy 1.8 but present in previous versions.
-
Here is an example of code that produces a violation:
+ If you implement a compareTo method then you should also implement the Comparable interface. If you don't then you could possibly get an exception if the Groovy == operator is invoked on your object. This is an issue fixed in Groovy 1.8 but present in previous versions.
+
Here is an example of code that produces a violation:
class BadClass {
int compareTo(Object o) { ... }
}
-
-]]>
+]]>design
@@ -2273,7 +2253,7 @@
MINOR
- Be sure to specify a Locale when creating a new instance of SimpleDateFormat; the class is locale-sensitive. If you instantiate SimpleDateFormat without a Locale parameter, it will format the date and time according to the default Locale. Both the pattern and the Locale determine the format. For the same pattern, SimpleDateFormat may format a date and time differently if the Locale varies.
+ Be sure to specify a Locale when creating a new instance of SimpleDateFormat; the class is locale-sensitive. If you instantiate SimpleDateFormat without a Locale parameter, it will format the date and time according to the default Locale. Both the pattern and the Locale determine the format. For the same pattern, SimpleDateFormat may format a date and time differently if the Locale varies.
// violation, missing locale
new SimpleDateFormat('pattern')
@@ -2283,8 +2263,7 @@
// OK, includes a variable that perhaps is a locale
new SimpleDateFormat('pattern', locale)
-
-]]>
+]]>design
@@ -2294,8 +2273,8 @@
MINOR
- The abstract class does not contain any abstract methods. An abstract class suggests an incomplete implementation, which is to be completed by subclasses implementing the abstract methods. If the class is intended to be used as a base class only (not to be instantiated directly) a protected constructor can be provided prevent direct instantiation.
-
Example:
+ The abstract class does not contain any abstract methods. An abstract class suggests an incomplete implementation, which is to be completed by subclasses implementing the abstract methods. If the class is intended to be used as a base class only (not to be instantiated directly) a protected constructor can be provided prevent direct instantiation.
+
Example:
public abstract class MyBaseClass {
void method1() { }
@@ -2311,8 +2290,7 @@
abstract class MyClass extends BaseParent{
// OK because parent is named Base.*
}
-
-]]>
+]]>design
@@ -2322,8 +2300,7 @@
MINOR
- If a class defines a "void close()" then that class should implement java.io.Closeable.
- ]]>
+ If a class defines a "void close()" then that class should implement java.io.Closeable.]]>design
@@ -2333,14 +2310,13 @@
MINOR
- An interface should be used only to model a behaviour of a class: using an interface as a container of constants is a poor usage pattern. Example:
+ An interface should be used only to model a behaviour of a class: using an interface as a container of constants is a poor usage pattern. Example:
public interface ConstantsInterface {
public static final int CONSTANT_1 = 0
public static final String CONSTANT_2 = "1"
}
-
-]]>
+]]>design
@@ -2350,7 +2326,7 @@
MINOR
- An empty method in an abstract class should be abstract instead, as developer may rely on this empty implementation rather than code the appropriate one.
+ An empty method in an abstract class should be abstract instead, as developer may rely on this empty implementation rather than code the appropriate one.
abstract class MyClass {
def couldBeAbstract_1() {
@@ -2361,8 +2337,7 @@
// Should be abstract method
}
}
-
-]]>
+]]>design
@@ -2372,8 +2347,7 @@
MINOR
- This rule finds classes marked final that contain protected members. If a class is final then it may not be subclassed, and there is therefore no point in having a member with protected visibility. Either the class should not be final or the member should be private or protected.
- ]]>
+ This rule finds classes marked final that contain protected members. If a class is final then it may not be subclassed, and there is therefore no point in having a member with protected visibility. Either the class should not be final or the member should be private or protected.]]>design
@@ -2383,14 +2357,13 @@
MINOR
- Using public fields is considered to be a bad design. Use properties instead.
-
Example of violations:
+ Using public fields is considered to be a bad design. Use properties instead.
+
Example of violations:
class Person {
public String name
}
-
-]]>
+]]>design
@@ -2400,9 +2373,9 @@
MINOR
- There is no point in creating a stateless Singleton because there is nothing within the class that needs guarding and no side effects to calling the constructor. Just create new instances of the object or write a Utility class with static methods. In the long term, Singletons can cause strong coupling and hard to change systems.
-
If the class has any fields at all, other than a self reference, then it is not considered stateless. A self reference is a field of the same type as the enclosing type, or a field named instance or _instance. The field name self reference is a property named instanceRegex that defaults to the value 'instance|_instance'
-
Example of violations:
+ There is no point in creating a stateless Singleton because there is nothing within the class that needs guarding and no side effects to calling the constructor. Just create new instances of the object or write a Utility class with static methods. In the long term, Singletons can cause strong coupling and hard to change systems.
+
If the class has any fields at all, other than a self reference, then it is not considered stateless. A self reference is a field of the same type as the enclosing type, or a field named instance or _instance. The field name self reference is a property named instanceRegex that defaults to the value 'instance|_instance'
+
Example of violations:
@groovy.lang.Singleton
class Service {
@@ -2423,8 +2396,7 @@
void processItem(item){
}
}
-
-]]>
+]]>design
@@ -2434,14 +2406,13 @@
MINOR
- Checks for abstract classes that define a public constructor, which is useless and confusing.
-
The following code produces a violation:
+ Checks for abstract classes that define a public constructor, which is useless and confusing.
+
The following code produces a violation:
abstract class MyClass {
MyClass() { }
}
-
-]]>
+]]>design
@@ -2451,9 +2422,9 @@
MINOR
- A builder method is defined as one that creates objects. As such, they should never be of void return type. If a method is named build, create, or make, then it should always return a value.
-
This rule has one property: methodNameRegex. The default value is (make.*|create.*|build.*). Update this property if you have some other naming convention for your builder methods.
-
Example of violations:
+ A builder method is defined as one that creates objects. As such, they should never be of void return type. If a method is named build, create, or make, then it should always return a value.
+
This rule has one property: methodNameRegex. The default value is (make.*|create.*|build.*). Update this property if you have some other naming convention for your builder methods.
-]]>
+]]>design
@@ -2478,16 +2448,15 @@
MAJOR
- This rule finds private fields that are only set within a or . Such fields can safely be made final.
-]]>
+ This rule finds private fields that are only set within a constructor or field initializer. Such fields can safely be made final.]]>designignoreFieldNames
-
+ ignoreJpaEntities
-
+ false
@@ -2498,16 +2467,15 @@
MINOR
- The method clone() should only be declared if the class implements the Cloneable interface.
-
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
-
Example of violations:
+ The method clone() should only be declared if the class implements the Cloneable interface.
+
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
+
Example of violations:
class ValueClass {
ValueClass clone() {
}
}
-
-]]>
+]]>design
@@ -2517,17 +2485,16 @@
MINOR
- Checks for calls to Locale.setDefault(), or Locale.default = Xxx, which sets the Locale across the entire JVM. That can impact other applications on the same web server, for instance.
-
From the java.util.Locale javadoc for setDefault: should only be used if the caller is prepared to reinitialize locale-sensitive code running within the same Java Virtual Machine.>
-
Example of violations:
+ Checks for calls to Locale.setDefault(), or Locale.default = Xxx, which sets the Locale across the entire JVM. That can impact other applications on the same web server, for instance.
+
From the java.util.Locale javadoc for setDefault: should only be used if the caller is prepared to reinitialize locale-sensitive code running within the same Java Virtual Machine.
-]]>
+]]>design
@@ -2537,8 +2504,8 @@
MINOR
- Checks for toString() methods that return null. This is unconventional and could cause unexpected NullPointerExceptions from normal or implicit use of toString().
-
Example of violations:
+ Checks for toString() methods that return null. This is unconventional and could cause unexpected NullPointerExceptions from normal or implicit use of toString().
+
-]]>
+]]>design
@@ -2572,23 +2538,22 @@
MINOR
- Checks for use of the instanceof operator. Prefer using instead.
-
Use the ignoreTypeNames property to configure ignored type names (the class name specified as the right-hand expression of the instanceof). It defaults to ignoring instanceof checks against exception classes.
-
Here are a couple references that discuss the problems with using instanceof and the preference for using instead:
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
-
Example of violations:
+ Checks for use of the instanceof operator. Prefer using polymorphism instead.
+
Use the ignoreTypeNames property to configure ignored type names (the class name specified as the right-hand expression of the instanceof). It defaults to ignoring instanceof checks against exception classes.
+
Here are a couple references that discuss the problems with using instanceof and the preference for using polymorphism instead:
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
Example of violations:
class MyClass {
boolean isRunnable = this instanceof Runnable // violation
}
-
-]]>
+]]>designignoreTypeNames
-
+ *Exceptions
@@ -2599,33 +2564,32 @@
MAJOR
- Reports classes with nested for loops.
-
Example of violations:
+ Reports classes with nested for loops.
+
Example of violations:
-for (int i = 0; i < 100; ++i) {
- for (int j = 0; j < 100; ++j) { // violation
+for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) { // violation
println i + j
}
}
-for (int i = 0; i < 100; ++i) {
- for (int j = 0; j < 100; ++j) { // violation
+for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) { // violation
println i + j
}
- for (int j = 0; j < 100; ++j) { // violation
+ for (int j = 0; j < 100; ++j) { // violation
println i + j
}
}
-for (int i = 0; i < 100; ++i) {
- for (int j = 0; j < 100; ++j) { // violation
- for (int k = 0; k < 100; ++k) { // violation
+for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) { // violation
+ for (int k = 0; k < 100; ++k) { // violation
println i + j + k
}
}
}
-
-]]>
+]]>design
@@ -2635,9 +2599,9 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for assignment to a static field from an instance method.
-
Influenced by the AssignmentToNonFinalStatic rule from PMD, and the ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD rule from FindBugs.
-
Example of violations:
+ Checks for assignment to a static field from an instance method.
+
Influenced by the AssignmentToNonFinalStatic rule from PMD, and the ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD rule from FindBugs.
+
Example of violations:
class MyClass {
private static field1
@@ -2655,8 +2619,7 @@ for (int i = 0; i < 100; ++i) {
final NAME = 'martin' // no violation; local var hides static field
}
}
-
-]]>
+]]>design
@@ -2668,14 +2631,15 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for duplicate number literals within the current class.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
- ]]>
+ This rule checks for duplicate number literals within the current class.
+
Code containing duplicate Number literals can usually be improved by declaring the Number as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+ * This rule does not search across several files at once, only in the current file, and only within the current class.
+
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateNumberLiteral') annotation.
]]>bugignoreNumbers
-
+ 0,1
@@ -2686,14 +2650,15 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for duplicate String literals within the current class.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
- ]]>
+ This rule checks for duplicate String literals within the current class.
+
Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+ * This rule does not search across several files at once, only in the current file, and only within the current class.
+
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateStringLiteral') annotation.
]]>bugignoreStrings
-
+ '' (empty string)
@@ -2704,10 +2669,10 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- This rule checks for duplicate literals within the current class. This rule only checks for s where the keys and values are all constants or literals.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
-
Examples of violations:
+ This rule checks for duplicate Map literals within the current class. This rule only checks for Maps where the keys and values are all constants or literals.
+
Code containing duplicate Map literals can usually be improved by declaring the Map as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
Examples of violations:
def var1 = [a:1, b:null, c:Boolean.FALSE, d:'x', e:true]
def var2 = [a:1, b:null, c:Boolean.FALSE, d:'x', e:true] // violation
@@ -2731,8 +2696,7 @@ for (int i = 0; i < 100; ++i) {
def var1 = [a:7+5]
def var2 = [a:7+5] // not a violation; contains a non-constant/literal expression
-
-]]>
+]]>bug
@@ -2742,10 +2706,10 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- This rule checks for duplicate literals within the current class. This rule only checks for s where values are all constants or literals.
-
Code containing duplicate literals can usually be improved by declaring the as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
-
Examples of violations:
+ This rule checks for duplicate List literals within the current class. This rule only checks for Lists where values are all constants or literals.
+
Code containing duplicate List literals can usually be improved by declaring the List as a constant field.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
Examples of violations:
def var1 = [1, null, Boolean.FALSE, 'x', true]
def var2 = [1, null, Boolean.FALSE, 'x', true] // violation
@@ -2763,8 +2727,7 @@ for (int i = 0; i < 100; ++i) {
def var1 = [1, 7+5]
def var2 = [1, 7+5] // not a violation; contains a non-constant/literal expression
-
-]]>
+]]>bug
@@ -2775,8 +2738,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a Error. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.
- ]]>
+ Checks for catching a Error. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.]]>error-handling
@@ -2785,8 +2747,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a Exception. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.
- ]]>
+ Checks for catching a Exception. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.]]>error-handling
@@ -2795,8 +2756,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a NullPointerException. Catching NullPointerException is never appropriate. It should be avoided in the first place with proper null checking, and it can mask underlying errors.
- ]]>
+ Checks for catching a NullPointerException. Catching NullPointerException is never appropriate. It should be avoided in the first place with proper null checking, and it can mask underlying errors.]]>error-handling
@@ -2805,8 +2765,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a RuntimeException. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.
- ]]>
+ Checks for catching a RuntimeException. In most cases that is too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.]]>error-handling
@@ -2815,8 +2774,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a Throwable. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.
- ]]>
+ Checks for catching a Throwable. In most cases that is much too broad, and is also dangerous because it can catch exceptions such as ThreadDeath and OutOfMemoryError.]]>error-handling
@@ -2825,8 +2783,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for throwing an instance of java.lang.Error. This is not appropriate within normal application code. Throw an instance of a more specific exception subclass instead.
- ]]>
+ Checks for throwing an instance of java.lang.Error. This is not appropriate within normal application code. Throw an instance of a more specific exception subclass instead.]]>error-handling
@@ -2835,8 +2792,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for throwing an instance of java.lang.Exception. Throw an instance of a more specific exception subclass instead.
- ]]>
+ Checks for throwing an instance of java.lang.Exception. Throw an instance of a more specific exception subclass instead.]]>error-handling
@@ -2845,8 +2801,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for throwing an instance of java.lang.NullPointerException. Applications should never throw a NullPointerException.
- ]]>
+ Checks for throwing an instance of java.lang.NullPointerException. Applications should never throw a NullPointerException.]]>error-handling
@@ -2855,8 +2810,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for throwing an instance of java.lang.RuntimeException. Throw an instance of a more specific exception subclass instead.
- ]]>
+ Checks for throwing an instance of java.lang.RuntimeException. Throw an instance of a more specific exception subclass instead.]]>error-handling
@@ -2865,8 +2819,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for throwing an instance of java.lang.Throwable. Throw an instance of a more specific exception subclass instead.
-]]>
+ Checks for throwing an instance of java.lang.Throwable. Throw an instance of a more specific exception subclass instead.]]>error-handling
@@ -2876,8 +2829,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Dubious catching of IllegalMonitorStateException. IllegalMonitorStateException is generally only thrown in case of a design flaw in your code (calling wait or notify on an object you do not hold a lock on).
- ]]>
+ Dubious catching of IllegalMonitorStateException. IllegalMonitorStateException is generally only thrown in case of a design flaw in your code (calling wait or notify on an object you do not hold a lock on).]]>error-handling
@@ -2887,8 +2839,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This class is not derived from another exception, but ends with 'Exception'. This will be confusing to users of this class.
- ]]>
+ This class is not derived from another exception, but ends with 'Exception'. This will be confusing to users of this class.]]>error-handling
@@ -2898,8 +2849,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Returning null from a catch block often masks errors and requires the client to handle error codes. In some coding styles this is discouraged. This rule ignores methods with void return type.
- ]]>
+ Returning null from a catch block often masks errors and requires the client to handle error codes. In some coding styles this is discouraged. This rule ignores methods with void return type.]]>error-handling
@@ -2909,8 +2859,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a ArrayIndexOutOfBoundsException. Catching ArrayIndexOutOfBoundsException should be avoided in the first place by checking the array size before accessing an array element. Catching the exception may mask underlying errors.
- ]]>
+ Checks for catching a ArrayIndexOutOfBoundsException. Catching ArrayIndexOutOfBoundsException should be avoided in the first place by checking the array size before accessing an array element. Catching the exception may mask underlying errors.]]>error-handling
@@ -2920,8 +2869,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for catching a IndexOutOfBoundsException. Catching IndexOutOfBoundsException should be avoided in the first place by checking for a valid index before accessing an indexed element. Catching the exception may mask underlying errors.
- ]]>
+ Checks for catching a IndexOutOfBoundsException. Catching IndexOutOfBoundsException should be avoided in the first place by checking for a valid index before accessing an indexed element. Catching the exception may mask underlying errors.]]>error-handling
@@ -2931,8 +2879,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- A common Groovy mistake when throwing exceptions is to forget the new keyword. For instance, throw RuntimeException() instead of throw new RuntimeException(). If the error path is not unit tested then the production system will throw a Method Missing exception and hide the root cause. This rule finds constructs like throw RuntimeException() that look like a new keyword was meant to be used but forgotten.
-
The following code will all cause violations:
+ A common Groovy mistake when throwing exceptions is to forget the new keyword. For instance, throw RuntimeException() instead of throw new RuntimeException(). If the error path is not unit tested then the production system will throw a Method Missing exception and hide the root cause. This rule finds constructs like throw RuntimeException() that look like a new keyword was meant to be used but forgotten.
+
The following code will all cause violations:
throw RuntimeException() // ends in Exceptions, first letter Capitalized
throw RuntimeFailure() // ends in Failure, first letter Capitalized
@@ -2941,8 +2889,7 @@ for (int i = 0; i < 100; ++i) {
throw new RuntimeException()
throw runtimeFailure() // first letter lowercase, assumed to be method call
-
-]]>
+]]>error-handling
@@ -2952,15 +2899,14 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Errors are system exceptions. Do not extend them.
-
Examples:
+ Errors are system exceptions. Do not extend them.
+
Examples:
class MyError extends Error { } // violation
class MyError extends java.lang.Error { } // violation
class MyException extends Exception { } // OK
-
-]]>
+]]>error-handling
@@ -2971,15 +2917,14 @@ for (int i = 0; i < 100; ++i) {
Detects code that catches java.lang.ThreadDeath without re-throwing it.
-
-]]>
+]]>
error-handling
@@ -2989,8 +2934,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for an exception constructor call without a throw as the last statement within a catch block. This rule treats any constructor call for a class named Exception as an exception constructor call.
-
Example of violations:
+ Checks for an exception constructor call without a throw as the last statement within a catch block. This rule treats any constructor call for a class named xxxException as an exception constructor call.
+
Example of violations:
void execute() {
try { } catch(Exception e) { new Exception(e) } // violation
@@ -3008,8 +2953,7 @@ for (int i = 0; i < 100; ++i) {
try {
doStuff()
} catch(Exception e) { throw new DaoException(e) } // ok
-
-]]>
+]]>error-handling
@@ -3019,12 +2963,11 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for classes that extend Throwable. Custom exception classes should subclass Exception or one of its descendants.
-
Example of violations:
+ Checks for classes that extend Throwable. Custom exception classes should subclass Exception or one of its descendants.
+
Example of violations:
class MyException extends Throwable { } // violation
-
-]]>
+]]>error-handling
@@ -3036,9 +2979,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks the location of the opening brace (\{) for classes. By default, requires them on the same line, but the sameLine property can be set to false to override this.
-
NOTE: This rule ignores annotation types, e.g. @interface MyAnnotation {}.
- ]]>
+ Checks the location of the opening brace (\{) for classes. By default, requires them on the same line, but the sameLine property can be set to false to override this.
+
NOTE: This rule ignores annotation types, e.g. @interface MyAnnotation {}.
]]>conventionsameLine
@@ -3052,27 +2994,26 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks the maximum length for each line of source code. It checks for number of characters, so lines that include tabs may appear longer than the allowed number when viewing the file. The maximum line length can be configured by setting the length property, which defaults to 120.
-
NOTE: This rule does not support the @SuppressAnnotations annotation or the classname-based rule properties (applyToClassNames, doNotApplyToClassNames) to enable/disable the rule. If you want to specify or restrict where this rule is applied, you must use the file-based rule properties: applyToFileNames, doNotApplyToFileNames, applyToFilesMatching and doNotApplyToFilesMatching.
- ]]>
+ Checks the maximum length for each line of source code. It checks for number of characters, so lines that include tabs may appear longer than the allowed number when viewing the file. The maximum line length can be configured by setting the length property, which defaults to 120.
+
NOTE: This rule does not support the @SuppressAnnotations annotation or the classname-based rule properties (applyToClassNames, doNotApplyToClassNames) to enable/disable the rule. If you want to specify or restrict where this rule is applied, you must use the file-based rule properties: applyToFileNames, doNotApplyToFileNames, applyToFilesMatching and doNotApplyToFilesMatching.
]]>conventionignoreImportStatements
-
+ trueignoreLineRegex
-
+ ignorePackageStatements
-
+ truelength
-
+ 120
@@ -3083,8 +3024,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks the location of the opening brace (\{) for for loops. By default, requires them on the same line, but the sameLine property can be set to false to override this.
- ]]>
+ Checks the location of the opening brace (\{) for for loops. By default, requires them on the same line, but the sameLine property can be set to false to override this.]]>conventionsameLine
@@ -3098,27 +3038,26 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks the location of the opening brace (\{) for if statements. By default, requires them on the same line, but the sameLine property can be set to false to override this.
-]]>
+ Checks the location of the opening brace (\{) for if statements. By default, requires them on the same line, but the sameLine property can be set to false to override this.]]>conventionelseOnSameLineAsClosingBrace
-
+ trueelseOnSameLineAsOpeningBrace
-
+ truesameLine
-
+ truevalidateElse
-
+ false
@@ -3129,8 +3068,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks the location of the opening brace (\{) for constructors and methods. By default, requires them on the same line, but the sameLine property can be set to false to override this.
- ]]>
+ Checks the location of the opening brace (\{) for constructors and methods. By default, requires them on the same line, but the sameLine property can be set to false to override this.]]>conventionsameLine
@@ -3144,8 +3082,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks the location of the opening brace (\{) for try statements. By default, requires them on the line, but the sameLine property can be set to false to override this.
- ]]>
+ Checks the location of the opening brace (\{) for try statements. By default, requires them on the line, but the sameLine property can be set to false to override this.]]>conventionsameLine
@@ -3159,8 +3096,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.
- ]]>
+ Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.]]>convention
@@ -3170,9 +3106,21 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks that there is at least one space or whitespace following each comma. That includes checks for method and closure declaration parameter lists, method call parameter lists, Map literals and List literals.
-
Known limitations:
-]]>
+ Checks that there is at least one space or whitespace following each comma. That includes checks for method and closure declaration parameter lists, method call parameter lists, Map literals and List literals.
+
Known limitations:
+
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
+ Examples of violations:
+
+ def value = calculate(1,399, 'abc') // violation on parameter 399
+
+ def method1(int a,String b) { } // violation on parameter b
+
+ def closure1 = { int a,String b -> } // violation on parameter b
+
+ def list1 = [a,b, c] // violation on list element b
+
+ def map1 = [a:1,b:2, c:3] // violation on map element b:2
+
]]>convention
@@ -3182,8 +3130,20 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is at least one space (blank) or whitespace following a semicolon that separates:
-]]>
+ Check that there is at least one space (blank) or whitespace following a semicolon that separates:
+
* multiple statements on a single line
+
* the clauses within a classic for loop, e.g. for (i=0;i<10;i++)
]]>convention
@@ -3193,10 +3153,25 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is at least one space (blank) or whitespace around each binary operator, including: +, -, *, /, \>\>, \<\<, &&, ||, &, |, ?:, =, "as".
-
Do not check dot ('.') operator. Do not check unary operators (!, +, -, ++, --, ?.). Do not check array ('[') operator.
-
Known limitations:
-]]>
+ Check that there is at least one space (blank) or whitespace around each binary operator, including: +, -, *, /, >>, <<, &&, ||, &, |, ?:, =, "as".
+
Do not check dot ('.') operator. Do not check unary operators (!, +, -, ++, --, ?.). Do not check array ('[') operator.
+
Known limitations:
+
* Does not catch violations of missing space around equals operator (=) within a declaration expression, e.g. def x=23
+
* Does not catch violations of certain ternary expressions and standalone elvis operator (?:) expressions
]]>convention
@@ -3206,13 +3181,50 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is at least one space (blank) or whitespace before each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
-
Known limitations:
-]]>
+ Check that there is at least one space (blank) or whitespace before each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+
Known limitations:
+
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
]]>conventioncheckClosureMapEntryValue
-
+ true
@@ -3223,8 +3235,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is at least one space (blank) or whitespace after each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
- Examples of violations:
+ Check that there is at least one space (blank) or whitespace after each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+ Examples of violations:
class MyClass{int count } // violation
@@ -3239,7 +3251,7 @@ for (int i = 0; i < 100; ++i) {
if (ready) {
} else {println 99} // violation
- for (int i=0; i<10; i++) {println i } // violation
+ for (int i=0; i<10; i++) {println i } // violation
for (String name in names) {println name } // violation
@@ -3251,20 +3263,19 @@ for (int i = 0; i < 100; ++i) {
} catch(Exception e) {x=77 } // violation
} finally {println 'error' } // violation
- list.each {name -> } // violation
+ list.each {name -> } // violation
shouldFail(Exception) {doStuff() } // violation
-
-]]>
+]]>conventioncheckClosureMapEntryValue
-
+ trueignoreEmptyBlock
-
+ false
@@ -3275,14 +3286,26 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is at least one space (blank) or whitespace after each closing brace ("\{") for method/class/interface declarations, closure expressions and block statements.
-
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
- Known limitations:
-]]>
+ Check that there is at least one space (blank) or whitespace after each closing brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
+ Known limitations:
+
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
+ Examples of violations and exceptions:
+
+ if (ready) { return 9 }else { } // violation
+ try { doStuff() }finally { } // violation
+
+ def matching = list.find { it.isReady() }.filter() // no violation for dot operator
+ assert list.every { it.isReady() }, "Error" // no violation for comma
+ def m = [a:123, b:{ println 7 },c:99] // no violation for comma
+ processItems(list.select { it.isReady() }) // no violation for closing parenthesis
+ def names = records.findAll { it.age > 1 }*.name // no violation for spread operator
+ list?.collect { it?.type }?.join(',') // no violation for null-safe operator
+
]]>conventioncheckClosureMapEntryValue
-
+ true
@@ -3293,18 +3316,49 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is at least one space (blank) or whitespace before each closing brace ("\}") for method/class/interface declarations, closure expressions and block statements.
-
Known limitations:
-]]>
+ Check that there is at least one space (blank) or whitespace before each closing brace ("\}") for method/class/interface declarations, closure expressions and block statements.
+
Known limitations:
+
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
]]>conventioncheckClosureMapEntryValue
-
+ trueignoreEmptyBlock
-
+ false
@@ -3315,13 +3369,12 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is exactly one space (blank) after the if keyword and before the opening parenthesis.
-
Examples of violations:
+ Check that there is exactly one space (blank) after the if keyword and before the opening parenthesis.
+
-]]>
+]]>convention
@@ -3331,13 +3384,12 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is exactly one space (blank) after the while keyword and before the opening parenthesis.
-
Examples of violations:
+ Check that there is exactly one space (blank) after the while keyword and before the opening parenthesis.
+
-]]>
+]]>convention
@@ -3347,13 +3399,12 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is exactly one space (blank) after the for keyword and before the opening parenthesis.
-
Examples of violations:
+ Check that there is exactly one space (blank) after the for keyword and before the opening parenthesis.
+
Examples of violations:
for(name in names) { } // violation
- for (int i=0; i < 10; i++) { } // violation
-
-]]>
+ for (int i=0; i < 10; i++) { } // violation
+]]>convention
@@ -3363,8 +3414,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is exactly one space (blank) after the switch keyword and before the opening parenthesis.
-
Examples of violations:
+ Check that there is exactly one space (blank) after the switch keyword and before the opening parenthesis.
+
Examples of violations:
switch(x) { // violation
case 1: println 'one'
@@ -3372,8 +3423,7 @@ for (int i = 0; i < 100; ++i) {
switch (x) { // violation
case 1: println 'one'
}
-
-]]>
+]]>convention
@@ -3383,13 +3433,12 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check that there is exactly one space (blank) after the catch keyword and before the opening parenthesis.
-
Examples of violations:
+ Check that there is exactly one space (blank) after the catch keyword and before the opening parenthesis.
+
-]]>
+]]>convention
@@ -3399,9 +3448,17 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks that there is at least one space (blank) or whitespace around each closure arrow (->) symbol.
-
Known limitations:
-]]>
+ Checks that there is at least one space (blank) or whitespace around each closure arrow (->) symbol.
+
Known limitations:
+
* Does not catch violations if the closure arrow (->) is on a separate line from the start of the closure.
]]>convention
@@ -3411,23 +3468,22 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Check for proper formatting of whitespace around colons for literal Map entries. By default, no whitespace is allowed either before or after the Map entry colon, but you can change that through the configuration properties below.
-
Example of violations:
+ Check for proper formatting of whitespace around colons for literal Map entries. By default, no whitespace is allowed either before or after the Map entry colon, but you can change that through the configuration properties below.
+
Example of violations:
Map m1 = [myKey : 12345] // violation (both before and after the colon)
println [a :[1:11, 2:22], // violation on a (before colon)
b:[(Integer): 33]] // violation on Integer (after colon)
-
-]]>
+]]>conventioncharacterAfterColonRegex
- entry. For example, /\\S/ matches any non-whitespace character and /\\s/ matches any whitespace character (thus requiring a space or whitespace). ]]>
+ \\ScharacterBeforeColonRegex
- entry. For example, /\\S/ matches any non-whitespace character and /\\s/ matches any whitespace character (thus requiring a space or whitespace). ]]>
+ \\S
@@ -3438,14 +3494,13 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks for closure logic on first line (after -\) for a multi-line closure. That breaks the symmetry of indentation (if the subsequent statements are indented normally), and that first statement can be easily missed when reading the code.
-
Example of violations:
+ Checks for closure logic on first line (after ->) for a multi-line closure. That breaks the symmetry of indentation (if the subsequent statements are indented normally), and that first statement can be easily missed when reading the code.
+
Example of violations:
- def closure = { name -> println name
+ def closure = { name -> println name
addToCounts()
println “done” }
-
-]]>
+]]>convention
@@ -3455,8 +3510,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure there are no consecutive lines that are either blank or whitespace only. This reduces the need to scroll further than necessary when reading code, and increases the likelihood that a logical block of code will fit on one screen for easier comprehension.
-
Example of violation:
+ Makes sure there are no consecutive lines that are either blank or whitespace only. This reduces the need to scroll further than necessary when reading code, and increases the likelihood that a logical block of code will fit on one screen for easier comprehension.
+
Example of violation:
def name
@@ -3466,8 +3521,7 @@ for (int i = 0; i < 100; ++i) {
def id
-
-]]>
+]]>convention
@@ -3477,8 +3531,7 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure there are no blank lines before the package declaration of a source code file.
- ]]>
+ Makes sure there are no blank lines before the package declaration of a source code file.]]>convention
@@ -3488,8 +3541,7 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure each source file ends with a newline character.
- ]]>
+ Makes sure each source file ends with a newline character.]]>convention
@@ -3499,13 +3551,12 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure there is a blank line after the imports of a source code file.
-
Example of violation:
+ Makes sure there is a blank line after the imports of a source code file.
+
Example of violation:
import org.apache.commons.lang.StringUtils
class MyClass { } // violation
-
-]]>
+]]>convention
@@ -3515,8 +3566,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure there is a blank line after the package statement of a source code file.
-
Example of violation:
+ Makes sure there is a blank line after the package statement of a source code file.
+
Example of violation:
package org.codenarc
import java.util.Date // violation
@@ -3524,8 +3575,7 @@ for (int i = 0; i < 100; ++i) {
class MyClass {
void go() { /* ... */ }
}
-
-]]>
+]]>convention
@@ -3535,8 +3585,7 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks that no lines of source code end with whitespace characters.
-]]>
+ Checks that no lines of source code end with whitespace characters.]]>convention
@@ -3547,14 +3596,13 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks for a specified illegal regular expression within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
- ]]>
+ Checks for a specified illegal regular expression within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and regex, and (optionally) customized violationMessage and priority.
+
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>bugregex
-
+
@@ -3563,14 +3611,13 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks for a specified regular expression that must exist within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
- ]]>
+ Checks for a specified regular expression that must exist within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and regex, and (optionally) customized violationMessage and priority.
+
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>bugregex
-
+
@@ -3579,14 +3626,13 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks for a specified text string that must exist within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
- ]]>
+ Checks for a specified text string that must exist within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and string, and (optionally) customized violationMessage and priority.
+
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>bugstring
-
+
@@ -3595,29 +3641,28 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for non-final fields on a class. The intent of this rule is to check a configured set of classes that should remain "stateless" and reentrant. One example might be Grails service classes which are singletons, by default, and so they should be reentrant.
-
This rule ignores final fields (either instance or static). Fields that are static and non-final, however, do cause a violation.
This rule also ignores all fields annotated with the @Inject annotation.
-
You can configure this rule to ignore certain fields either by name or by type. This can be useful to ignore fields that hold references to (static) dependencies (such as DAOs or Service objects) or static configuration.
-
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
- [[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
-
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.
-
[[3]] At least one of the (standard) applyToClassNames, applyToFileNames or applyToFilesMatching properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule to apply to a specific set of classes or files.
-
[[4]] This rule will not catch violations of true / if you define a final field whose value is itself mutable, e.g. a final HashMap.
-]]>
+ Checks for non-final fields on a class. The intent of this rule is to check a configured set of classes that should remain "stateless" and reentrant. One example might be Grails service classes which are singletons, by default, and so they should be reentrant.
+
This rule ignores final fields (either instance or static). Fields that are static and non-final, however, do cause a violation.
This rule also ignores all fields annotated with the @Inject annotation.
+
You can configure this rule to ignore certain fields either by name or by type. This can be useful to ignore fields that hold references to (static) dependencies (such as DAOs or Service objects) or static configuration.
+
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
+ [[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
+
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.
+
[[3]] At least one of the (standard) applyToClassNames, applyToFileNames or applyToFilesMatching properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule to apply to a specific set of classes or files.
+
[[4]] This rule will not catch violations of true statelessness/reentrancy if you define a final field whose value is itself mutable, e.g. a final HashMap.
]]>bugaddToIgnoreFieldNames
-
+ ignoreFieldNames
-
+ ignoreFieldTypes
-
+
@@ -3627,10 +3672,10 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for reference to any of the packages configured in packageNames.
-
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
-
This rule can be useful for governance and enforcement of . For instance, making sure that view or model classes, for instance, do not contain references to JDBC-specific packages (e.g. java.sql and javax.sql).
-
Here is an example configuration of this rule used to ensure that JDBC packages/classes are only referenced within DAO classes:
+ Checks for reference to any of the packages configured in packageNames.
+
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
+
This rule can be useful for governance and enforcement of architectural layering. For instance, making sure that view or model classes, for instance, do not contain references to JDBC-specific packages (e.g. java.sql and javax.sql).
+
Here is an example configuration of this rule used to ensure that JDBC packages/classes are only referenced within DAO classes:
ruleset {
description "Example CodeNarc Ruleset"
@@ -3645,12 +3690,11 @@ for (int i = 0; i < 100; ++i) {
description = 'Reference to JDBC packages should be restricted to DAO classes.'
}
}
-
-]]>
+]]>bugpackageNames
-
+
@@ -3660,10 +3704,10 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for reference to any of the classes configured in classNames.
-
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
-
This rule can be useful for governance and enforcement of . For instance, making sure that view or model classes, for instance, do not contain references to DAO classes (e.g., *Dao).
-
Here is an example configuration of this rule used to ensure that DAO classes are not referenced from within model classes:
+ Checks for reference to any of the classes configured in classNames.
+
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
+
This rule can be useful for governance and enforcement of architectural layering. For instance, making sure that view or model classes, for instance, do not contain references to DAO classes (e.g., *Dao).
+
Here is an example configuration of this rule used to ensure that DAO classes are not referenced from within model classes:
ruleset {
description "Example CodeNarc Ruleset"
@@ -3678,12 +3722,11 @@ for (int i = 0; i < 100; ++i) {
description = 'Do not reference DAOs from model classes.'
}
}
-
-]]>
+]]>bugclassNames
-
+
@@ -3693,41 +3736,70 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for classes containing fields/properties/methods matching configured illegal member modifiers or not matching any of the configured allowed member modifiers.
-
Modifiers for fields and methods include:
-]]>
+ Checks for classes containing fields/properties/methods matching configured illegal member modifiers or not matching any of the configured allowed member modifiers.
+
Modifiers for fields and methods include:
+
* public
+
* protected
+
* private
+
* static
+
* final
+
* volatile (fields only)
+
* transient (fields only)
+
Modifiers for properties are only:
+
* static
+
* final
+
Note that you must use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
]]>bugallowedFieldModifiers
-
+ allowedMethodModifiers
-
+ allowedPropertyModifiers
-
+ ignoreMethodNames
-
+ ignoreMethodsWithAnnotationNames
-
+ illegalFieldModifiers
-
+ illegalMethodModifiers
-
+ illegalPropertyModifiers
-
+
@@ -3737,14 +3809,13 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for a specified illegal string within the source code.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
-
NOTE: This rule applies to the text contents of an entire rather than a specific , so it does not support the and configuration properties.
- ]]>
+ Checks for a specified illegal string within the source code.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and string, and (optionally) customized violationMessage and priority.
+
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>bugstring
-
+
@@ -3754,13 +3825,12 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for classes that extend one of the specified set of illegal superclasses.
-
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule and , and (optionally) customized and .
- ]]>
+ Checks for classes that extend one of the specified set of illegal superclasses.
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and string, and (optionally) customized violationMessage and priority.
]]>bugsuperclassNames
-
+
@@ -3771,15 +3841,14 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Rule that checks for public methods on Grails controller classes. Static methods are ignored.
-
Grails controller actions and interceptors are defined as properties on the controller class. Public methods on a controller class are unnecessary. They break encapsulation and can be confusing.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' folder. You can override this with a different regular expression value if appropriate.
-
This rule also sets the default value of applyToClassNames to only match class names ending in 'Controller'. You can override this with a different class name pattern (String with wildcards) if appropriate.
- ]]>
+ Rule that checks for public methods on Grails controller classes. Static methods are ignored.
+
Grails controller actions and interceptors are defined as properties on the controller class. Public methods on a controller class are unnecessary. They break encapsulation and can be confusing.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' folder. You can override this with a different regular expression value if appropriate.
+
This rule also sets the default value of applyToClassNames to only match class names ending in 'Controller'. You can override this with a different class name pattern (String with wildcards) if appropriate.
]]>grailsignoreMethodNames
-
+
@@ -3788,12 +3857,11 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Rule that checks for references to the session object from within Grails controller and taglib classes.
-
This rule is intended as a "governance" rule to enable monitoring and controlling access to the session from within application source code. Storing objects in the session may inhibit scalability and/or performance and should be carefully considered.
-
Note that this rule does not check for direct access to the session from within GSP (Groovy Server Pages) files.
-
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate session access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
- ]]>
+ Rule that checks for references to the session object from within Grails controller and taglib classes.
+
This rule is intended as a "governance" rule to enable monitoring and controlling access to the session from within application source code. Storing objects in the session may inhibit scalability and/or performance and should be carefully considered.
+
Note that this rule does not check for direct access to the session from within GSP (Groovy Server Pages) files.
+
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate session access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
]]>grails
@@ -3802,12 +3870,11 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Rule that checks for references to the servletContext object from within Grails controller and taglib classes.
-
This rule is intended as a "governance" rule to enable monitoring and controlling access to the servletContext from within application source code. Storing objects in the servletContext may inhibit scalability and/or performance and should be carefully considered. Furthermore, access to the servletContext is not synchronized, so reading/writing objects from the servletConext must be manually synchronized, as described in The Definitive Guide to Grails (2nd edition).
-
Note that this rule does not check for direct access to the servletContext from within GSP (Groovy Server Pages) files.
-
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate servletContext access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
- ]]>
+ Rule that checks for references to the servletContext object from within Grails controller and taglib classes.
+
This rule is intended as a "governance" rule to enable monitoring and controlling access to the servletContext from within application source code. Storing objects in the servletContext may inhibit scalability and/or performance and should be carefully considered. Furthermore, access to the servletContext is not synchronized, so reading/writing objects from the servletConext must be manually synchronized, as described in The Definitive Guide to Grails (2nd edition).
+
Note that this rule does not check for direct access to the servletContext from within GSP (Groovy Server Pages) files.
+
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate servletContext access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
]]>grails
@@ -3816,15 +3883,32 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for non-final fields on a Grails service class. Grails service classes are singletons by default, and so they should be reentrant. In most cases, this implies (or at least encourages) that they should be stateless.
-
This rule ignores (i.e., does not cause violations for) the following:
-]]>
+ Checks for non-final fields on a Grails service class. Grails service classes are singletons by default, and so they should be reentrant. In most cases, this implies (or at least encourages) that they should be stateless.
+
This rule ignores (i.e., does not cause violations for) the following:
+
* All final fields (either instance or static). Note that fields that are static and non-final, however, do cause a violation.
+
* Non-static properties (i.e., no visibility modifier specified) declared with def.
* All fields annotated with the @Inject annotation.
+
* All fields with names matching the ignoreFieldNames property.
+
* All fields with types matching the ignoreFieldTypes property.
+ The ignoreFieldNames property of this rule is preconfigured to ignore the standard Grails service configuration field names ('scope', 'transactional') and the standard injected bean names ('dataSource', 'sessionFactory'), as well as all other field names ending with 'Service'.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/services' folder. You can override this with a different regular expression value if appropriate.
+
This rule also sets the default value of applyToClassNames to only match class names ending in 'Service'. You can override this with a different class name pattern (String with wildcards) if appropriate.
+
[[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
+
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.]]>
grails
+
+ addToIgnoreFieldName
+
+
ignoreFieldNames
+
+ 'dataSource,scope,sessionFactory,ignoreFieldTypes
+
@@ -3834,10 +3918,9 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks that Grails domain classes redefine toString().
-
Ignores classes annotated with @ToString or @Canonical.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
Ignores classes annotated with @ToString or @Canonical.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
]]>grails
@@ -3847,10 +3930,9 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks that Grails domain classes redefine equals().
-
Ignores classes annotated with @EqualsAndHashCode or @Canonical.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
Ignores classes annotated with @EqualsAndHashCode or @Canonical.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
]]>grails
@@ -3860,9 +3942,9 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Check for duplicate name in a Grails domain class mapping. Duplicate names/entries are legal, but can be confusing and error-prone.
-
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
-
Example of violations:
+ Check for duplicate name in a Grails domain class mapping. Duplicate names/entries are legal, but can be confusing and error-prone.
+
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
+
Example of violations:
class Person {
String firstName
@@ -3876,8 +3958,7 @@ for (int i = 0; i < 100; ++i) {
table 'people2' // violation
}
}
-
-]]>
+]]>grails
@@ -3887,9 +3968,9 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Check for duplicate name in a Grails domain class constraints. Duplicate names/entries are legal, but can be confusing and error-prone.
-
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
-
Example of violations:
+ Check for duplicate name in a Grails domain class constraints. Duplicate names/entries are legal, but can be confusing and error-prone.
+
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
+
Example of violations:
class Person {
String firstName
@@ -3901,8 +3982,7 @@ for (int i = 0; i < 100; ++i) {
firstName nullable:false // violation
}
}
-
-]]>
+]]>grails
@@ -3912,17 +3992,16 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Forbids usage of SQL reserved keywords as class or field names in Grails domain classes. Naming a domain class (or its field) with such a keyword causes SQL schema creation errors and/or redundant table/column name mappings.
-
Note: due to limited type information available during CodeNarc's operation, this rule will report fields of type java.io.Serializable, but not of its implementations. Please specify any implementations used as domain properties in additionalHibernateBasicTypes.
-]]>
+ Forbids usage of SQL reserved keywords as class or field names in Grails domain classes. Naming a domain class (or its field) with such a keyword causes SQL schema creation errors and/or redundant table/column name mappings.
+
Note: due to limited type information available during CodeNarc's operation, this rule will report fields of type java.io.Serializable, but not of its implementations. Please specify any implementations used as domain properties in additionalHibernateBasicTypes.
]]>grailsadditionalHibernateBasicTypes
-
+ additionalReservedSqlKeywords
-
+
@@ -3932,9 +4011,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks that Grails Domain classes do not have Service classes injected.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
- ]]>
+ Checks that Grails Domain classes do not have Service classes injected.
+
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/domain' folder. You can override this with a different regular expression value if appropriate.
]]>grails
@@ -3944,8 +4022,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Untrusted input should not be allowed to set arbitrary object fields without restriction.
-
Example of violations:
+ Untrusted input should not be allowed to set arbitrary object fields without restriction.
+
Example of violations:
// Person would be a grails domain object
def person = new Person(params)
@@ -3955,8 +4033,7 @@ for (int i = 0; i < 100; ++i) {
def person = Person.get(1)
person.properties = params
person.save()
-
-]]>
+]]>grails
@@ -3968,8 +4045,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for explicit calls to the no-argument constructor of ArrayList. In Groovy, it is best to write new ArrayList() as [], which creates the same object.
- ]]>
+ This rule checks for explicit calls to the no-argument constructor of ArrayList. In Groovy, it is best to write new ArrayList() as [], which creates the same object.]]>groovyism
@@ -3979,9 +4055,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the and(Object) method is called directly in code instead of using the & operator. A groovier way to express this: a.and(b) is this: a & b. This rule can be configured to ignore this.and(Object) using the property. It defaults to , so even and(x) will not trigger a violation. The default is because and appears commonly in Grails criteria.
-
This rule also ignores all calls to super.and(Object).
- ]]>
+ This rule detects when the and(Object) method is called directly in code instead of using the & operator. A groovier way to express this: a.and(b) is this: a & b. This rule can be configured to ignore this.and(Object) using the ignoreThisReference property. It defaults to true, so even and(x) will not trigger a violation. The default is true because and appears commonly in Grails criteria.
+
This rule also ignores all calls to super.and(Object).
]]>groovyism
@@ -3991,16 +4066,15 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the compareTo(Object) method is called directly in code instead of using the \<\=\>, \>, \>\=, \<, and \<\= operators. A groovier way to express this: a.compareTo(b) is this: a \<\=\> b, or using the other operators. Here are some other ways to write groovier code:
+ This rule detects when the compareTo(Object) method is called directly in code instead of using the <=>, >, >=, <, and <= operators. A groovier way to express this: a.compareTo(b) is this: a <=> b, or using the other operators. Here are some other ways to write groovier code:
a.compareTo(b) == 0 // can be replaced by: a == b
- a.compareTo(b) // can be replaced by: a <=> b
- a.compareTo(b) > 0 // can be replaced by: a > b
- a.compareTo(b) >= 0 // can be replaced by: a >= b
- a.compareTo(b) < 0 // can be replaced by: a < b
- a.compareTo(b) <= 0 // can be replaced by: a <= b
-
-]]>
+ a.compareTo(b) // can be replaced by: a <=> b
+ a.compareTo(b) > 0 // can be replaced by: a > b
+ a.compareTo(b) >= 0 // can be replaced by: a >= b
+ a.compareTo(b) < 0 // can be replaced by: a < b
+ a.compareTo(b) <= 0 // can be replaced by: a <= b
+]]>groovyism
@@ -4010,9 +4084,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the div(Object) method is called directly in code instead of using the / operator. A groovier way to express this: a.div(b) is this: a / b. This rule can be configured to ignore div.xor(Object) using the property. It defaults to , so even div(x) will trigger a violation.
-
This rule also ignores all calls to super.div(Object).
- ]]>
+ This rule detects when the div(Object) method is called directly in code instead of using the / operator. A groovier way to express this: a.div(b) is this: a / b. This rule can be configured to ignore div.xor(Object) using the ignoreThisReference property. It defaults to false, so even div(x) will trigger a violation.
+
This rule also ignores all calls to super.div(Object).
]]>groovyism
@@ -4022,9 +4095,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the equals(Object) method is called directly in code instead of using the == or != operator. A groovier way to express this: a.equals(b) is this: a == b and a groovier way to express : !a.equals(b) is: a != b. This rule can be configured to ignore this.equals(Object) using the property. It defaults to , so even equals(x) will trigger a violation.
-
This rule also ignores all calls to super.equals(Object).
- ]]>
+ This rule detects when the equals(Object) method is called directly in code instead of using the == or != operator. A groovier way to express this: a.equals(b) is this: a == b and a groovier way to express : !a.equals(b) is: a != b. This rule can be configured to ignore this.equals(Object) using the ignoreThisReference property. It defaults to false, so even equals(x) will trigger a violation.
+
This rule also ignores all calls to super.equals(Object).
]]>groovyism
@@ -4034,9 +4106,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the getAt(Object) method is called directly in code instead of using the [] index operator. A groovier way to express this: a.getAt(b) is this: a[b]. This rule can be configured to ignore this.getAt(Object) using the property. It defaults to , so even getAt(x) will trigger a violation.
-
This rule also ignores all calls to super.getAt(Object).
- ]]>
+ This rule detects when the getAt(Object) method is called directly in code instead of using the [] index operator. A groovier way to express this: a.getAt(b) is this: a[b]. This rule can be configured to ignore this.getAt(Object) using the ignoreThisReference property. It defaults to false, so even getAt(x) will trigger a violation.
+
This rule also ignores all calls to super.getAt(Object).
]]>groovyism
@@ -4046,9 +4117,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the leftShift(Object) method is called directly in code instead of using the \<\< operator. A groovier way to express this: a.leftShift(b) is this: a \<\< b. This rule can be configured to ignore this.leftShift(Object) using the property. It defaults to , so even leftShift(x) will trigger a violation.
-
This rule also ignores all calls to super.leftShift(Object).
- ]]>
+ This rule detects when the leftShift(Object) method is called directly in code instead of using the << operator. A groovier way to express this: a.leftShift(b) is this: a << b. This rule can be configured to ignore this.leftShift(Object) using the ignoreThisReference property. It defaults to false, so even leftShift(x) will trigger a violation.
+
This rule also ignores all calls to super.leftShift(Object).
]]>groovyism
@@ -4058,9 +4128,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the minus(Object) method is called directly in code instead of using the - operator. A groovier way to express this: a.minus(b) is this: a - b. This rule can be configured to ignore minus.xor(Object) using the property. It defaults to , so even minus(x) will trigger a violation.
-
This rule also ignores all calls to super.minus(Object).
- ]]>
+ This rule detects when the minus(Object) method is called directly in code instead of using the -> operator. A groovier way to express this: a.minus(b) is this: a - b. This rule can be configured to ignore minus.xor(Object) using the ignoreThisReference property. It defaults to false, so even minus(x) will trigger a violation.
+
This rule also ignores all calls to super.minus(Object).
]]>groovyism
@@ -4070,9 +4139,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the multiply(Object) method is called directly in code instead of using the * operator. A groovier way to express this: a.multiply(b) is this: a * b. This rule can be configured to ignore this.multiply(Object) using the property. It defaults to , so even multiply(x) will trigger a violation.
-
This rule also ignores all calls to super.multiply(Object).
- ]]>
+ This rule detects when the multiply(Object) method is called directly in code instead of using the * operator. A groovier way to express this: a.multiply(b) is this: a * b. This rule can be configured to ignore this.multiply(Object) using the ignoreThisReference property. It defaults to false, so even multiply(x) will trigger a violation.
+
This rule also ignores all calls to super.multiply(Object).
]]>groovyism
@@ -4082,9 +4150,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the mod(Object) method is called directly in code instead of using the % operator. A groovier way to express this: a.mod(b) is this: a % b. This rule can be configured to ignore this.mod(Object) using the property. It defaults to , so even mod(x) will trigger a violation.
-
This rule also ignores all calls to super.mod(Object).
- ]]>
+ This rule detects when the mod(Object) method is called directly in code instead of using the % operator. A groovier way to express this: a.mod(b) is this: a % b. This rule can be configured to ignore this.mod(Object) using the ignoreThisReference property. It defaults to false, so even mod(x) will trigger a violation.
+
This rule also ignores all calls to super.mod(Object).
]]>groovyism
@@ -4094,9 +4161,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the or(Object) method is called directly in code instead of using the | operator. A groovier way to express this: a.or(b) is this: a | b. This rule can be configured to ignore this.or(Object) using the property. It defaults to , so even or(x) will not trigger a violation. This is the default because it is commonly used in Grails criteria.
-
This rule also ignores all calls to super.or(Object).
- ]]>
+ This rule detects when the or(Object) method is called directly in code instead of using the | operator. A groovier way to express this: a.or(b) is this: a | b. This rule can be configured to ignore this.or(Object) using the ignoreThisReference property. It defaults to true, so even or(x) will not trigger a violation. This is the default because it is commonly used in Grails criteria.
+
This rule also ignores all calls to super.or(Object).
]]>groovyism
@@ -4106,9 +4172,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the plus(Object) method is called directly in code instead of using the + operator. A groovier way to express this: a.plus(b) is this: a + b. This rule can be configured to ignore this.plus(Object) using the property. It defaults to , so even plus(x) will trigger a violation.
-
This rule also ignores all calls to super.plus(Object).
- ]]>
+ This rule detects when the plus(Object) method is called directly in code instead of using the + operator. A groovier way to express this: a.plus(b) is this: a + b. This rule can be configured to ignore this.plus(Object) using the ignoreThisReference property. It defaults to false, so even plus(x) will trigger a violation.
+
This rule also ignores all calls to super.plus(Object).
]]>groovyism
@@ -4118,9 +4183,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the power(Object) method is called directly in code instead of using the ** operator. A groovier way to express this: a.power(b) is this: a ** b. This rule can be configured to ignore this.power(Object) using the property. It defaults to , so even power(x) will trigger a violation.
-
This rule also ignores all calls to super.power(Object).
- ]]>
+ This rule detects when the power(Object) method is called directly in code instead of using the ** operator. A groovier way to express this: a.power(b) is this: a ** b. This rule can be configured to ignore this.power(Object) using the ignoreThisReference property. It defaults to false, so even power(x) will trigger a violation.
+
This rule also ignores all calls to super.power(Object).
]]>groovyism
@@ -4130,9 +4194,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the rightShift(Object) method is called directly in code instead of using the \>\> operator. A groovier way to express this: a.rightShift(b) is this: a \>\> b. This rule can be configured to ignore this.rightShift(Object) using the property. It defaults to , so even rightShift(x) will trigger a violation.
-
This rule also ignores all calls to super.rightShift(Object).
- ]]>
+ This rule detects when the rightShift(Object) method is called directly in code instead of using the >> operator. A groovier way to express this: a.rightShift(b) is this: a >> b. This rule can be configured to ignore this.rightShift(Object) using the ignoreThisReference property. It defaults to false, so even rightShift(x) will trigger a violation.
+
This rule also ignores all calls to super.rightShift(Object).
]]>groovyism
@@ -4142,9 +4205,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule detects when the xor(Object) method is called directly in code instead of using the ^ operator. A groovier way to express this: a.xor(b) is this: a ^ b. This rule can be configured to ignore this.xor(Object) using the property. It defaults to , so even xor(x) will trigger a violation.
-
This rule also ignores all calls to super.xor(Object).
- ]]>
+ This rule detects when the xor(Object) method is called directly in code instead of using the ^ operator. A groovier way to express this: a.xor(b) is this: a ^ b. This rule can be configured to ignore this.xor(Object) using the ignoreThisReference property. It defaults to false, so even xor(x) will trigger a violation.
+
This rule also ignores all calls to super.xor(Object).
]]>groovyism
@@ -4154,8 +4216,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for explicit calls to the no-argument constructor of HashMap. In Groovy, it is best to replace new HashMap() with [:], which creates (mostly) the same object. [:] is technically a LinkedHashMap but it is very rare that someone absolutely needs an instance of HashMap and not a subclass.
- ]]>
+ This rule checks for explicit calls to the no-argument constructor of HashMap. In Groovy, it is best to replace new HashMap() with [:], which creates (mostly) the same object. [:] is technically a LinkedHashMap but it is very rare that someone absolutely needs an instance of HashMap and not a subclass.]]>groovyism
@@ -4165,8 +4226,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for explicit calls to the no-argument constructor of HashSet. In Groovy, it is best to replace new HashSet() with [] as Set, which creates the same object.
- ]]>
+ This rule checks for explicit calls to the no-argument constructor of HashSet. In Groovy, it is best to replace new HashSet() with [] as Set, which creates the same object.]]>groovyism
@@ -4176,8 +4236,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for explicit calls to the no-argument constructor of LinkedList. In Groovy, it is best to replace new LinkedList() with [] as Queue, which creates the same object.
- ]]>
+ This rule checks for explicit calls to the no-argument constructor of LinkedList. In Groovy, it is best to replace new LinkedList() with [] as Queue, which creates the same object.]]>groovyism
@@ -4187,8 +4246,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for explicit calls to the no-argument constructor of Stack. In Groovy, it is best to replace new Stack() with [] as Stack, which creates the same object.
- ]]>
+ This rule checks for explicit calls to the no-argument constructor of Stack. In Groovy, it is best to replace new Stack() with [] as Stack, which creates the same object.]]>groovyism
@@ -4198,8 +4256,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for explicit calls to the no-argument constructor of TreeSet. In Groovy, it is best to replace new TreeSet() with [] as SortedSet, which creates the same object.
- ]]>
+ This rule checks for explicit calls to the no-argument constructor of TreeSet. In Groovy, it is best to replace new TreeSet() with [] as SortedSet, which creates the same object.]]>groovyism
@@ -4209,12 +4266,11 @@ for (int i = 0; i < 100; ++i) {
MINOR
- A GString should not be used as a map key since its is not guaranteed to be stable. Consider calling key.toString().
-
Here is an example of code that produces a violation:
+ A GString should not be used as a map key since its hashcode is not guaranteed to be stable. Consider calling key.toString().
+
Here is an example of code that produces a violation:
-]]>
+]]>groovyism
@@ -4224,8 +4280,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- The groovy.lang.Immutable annotation has been deprecated and replaced by groovy.transform.Immutable. Do not use the Immutable in groovy.lang.
-
Example of violations:
+ The groovy.lang.Immutable annotation has been deprecated and replaced by groovy.transform.Immutable. Do not use the Immutable in groovy.lang.
+
Example of violations:
@Immutable
class Person { }
@@ -4252,8 +4308,7 @@ for (int i = 0; i < 100; ++i) {
import groovy.transform.Immutable as Imtl
@Imtl
class Person { }
-
-]]>
+]]>groovyism
@@ -4263,8 +4318,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for the explicit instantiation of a LinkedHashMap using the no-arg constructor. In Groovy, it is best to replace new LinkedHashMap() with [:], which creates the same object.
- ]]>
+ This rule checks for the explicit instantiation of a LinkedHashMap using the no-arg constructor. In Groovy, it is best to replace new LinkedHashMap() with [:], which creates the same object.]]>groovyism
@@ -4274,16 +4328,15 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- If a method is called and the last parameter is an inline closure then it can be declared outside of the method call parentheses.
-
Example of violations:
+ If a method is called and the last parameter is an inline closure then it can be declared outside of the method call parentheses.
+
Example of violations:
// creates violation: poor Groovy style
[1,2,3].each({ println it })
// no violation
[1,2,3].each { println it }
-
-]]>
+]]>groovyism
@@ -4293,15 +4346,14 @@ for (int i = 0; i < 100; ++i) {
MINOR
- The Collections.unique() method mutates the list and returns the list as a value. If you are assigning the result of unique() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a unique() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
-
Example of violations:
+ The Collections.unique() method mutates the list and returns the list as a value. If you are assigning the result of unique() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a unique() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
+
Example of violations:
def a = myList.unique()
def b = myList.unique() { it }
- def c = myList.unique().findAll { x < 1 }
+ def c = myList.unique().findAll { x < 1 }
-
-]]>
+]]>groovyism
@@ -4311,14 +4363,13 @@ for (int i = 0; i < 100; ++i) {
MINOR
- The Collections.sort() method mutates the list and returns the list as a value. If you are assigning the result of sort() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a sort() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
-
Example of violations:
+ The Collections.sort() method mutates the list and returns the list as a value. If you are assigning the result of sort() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a sort() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
+
Example of violations:
def a = myList.sort()
def b = myList.sort() { it }
- def c = myList.sort().findAll { x < 1 }
-
-]]>
+ def c = myList.sort().findAll { x < 1 }
+]]>groovyism
@@ -4328,8 +4379,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Multiple return values can be used to set several variables at once. To use multiple return values, the left hand side of the assignment must be enclosed in parenthesis. If not, then you are not using multiple return values, you're only assigning the last element.
-
Example of violations:
+ Multiple return values can be used to set several variables at once. To use multiple return values, the left hand side of the assignment must be enclosed in parenthesis. If not, then you are not using multiple return values, you're only assigning the last element.
+
Example of violations:
def a, b = [1, 2] // bad, b is null
def c, d, e = [1, 2, 3] // bad, c and d are null
@@ -4340,8 +4391,7 @@ class MyClass {
def x = 1 // ok
def (f, g) = [1, 2] // ok
(a, b, c) = [1, 2, 3] // ok
-
-]]>
+]]>groovyism
@@ -4351,8 +4401,8 @@ def (f, g) = [1, 2] // ok
MAJOR
- If a class defines a public method that follows the Java getter notation and that returns a constant, then it is cleaner to provide a Groovy property for the value rather than a Groovy method.
-
Example of violations:
+ If a class defines a public method that follows the Java getter notation and that returns a constant, then it is cleaner to provide a Groovy property for the value rather than a Groovy method.
+
Example of violations:
interface Parent {
String getSomething()
@@ -4388,8 +4438,7 @@ def (f, g) = [1, 2] // ok
final int otherValue = 123 // this is cleaner
static final String name = 'MyName' // this is cleaner
}
-
-]]>
+]]>groovyism
@@ -4399,16 +4448,15 @@ def (f, g) = [1, 2] // ok
MINOR
- In many case collectMany() yields the same result as collect{}.flatten(). It is easier to understand and more clearly conveys the intent.
-
Example of violations:
+ In many case collectMany() yields the same result as collect{}.flatten(). It is easier to understand and more clearly conveys the intent.
+
-]]>
+]]>groovyism
@@ -4418,16 +4466,15 @@ l.collectMany{ [it, it*2] } // same functionality, better readability
MINOR
- The collectAll method is deprecated since Groovy 1.8.1. Use collectNested instead.
-
Example of violations:
+ The collectAll method is deprecated since Groovy 1.8.1. Use collectNested instead.
+
Example of violations:
def list = [1, 2, [3, 4, [5, 6]], 7]
list.collectAll { it * 2 } // deprecated
list.collectNested { it * 2 } // replacement
-
-]]>
+]]>groovyism
@@ -4437,12 +4484,12 @@ list.collectNested { it * 2 } // replacement
MINOR
- Instead of nested collect{} calls use collectNested{}.
-
Example of violations:
+ Instead of nested collect{} calls use collectNested{}.
+
-]]>
+]]>groovyism
@@ -4487,8 +4532,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for a duplicate statements.
- ]]>
+ Checks for a duplicate import statements.]]>bug
@@ -4497,8 +4541,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for an of a class that is within the same package as the importing class.
- ]]>
+ Checks for an import of a class that is within the same package as the importing class.]]>bug
@@ -4507,8 +4550,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for an from any package that is already automatically imported for Groovy files. A Groovy file does not need to include an import for classes from , , , , and , as well as the classes and .
- ]]>
+ Checks for an import from any package that is already automatically imported for Groovy files. A Groovy file does not need to include an import for classes from java.lang, java.util, java.io, java.net, groovy.lang and groovy.util, as well as the classes java.math.BigDecimal and java.math.BigInteger.]]>bug
@@ -4517,9 +4559,10 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for statements for classes that are never referenced within the source file. Also checks static imports.
-
Known limitations:
-]]>
+ Checks for import statements for classes that are never referenced within the source file. Also checks static imports.
+
Known limitations:
+
* Does not check for unused imports containing wildcards (e.g. import org.codenarc.*)
+
* Misses unused imports if the class/alias name is contained within strings, comments or other (longer) names (i.e., if that string shows up almost anywhere within the source code).
]]>bug
@@ -4530,14 +4573,13 @@ println list.collectNested { it * 2 } // same functionality, better readability
Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change.
-
Example of violations:
+
Example of violations:
import sun.misc.foo
import sun.misc.foo as Foo
public class MyClass{}
-
-]]>
+]]>
bug
@@ -4547,20 +4589,19 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for static statements which should never be after nonstatic imports.
-
This rule has one property comesBefore, which defaults to true. If you like your static imports to come after the others, then set this property to false.
-
Examples of violations:
+ Checks for static import statements which should never be after nonstatic imports.
+
This rule has one property comesBefore, which defaults to true. If you like your static imports to come after the others, then set this property to false.
+
Examples of violations:
import my.something.another
import static foo.bar
public class MyClass{}
-
-]]>
+]]>bugcomesBefore
-
+ true
@@ -4571,15 +4612,14 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Wildcard imports, static or otherwise, should not be used.
-
Example of violations:
+ Wildcard imports, static or otherwise, should not be used.
+
Example of violations:
import my.something.*
import static foo.bar.*
public class MyClass{}
-
-]]>
+]]>bug
@@ -4591,14 +4631,13 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- The J2EE standard requires that applications use the container's resource management facilities to obtain connections to resources. Every major web application container provides pooled database connection management as part of its resource management framework. Duplicating this functionality in an application is difficult and error prone, which is part of the reason it is forbidden under the J2EE standard.
-
+ The J2EE standard requires that applications use the container's resource management facilities to obtain connections to resources. Every major web application container provides pooled database connection management as part of its resource management framework. Duplicating this functionality in an application is difficult and error prone, which is part of the reason it is forbidden under the J2EE standard.
+
-]]>
+]]>bug
@@ -4608,10 +4647,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for direct use of java.sql.Connection, which is discouraged and almost never necessary in application code.
-
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
- ]]>
+ Checks for direct use of java.sql.Connection, which is discouraged and almost never necessary in application code.
+
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
]]>bug
@@ -4621,10 +4659,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for direct use of java.sql.ResultSet, which is not necessary if using the Groovy Sql facility or an ORM framework such as .
-
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
- ]]>
+ Checks for direct use of java.sql.ResultSet, which is not necessary if using the Groovy Sql facility or an ORM framework such as Hibernate.
+
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
]]>bug
@@ -4634,10 +4671,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for direct use of java.sql.Statement, java.sql.PreparedStatement, or java.sql.CallableStatement, which is not necessary if using the Groovy Sql facility or an ORM framework such as .
-
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
-]]>
+ Checks for direct use of java.sql.Statement, java.sql.PreparedStatement, or java.sql.CallableStatement, which is not necessary if using the Groovy Sql facility or an ORM framework such as Hibernate.
+
Note: If a violation is triggered from an import statement, then you may get multiple violations per import if there are multiple classes in the source file. In that case, the imports are processed once per class.
]]>bug
@@ -4648,8 +4684,23 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Rule that checks for JUnit <<>> method calls with constant or literal arguments such that theassertion always fails. This includes:
-]]>
+ Rule that checks for JUnit assert() method calls with constant or literal arguments such that the assertion always fails. This includes:
+
* assertTrue(false)
+
* assertTrue(0)
+
* assertTrue('')
+
* assertTrue([])
+
* assertTrue([:])
+
* assertFalse(true)
+
* assertFalse('abc')
+
* assertFalse(99)
+
* assertFalse([123])
+
* assertFalse([a:123)
+
* assertNull(CONSTANT).
+
* assertNull([]).
+
* assertNull([123]).
+
* assertNull([:]).
+
* assertNull([a:123]).
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4658,8 +4709,19 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Rule that checks for JUnit assert() method calls with constant arguments such that the assertion always succeeds. This includes:
-]]>
+ Rule that checks for JUnit assert() method calls with constant arguments such that the assertion always succeeds. This includes:
+
* assertTrue(true)
+
* assertTrue(99)
+
* assertTrue('abc')
+
* assertTrue([123])
+
* assertTrue([a:123])
+
* assertFalse(false)
+
* assertFalse('')
+
* assertFalse(0)
+
* assertFalse([])
+
* assertFalse([:)
+
* assertNull(null)
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4668,9 +4730,17 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Rule that checks if a JUnit test class contains public methods other than standard test methods, JUnit framework methods or methods with JUnit annotations.
-
The following public methods are ignored by this rule:
-]]>
+ Rule that checks if a JUnit test class contains public methods other than standard test methods, JUnit framework methods or methods with JUnit annotations.
+
The following public methods are ignored by this rule:
+
* Zero-argument methods with names starting with "test"
+
* The setUp() and tearDown() methods
+
* Methods annotated with @Test
+
* Methods annotated with @Before and @After
+
* Methods annotated with @BeforeClass and @AfterClass
+
* Methods annotated with @Override
+
Public, non-test methods on a test class violate conventional usage of test classes, and they typically break encapsulation unnecessarily.
+
Public, non-test methods may also hide unintentional 'Lost Tests'. For instance, the test method declaration may (unintentionally) include methods parameters, and thus be ignored by JUnit. Or the method may (unintentionally) not follow the "test.." naming convention and not have the @Test annotation, and thus be ignored by JUnit.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4679,9 +4749,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Rule that checks that if the JUnit setUp method is defined, that it includes a call to super.setUp().
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
+ Rule that checks that if the JUnit setUp method is defined, that it includes a call to super.setUp().
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4690,9 +4759,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Rule that checks that if the JUnit tearDown method is defined, that it includes a call to super.tearDown().
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
+ Rule that checks that if the JUnit tearDown method is defined, that it includes a call to super.tearDown().
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4701,17 +4769,16 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Rule that checks checks for JUnit setUp() methods that contain only a call to super.setUp(). The method is then unnecessary.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Here is an example of a violation:
+ Rule that checks checks for JUnit setUp() methods that contain only a call to super.setUp(). The method is then unnecessary.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-]]>
+]]>junit
@@ -4720,17 +4787,16 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Rule that checks checks for JUnit tearDown() methods that contain only a call to super.tearDown(). The method is then unnecessary.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Here is an example of a violation:
+ Rule that checks checks for JUnit tearDown() methods that contain only a call to super.tearDown(). The method is then unnecessary.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-]]>
+]]>junit
@@ -4740,8 +4806,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule detects calling JUnit style assertions like assertEquals, assertTrue, assertFalse, assertNull, assertNotNull. Groovy 1.7 ships with a feature called the "power assert", which is an assert statement with better error reporting. This is preferable to the JUnit assertions.
- ]]>
+ This rule detects calling JUnit style assertions like assertEquals, assertTrue, assertFalse, assertNull, assertNotNull. Groovy 1.7 ships with a feature called the "power assert", which is an assert statement with better error reporting. This is preferable to the JUnit assertions.]]>junit
@@ -4751,9 +4816,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
+ This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4763,9 +4827,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- In unit tests, if a condition is expected to be false then there is no sense using assertTrue with the negation operator. For instance, assertTrue(!condition) can always be simplified to assertFalse(condition).
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
+ In unit tests, if a condition is expected to be false then there is no sense using assertTrue with the negation operator. For instance, assertTrue(!condition) can always be simplified to assertFalse(condition).
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4775,9 +4838,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule detects JUnit calling assertEquals where the first parameter is a boolean. These assertions should be made by more specific methods, like assertTrue or assertFalse.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- All of the following examples can be simplified to assertTrue or remove the true literal:
+ This rule detects JUnit calling assertEquals where the first parameter is a boolean. These assertions should be made by more specific methods, like assertTrue or assertFalse.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+ All of the following examples can be simplified to assertTrue or remove the true literal:
assertEquals(true, foo())
assertEquals("message", true, foo())
@@ -4792,12 +4855,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
assert foo() == true : "message" // violation only if checkAssertStatements == true
assert false == foo() // violation only if checkAssertStatements == true
assert foo() == false : "message" // violation only if checkAssertStatements == true
-
-]]>
+]]>junitcheckAssertStatements
-
+ false
@@ -4808,9 +4870,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule detects JUnit calling assertEquals where the first or second parameter is null. These assertion should be made against the assertNull method instead.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
+ This rule detects JUnit calling assertEquals where the first or second parameter is null. These assertion should be made against the assertNull method instead.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4820,9 +4881,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule detects JUnit calling assertTrue or assertFalse where the first or second parameter is an Object#is() call testing for reference equality. These assertion should be made against the assertSame or assertNotSame method instead.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-]]>
+ This rule detects JUnit calling assertTrue or assertFalse where the first or second parameter is an Object#is() call testing for reference equality. These assertion should be made against the assertSame or assertNotSame method instead.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4832,8 +4892,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule detects JUnit calling the fail() method without an argument. For better error reporting you should always provide a message.
- ]]>
+ This rule detects JUnit calling the fail() method without an argument. For better error reporting you should always provide a message.]]>junit
@@ -4843,9 +4902,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- In unit tests, if a condition is expected to be true then there is no sense using assertFalse with the negation operator. For instance, assertFalse(!condition) can always be simplified to assertTrue(condition).
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- ]]>
+ In unit tests, if a condition is expected to be true then there is no sense using assertFalse with the negation operator. For instance, assertFalse(!condition) can always be simplified to assertTrue(condition).
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4855,15 +4913,14 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule searches for test methods that do not contain assert statements. Either the test method is missing assert statements, which is an error, or the test method contains custom assert statements that do not follow a proper assert naming convention. Test methods are defined as public void methods that begin with the work test or have a @Test annotation. By default this rule applies to the default test class names, but this can be changed using the rule's applyToClassNames property. An assertion is defined as either using the assert keyword or invoking a method that starts with the work assert, like assertEquals, assertNull, or assertMyClassIsSimilar. Also, any method named should.* also counts as an assertion so that shouldFail methods do not trigger an assertion, any method that starts with fail counts as an assertion, and any method that starts with verify counts as an assertion. Since version 0.23 CodeNarc has support for JUnit's ExpectedException.
-
What counts as an assertion method can be overridden using the assertMethodPatterns property of the rule. The default value is this comma separated list of regular expressions:
+ This rule searches for test methods that do not contain assert statements. Either the test method is missing assert statements, which is an error, or the test method contains custom assert statements that do not follow a proper assert naming convention. Test methods are defined as public void methods that begin with the work test or have a @Test annotation. By default this rule applies to the default test class names, but this can be changed using the rule's applyToClassNames property. An assertion is defined as either using the assert keyword or invoking a method that starts with the work assert, like assertEquals, assertNull, or assertMyClassIsSimilar. Also, any method named should.* also counts as an assertion so that shouldFail methods do not trigger an assertion, any method that starts with fail counts as an assertion, and any method that starts with verify counts as an assertion. Since version 0.23 CodeNarc has support for JUnit's ExpectedException.
+
What counts as an assertion method can be overridden using the assertMethodPatterns property of the rule. The default value is this comma separated list of regular expressions:
-]]>
+]]>junit
@@ -4873,8 +4930,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A test method that invokes another test method is a chained test; the methods are dependent on one another. Tests should be isolated, and not be dependent on one another.
-
Example of violations:
+ A test method that invokes another test method is a chained test; the methods are dependent on one another. Tests should be isolated, and not be dependent on one another.
+
Example of violations:
class MyTest extends GroovyTestCase {
public void testFoo() {
@@ -4896,8 +4953,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// ...
}
}
-
-]]>
+]]>junit
@@ -4907,8 +4963,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule finds test cases that are coupled to other test cases, either by invoking static methods on another test case or by creating instances of another test case. If you require shared logic in test cases then extract that logic to a new class where it can properly be reused. Static references to methods on the current test class are ignored.
-
Example of violations:
+ This rule finds test cases that are coupled to other test cases, either by invoking static methods on another test case or by creating instances of another test case. If you require shared logic in test cases then extract that logic to a new class where it can properly be reused. Static references to methods on the current test class are ignored.
+
Example of violations:
class MyTest extends GroovyTestCase {
public void testMethod() {
@@ -4922,8 +4978,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def input = MyTest.getResourceAsStream('sample.txt')
}
}
-
-]]>
+]]>junit
@@ -4933,9 +4988,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- In a unit test, catching an exception and immediately calling Assert.fail() is pointless and hides the stack trace. It is better to rethrow the exception or not catch the exception at all.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Example of violations:
+ In a unit test, catching an exception and immediately calling Assert.fail() is pointless and hides the stack trace. It is better to rethrow the exception or not catch the exception at all.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
Example of violations:
public void testSomething() {
try {
@@ -4950,8 +5005,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
fail()
}
}
-
-]]>
+]]>junit
@@ -4961,9 +5015,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- If Spock's @IgnoreRest annotation appears on any method, all non-annotated test methods are not executed. This behaviour is almost always unintended. It's fine to use @IgnoreRest locally during development, but when committing code, it should be removed.
-
The and properties determine which classes are considered Spock classes.
-
Example of violations:
+ If Spock's @IgnoreRest annotation appears on any method, all non-annotated test methods are not executed. This behaviour is almost always unintended. It's fine to use @IgnoreRest locally during development, but when committing code, it should be removed.
+
The specificationClassNames and specificationSuperclassNames properties determine which classes are considered Spock Specification classes.
+
Example of violations:
public class MySpec extends spock.lang.Specification {
@spock.lang.IgnoreRest
@@ -4979,16 +5033,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
then: a == 4
}
}
-
-]]>
+]]>junitspecificationClassNames
-
+ specificationSuperclassNames
-
+ *Specification
@@ -4999,18 +5052,17 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named * that is not annotated with the JUnit 4 @Test annotation.
-
Note: This rule should be disabled for Grails 2.x projects, since the Grails test framework can use AST Transformations to automatically annotate test methods.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Example of violations:
+ This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named test* that is not annotated with the JUnit 4 @Test annotation.
+
Note: This rule should be disabled for Grails 2.x projects, since the Grails test framework can use AST Transformations to automatically annotate test methods.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-]]>
+]]>junit
@@ -5020,9 +5072,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Example of violations:
+ Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-]]>
+]]>junit
@@ -5049,10 +5100,10 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for public fields on a JUnit test class. There is usually no reason to have a public field (even a constant) on a test class.
-
Fields within interfaces and fields annotated with @Rule are ignored.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Example of violations:
+ Checks for public fields on a JUnit test class. There is usually no reason to have a public field (even a constant) on a test class.
+
Fields within interfaces and fields annotated with @Rule are ignored.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
Example of violations:
import org.junit.Test
class MyTestCase {
@@ -5062,8 +5113,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
@Test
void testMe() { }
}
-
-]]>
+]]>junit
@@ -5073,16 +5123,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Reports usages of org.junit.Assert.assertEquals([message,] expected, actual) where the actual parameter is a constant or a literal. Most likely it was intended to be the expected value.
-
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
-
Example of violations:
+ Reports usages of org.junit.Assert.assertEquals([message,] expected, actual) where the actual parameter is a constant or a literal. Most likely it was intended to be the expected value.
+
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
-]]>
+]]>junit
@@ -5092,9 +5141,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for public properties defined on JUnit test classes. There is typically no need to expose a public property (with public and methods) on a test class.
-
This rule sets the default value of the property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
-
Example of violations:
+ Checks for public properties defined on JUnit test classes. There is typically no need to expose a public property (with public getter and setter methods) on a test class.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
Example of violations:
import org.junit.Test
class MyTestCase {
@@ -5105,12 +5154,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
@Test
void testMe() { }
}
-
-]]>
+]]>junitignorePropertyNames
-
+
@@ -5121,8 +5169,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for calls to this.print(), this.println() or this.printf(). Consider using a standard logging facility instead.
- ]]>
+ Checks for calls to this.print(), this.println() or this.printf(). Consider using a standard logging facility instead.]]>bug
@@ -5131,8 +5178,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for calls to Throwable.printStackTrace() or StackTraceUtils.printSanitizedStackTrace(Throwable). Consider using a standard logging facility instead.
- ]]>
+ Checks for calls to Throwable.printStackTrace() or StackTraceUtils.printSanitizedStackTrace(Throwable). Consider using a standard logging facility instead.]]>bug
@@ -5141,8 +5187,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for calls to System.err.print(), System.err.println() or System.err.printf(). Consider using a standard logging facility instead.
- ]]>
+ Checks for calls to System.err.print(), System.err.println() or System.err.printf(). Consider using a standard logging facility instead.]]>bug
@@ -5151,8 +5196,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for calls to System.out.print(), System.out.println() or System.out.printf(). Consider using a standard logging facility instead.
-]]>
+ Checks for calls to System.out.print(), System.out.println() or System.out.printf(). Consider using a standard logging facility instead.]]>bug
@@ -5162,10 +5206,52 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for instantiating a logger for a class other than the current class. Checks for logger instantiations for Log4J, SLF4J, Logback, Apache Commons Logging and Java Logging API (java.util.logging).
-
This rule contains a parameter allowDerivedClasses. When set, a logger may be created about this.getClass().
-
Limitations:
-]]>
+ Checks for instantiating a logger for a class other than the current class. Checks for logger instantiations for Log4J, SLF4J, Logback, Apache Commons Logging and Java Logging API (java.util.logging).
+
This rule contains a parameter allowDerivedClasses. When set, a logger may be created about this.getClass().
+
Limitations:
+
* Only checks Loggers instantiated within a class field or property (not variables or expressions within a method)
+
* For Log4J: Does not catch Logger instantiations if you specify the full package name for the Logger class: e.g. org.apache.log4.Logger.getLogger(..)
+
* For SLF4J and Logback: Does not catch Log instantiations if you specify the full package name for the LoggerFactory class: e.g. org.slf4j.LoggerFactory.getLogger(..)
+
* For Commons Logging: Does not catch Log instantiations if you specify the full package name for the LogFactory class: e.g. org.apache.commons.logging.LogFactory.getLog(..)
+
* For Java Logging API: Does not catch Logger instantiations if you specify the full package name for the Logger class: e.g. java.util.logging.Logger.getLogger(..)
+ Here are examples of Log4J or Java Logging API code that cause violations:
+
+ // Log4J or Java Logging API
+
+ class MyClass {
+ private static final LOG = Logger.getLogger(MyClass) // ok
+ def log2 = Logger.getLogger(MyClass.class) // ok
+ private static log3 = Logger.getLogger(MyClass.getClass().getName()) // ok
+ private static log4 = Logger.getLogger(MyClass.getClass().name) // ok
+ private static log5 = Logger.getLogger(MyClass.class.getName()) // ok
+ private static log6 = Logger.getLogger(MyClass.class.name) // ok
+ }
+
+ // Commons Logging
+
+ class MyClass {
+ private static final LOG = LogFactory.getLog(MyClass) // ok
+ def log2 = LogFactory.getLog(MyClass.class) // ok
+ private static log3 = LogFactory.getLog(MyClass.getClass().getName()) // ok
+ private static log4 = LogFactory.getLog(MyClass.getClass().name) // ok
+ private static log5 = LogFactory.getLog(MyClass.class.getName()) // ok
+ private static log6 = LogFactory.getLog(MyClass.class.name) // ok
+ }
+
]]>bug
@@ -5175,8 +5261,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- If you are logging an exception then the proper API is to call error(Object, Throwable), which will log the message and the exception stack trace. If you call error(Object) then the stacktrace may not be logged.
- ]]>
+ If you are logging an exception then the proper API is to call error(Object, Throwable), which will log the message and the exception stack trace. If you call error(Object) then the stacktrace may not be logged.]]>bug
@@ -5186,10 +5271,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Logger objects should be declared private, static and final.
-
This rule has a property: allowProtectedLogger, which defaults to false. Set it to true if you believe subclasses should have access to a Logger in a parent class and that Logger should be declared protected or public.
-
This rule has a property: allowNonStaticLogger, which defaults to false. Set it to true if you believe a logger should be allowed to be non-static.
- ]]>
+ Logger objects should be declared private, static and final.
+
This rule has a property: allowProtectedLogger, which defaults to false. Set it to true if you believe subclasses should have access to a Logger in a parent class and that Logger should be declared protected or public.
+
This rule has a property: allowNonStaticLogger, which defaults to false. Set it to true if you believe a logger should be allowed to be non-static.
]]>bug
@@ -5199,8 +5283,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule catches classes that have more than one logger object defined. Typically, a class has zero or one logger objects.
- ]]>
+ This rule catches classes that have more than one logger object defined. Typically, a class has zero or one logger objects.]]>bug
@@ -5211,12 +5294,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of an abstract class matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active. This rule ignores interfaces and is applied only to abstract classes.
- ]]>
+ Verifies that the name of an abstract class matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active. This rule ignores interfaces and is applied only to abstract classes.]]>bugregex
-
+
@@ -5225,12 +5307,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of a class matches a regular expression. By default it checks that the class name starts with an uppercase letter and is followed by zero or more word characters (letters, numbers or underscores) or dollar signs ($).
- ]]>
+ Verifies that the name of a class matches a regular expression. By default it checks that the class name starts with an uppercase letter and is followed by zero or more word characters (letters, numbers or underscores) or dollar signs ($).]]>bugregex
-
+ ([A-Z]\w*\$?)*
@@ -5240,33 +5321,32 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of each field matches a regular expression. By default it checks that fields that are not have field names that start with a lowercase letter and contains only letters or numbers. By default, field names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
-
NOTE: This rule checks only regular of a class, not . In Groovy, are fields declared with no access modifier (public, protected, private). Thus, this rule only checks fields that specify an access modifier. For naming of , see PropertyNameRule.
-
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the field is the one that is applied for the field name validation.
- ]]>
+ Verifies that the name of each field matches a regular expression. By default it checks that fields that are not static final have field names that start with a lowercase letter and contains only letters or numbers. By default, static final field names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
+
NOTE: This rule checks only regular fields of a class, not properties. In Groovy, properties are fields declared with no access modifier (public, protected, private). Thus, this rule only checks fields that specify an access modifier. For naming of properties, see PropertyNameRule.
+
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the field is the one that is applied for the field name validation.
]]>bugfinalRegex
-
+ ignoreFieldNames
-
+ serialVersionUIDregex
-
+ [a-z][a-zA-Z0-9]*staticFinalRegex
-
+ [A-Z][A-Z0-9_]*staticRegex
-
+
@@ -5275,12 +5355,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of an interface matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active.
- ]]>
+ Verifies that the name of an interface matches the regular expression specified in the regex property. If that property is null or empty, then this rule is not applied (i.e., it does nothing). It defaults to null, so this rule must be explicitly configured to be active.]]>bugregex
-
+
@@ -5289,16 +5368,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of each method matches a regular expression. By default it checks that the method name starts with a lowercase letter. Implicit method names are ignored (i.e., 'main' and 'run' methods automatically created for Groovy scripts).
- ]]>
+ Verifies that the name of each method matches a regular expression. By default it checks that the method name starts with a lowercase letter. Implicit method names are ignored (i.e., 'main' and 'run' methods automatically created for Groovy scripts).]]>bugignoreMethodNames
-
+ regex
-
+ [a-z]\w*
@@ -5308,17 +5386,16 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the package name of a class matches a regular expression. By default it checks that the package name consists of only lowercase letters and numbers, separated by periods.
- ]]>
+ Verifies that the package name of a class matches a regular expression. By default it checks that the package name consists of only lowercase letters and numbers, separated by periods.]]>bugpackageNameRequired
-
+ falseregex
-
+ [a-z]+[a-z0-9]*(\.[a-z0-9]+)*
@@ -5328,16 +5405,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of each parameter matches a regular expression. This rule applies to method parameters, constructor parameters and closure parameters. By default it checks that parameter names start with a lowercase letter and contains only letters or numbers.
- ]]>
+ Verifies that the name of each parameter matches a regular expression. This rule applies to method parameters, constructor parameters and closure parameters. By default it checks that parameter names start with a lowercase letter and contains only letters or numbers.]]>bugignoreParameterNames
-
+ regex
-
+ [a-z][a-zA-Z0-9]*
@@ -5347,32 +5423,31 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of each property matches a regular expression. By default it checks that property names (other than ) start with a lowercase letter and contains only letters or numbers. By default, property names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
-
NOTE: This rule checks only of a class, not regular . In Groovy, are fields declared with no access modifier (public, protected, private). For naming of regular , see FieldNameRule.
-
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the property is the one that is applied for the field name validation.
- ]]>
+ Verifies that the name of each property matches a regular expression. By default it checks that property names (other than static final) start with a lowercase letter and contains only letters or numbers. By default, static final property names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
+
NOTE: This rule checks only properties of a class, not regular fields. In Groovy, properties are fields declared with no access modifier (public, protected, private). For naming of regular fields, see FieldNameRule.
+
The order of precedence for the regular expression properties is: staticFinalRegex, finalRegex, staticRegex and finally regex. In other words, the first regex in that list matching the modifiers for the property is the one that is applied for the field name validation.
]]>bugfinalRegex
-
+ ignorePropertyNames
-
+ regex
-
+ [a-z][a-zA-Z0-9]*staticFinalRegex
-
+ [A-Z][A-Z0-9_]*staticRegex
-
+
@@ -5381,21 +5456,20 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the name of each variable matches a regular expression. By default it checks that non-final variable names start with a lowercase letter and contains only letters or numbers. By default, final variable names start with an uppercase letter and contain only uppercase letters, numbers and underscores.
-]]>
+ Verifies that the name of each variable matches a regular expression. By default it checks that non-final variable names start with a lowercase letter and contains only letters or numbers. By default, final variable names start with an uppercase letter and contain only uppercase letters, numbers and underscores.]]>bugfinalRegex
-
+ [A-Z][A-Z0-9_]*ignoreVariableNames
-
+ regex
-
+ [a-z][a-zA-Z0-9]*
@@ -5406,8 +5480,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for very confusing method names. The referenced methods have names that differ only by capitalization. This is very confusing because if the capitalization were identical then one of the methods would override the other.
-
Also, violations are triggered when methods and fields have very similar names.
+ Checks for very confusing method names. The referenced methods have names that differ only by capitalization. This is very confusing because if the capitalization were identical then one of the methods would override the other.
+
Also, violations are triggered when methods and fields have very similar names.
class MyClass {
int total
@@ -5415,8 +5489,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
1
}
}
-
-]]>
+]]>bug
@@ -5426,8 +5499,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the names of the most commonly overridden methods of Object: equals, hashCode and toString, are correct.
-
Here are some examples of code that produces violations:
+ Verifies that the names of the most commonly overridden methods of Object: equals, hashCode and toString, are correct.
+
Here are some examples of code that produces violations:
-]]>
+]]>bug
@@ -5453,9 +5525,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A factory method is a method that creates objects, and they are typically named either buildFoo(), makeFoo(), or createFoo(). This rule enforces that only one naming convention is used. It defaults to allowing makeFoo(), but that can be changed using the property regex. The regex is a negative expression; it specifically bans methods named build* or create*. However, methods named build or build* receive some special treatment because of the popular Builder Pattern. If the 'build' method is in a class named *Builder then it does not cause a violation.
-
Builder methods are slightly different than factory methods.
-
Example of violations:
+ A factory method is a method that creates objects, and they are typically named either buildFoo(), makeFoo(), or createFoo(). This rule enforces that only one naming convention is used. It defaults to allowing makeFoo(), but that can be changed using the property regex. The regex is a negative expression; it specifically bans methods named build* or create*. However, methods named build or build* receive some special treatment because of the popular Builder Pattern. If the 'build' method is in a class named *Builder then it does not cause a violation.
+
Builder methods are slightly different than factory methods.
+
Example of violations:
class MyClass {
@@ -5495,12 +5567,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
def build() {
}
}
-
-]]>
+]]>bugregex
-
+ (build.*\|create.*)
@@ -5511,8 +5582,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Reports files containing only one top level class / enum / interface which is named differently than the file.
- ]]>
+ Reports files containing only one top level class / enum / interface which is named differently than the file.]]>bug
@@ -5522,12 +5592,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A package source file's path should match the package declaration.
- ]]>
+ A package source file's path should match the package declaration.]]>buggroupId
- part of a package name, that will appear within all checked package names. It must also map to the file path for the correspondin source file. For instance, a of <"org.sample"> means that for all classes that specify a package, that package name must include <"org.sample">, and the source file must exist under an "org/sample" directory. Then, a MyClass class in a org.sample.util package must be defined in a "MyClass.groovy" file within a <"org/sample/util"> directory. That directory can be the child of any arbitrary , e.g. "src/main/groovy". To find the sub-path relevant for the package the rule searches for the first appearance of in the file path. It's to configure this. If groupId is null or empty, this rule does nothing. ]]>
+
@@ -5537,13 +5606,12 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for any class that has an identical name to its superclass, other than the package. This can be very confusing.
-
Also see FindBugs NM_SAME_SIMPLE_NAME_AS_SUPERCLASS rule.
-
Example of violations:
+ Checks for any class that has an identical name to its superclass, other than the package. This can be very confusing.
+
Also see FindBugs NM_SAME_SIMPLE_NAME_AS_SUPERCLASS rule.
+
Example of violations:
class MyClass extends other.MyClass // violation
-
-]]>
+]]>bug
@@ -5553,12 +5621,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for any interface that has an identical name to its super-interface, other than the package. This can be very confusing.
-
Example of violations:
+ Checks for any interface that has an identical name to its super-interface, other than the package. This can be very confusing.
+
-]]>
+]]>bug
@@ -5570,9 +5637,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- The permissions classes such as java.security.Permission and java.security.BasicPermission are designed to be extended. Classes that derive from these permissions classes, however, must prohibit extension. This prohibition ensures that malicious subclasses cannot change the properties of the derived class. Classes that implement sensitive interfaces such as java.security.PrivilegedAction and java.security.PrivilegedActionException must also be declared final for analogous reasons.
-
+ The permissions classes such as java.security.Permission and java.security.BasicPermission are designed to be extended. Classes that derive from these permissions classes, however, must prohibit extension. This prohibition ensures that malicious subclasses cannot change the properties of the derived class. Classes that implement sensitive interfaces such as java.security.PrivilegedAction and java.security.PrivilegedActionException must also be declared final for analogous reasons.
+
class MyPermission extends java.security.Permission {
MyPermission(String name) { super(name) }
@@ -5593,8 +5660,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
class MyPrivilegedActionException extends PrivilegedActionException {
MyPrivilegedActionException(Exception exception) { super(exception) }
}
-
-]]>
+]]>bug
@@ -5604,10 +5670,10 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Reports usages of java.util.Random, which can produce very predictable results. If two instances of Random are created with the same seed and sequence of method calls, they will generate the exact same results. Use java.security.SecureRandom instead, which provides a cryptographically strong random number generator. SecureRandom uses PRNG, which means they are using a deterministic algorithm to produce a pseudo-random number from a true random seed. SecureRandom produces non-deterministic output.
-
By default, this rule ignores test classes are ignored.
+ Reports usages of java.util.Random, which can produce very predictable results. If two instances of Random are created with the same seed and sequence of method calls, they will generate the exact same results. Use java.security.SecureRandom instead, which provides a cryptographically strong random number generator. SecureRandom uses PRNG, which means they are using a deterministic algorithm to produce a pseudo-random number from a true random seed. SecureRandom produces non-deterministic output.
+
By default, this rule ignores test classes are ignored.
def r1 = new Random()
def r2 = new java.util.Random()
@@ -5617,8 +5683,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// this is OK
new java.security.SecureRandom()
new SecureRandom()
-
-]]>
+]]>bug
@@ -5628,9 +5693,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- The File.createTempFile() method is insecure, and has been deprecated by the ESAPI secure coding library. It has been replaced by the ESAPI Randomizer.getRandomFilename(String) method.
-
- ]]>
+ The File.createTempFile() method is insecure, and has been deprecated by the ESAPI secure coding library. It has been replaced by the ESAPI Randomizer.getRandomFilename(String) method.
+
]]>bug
@@ -5640,12 +5704,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Web applications should never call System.exit(). A call to System.exit() is probably part of leftover debug code or code imported from a non-J2EE application.
-
[[1]] Standards Mapping - OWASP Top 10 2004 - (OWASP 2004) A9 Application Denial of Service
-
[[2]] Standards Mapping - Security Technical Implementation Guide Version 3 - (STIG 3) APP6080 CAT II
-
[[3]] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 382
-
[[4]] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1 - (PCI 1.1) Requirement 6.5.9
- ]]>
+ Web applications should never call System.exit(). A call to System.exit() is probably part of leftover debug code or code imported from a non-J2EE application.
+
[[1]] Standards Mapping - OWASP Top 10 2004 - (OWASP 2004) A9 Application Denial of Service
+
[[2]] Standards Mapping - Security Technical Implementation Guide Version 3 - (STIG 3) APP6080 CAT II
+
[[3]] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 382
+
[[4]] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1 - (PCI 1.1) Requirement 6.5.9
]]>bug
@@ -5655,10 +5718,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- The finalize() method should only be called by the JVM after the object has been garbage collected.
-
While the Java Language Specification allows an object's finalize() method to be called from outside the finalizer, doing so is usually a bad idea. For example, calling finalize() explicitly means that finalize() will be called more than once: the first time will be the explicit call and the last time will be the call that is made after the object is garbage collected.
-
References: Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 586
- ]]>
+ The finalize() method should only be called by the JVM after the object has been garbage collected.
+
While the Java Language Specification allows an object's finalize() method to be called from outside the finalizer, doing so is usually a bad idea. For example, calling finalize() explicitly means that finalize() will be called more than once: the first time will be the explicit call and the last time will be the call that is made after the object is garbage collected.
+
References: Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 586
]]>bug
@@ -5668,15 +5730,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule reports violations of the Enterprise JavaBeans specification by using the java.io package to access files or the file system.
-
The Enterprise JavaBeans specification requires that every bean provider follow a set of programming guidelines designed to ensure that the bean will be portable and behave consistently in any EJB container [1].
-
In this case, the program violates the following EJB guideline: "An enterprise bean must not use the java.io package to attempt to access files and directories in the file system."
-
A requirement that the specification justifies in the following way: "The file system APIs are not well-suited for business components to access data. Business components should use a resource manager API, such as JDBC, to store data."
-
REFERENCES
-
[[1]] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 576
-
[[2]] The Enterprise JavaBeans 2.1 Specification Sun Microsystems
- By default, this rule is not applied to tests and test cases.
-
Example of violations:
+ This rule reports violations of the Enterprise JavaBeans specification by using the java.io package to access files or the file system.
+
The Enterprise JavaBeans specification requires that every bean provider follow a set of programming guidelines designed to ensure that the bean will be portable and behave consistently in any EJB container [1].
+
In this case, the program violates the following EJB guideline: "An enterprise bean must not use the java.io package to attempt to access files and directories in the file system."
+
A requirement that the specification justifies in the following way: "The file system APIs are not well-suited for business components to access data. Business components should use a resource manager API, such as JDBC, to store data."
+
REFERENCES
+
[[1]] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 576
+
[[2]] The Enterprise JavaBeans 2.1 Specification Sun Microsystems
+ By default, this rule is not applied to tests and test cases.
+
Example of violations:
FileSystem.getFileSystem() // any method on FileSystem
FileSystem.fileSystem.delete(aFile) // property access of FileSystem
@@ -5694,8 +5756,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// don't create random access file
new RandomAccessFile(name, parent)
-
-]]>
+]]>bug
@@ -5705,16 +5766,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Triggers a violation when an array is declared public, final, and static.
-
In most cases an array declared public, final and static is a bug. Because arrays are mutable objects, the final constraint requires that the array object itself be assigned only once, but makes no guarantees about the values of the array elements. Since the array is public, a malicious program can change the values stored in the array. In most situations the array should be made private.
-
Example of violations:
+ Triggers a violation when an array is declared public, final, and static.
+
In most cases an array declared public, final and static is a bug. Because arrays are mutable objects, the final constraint requires that the array object itself be assigned only once, but makes no guarantees about the values of the array elements. Since the array is public, a malicious program can change the values stored in the array. In most situations the array should be made private.
+
Example of violations:
class MyClass {
public static final String[] myArray = init()
public static final def myArray = [] as String[]
}
-
-]]>
+]]>bug
@@ -5724,10 +5784,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Creates a violation when the program violates secure coding principles by declaring a finalize() method public.
-
A program should never call finalize explicitly, except to call super.finalize() inside an implementation of finalize(). In mobile code situations, the otherwise error prone practice of manual garbage collection can become a security threat if an attacker can maliciously invoke one of your finalize() methods because it is declared with public access. If you are using finalize() as it was designed, there is no reason to declare finalize() with anything other than protected access.
-
References:
-]]>
+ Creates a violation when the program violates secure coding principles by declaring a finalize() method public.
+
A program should never call finalize explicitly, except to call super.finalize() inside an implementation of finalize(). In mobile code situations, the otherwise error prone practice of manual garbage collection can become a security threat if an attacker can maliciously invoke one of your finalize() methods because it is declared with public access. If you are using finalize() as it was designed, there is no reason to declare finalize() with anything other than protected access.
+
References:
+
* Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 583
+
* G. McGraw Securing Java. Chapter 7: Java Security Guidelines
]]>bug
@@ -5737,10 +5798,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Finds code that violates secure coding principles for mobile code by declaring a member variable public but not final.
-
All public member variables in an Applet and in classes used by an Applet should be declared final to prevent an attacker from manipulating or gaining unauthorized access to the internal state of the Applet.
-
References:
-]]>
+ Finds code that violates secure coding principles for mobile code by declaring a member variable public but not final.
+
All public member variables in an Applet and in classes used by an Applet should be declared final to prevent an attacker from manipulating or gaining unauthorized access to the internal state of the Applet.
+
References:
+
* Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 493
+
* G. McGraw Securing Java. Chapter 7: Java Security Guidelines
]]>bug
@@ -5750,15 +5812,14 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Reports incomplete interface implementations created by map-to-interface coercions.
-
By default, this rule does not apply to test files.
-
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
-
Example of violations:
+ Reports incomplete interface implementations created by map-to-interface coercions.
+
By default, this rule does not apply to test files.
+
NOTE: This is a CodeNarc Enhanced Classpath Rule. It requires CodeNarc to have the application classes being analyzed, as well as any referenced classes, on the classpath.
+
Example of violations:
[mouseClicked: { ... }] as MouseListener
//not all MouseListener methods are implemented which can lead to UnsupportedOperationException-s
-
-]]>
+]]>bug
@@ -5770,9 +5831,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A serialVersionUID is normally intended to be used with Serialization. It needs to be of type long, static, and final. Also, it should be declared private. Providing no modifier creates a and Groovy generates a , which is probably not intended.
-
From API javadoc for java.io.Serializable:
- ]]>
+ A serialVersionUID is normally intended to be used with Serialization. It needs to be of type long, static, and final. Also, it should be declared private. Providing no modifier creates a Property and Groovy generates a getter, which is probably not intended.
+
From API javadoc for java.io.Serializable: It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.
]]>bug
@@ -5782,14 +5842,13 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Classes that implement Serializable should define a serialVersionUID. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If you don't define serialVersionUID, the system will make one by hashing most of your class's features. Then if you change anything, the UID will change and Java won't let you reload old data.
-
An example of a missing serialVersionUID:
+ Classes that implement Serializable should define a serialVersionUID. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If you don't define serialVersionUID, the system will make one by hashing most of your class's features. Then if you change anything, the UID will change and Java won't let you reload old data.
+
An example of a missing serialVersionUID:
class MyClass imlements Serializable {
// missing serialVersionUID
}
-
-]]>
+]]>bug
@@ -5799,10 +5858,22 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- To use a Serializable object's serialPersistentFields correctly, it must be declared private, static, and final.
-
The Java Object Serialization Specification allows developers to manually define Serializable fields for a class by specifying them in the serialPersistentFields array. This feature will only work if serialPersistentFields is declared as private, static, and final. Also, specific to Groovy, the field must be of type ObjectStreamField[], and cannot be Object.
-
References:
-]]>
+ To use a Serializable object's serialPersistentFields correctly, it must be declared private, static, and final.
+
The Java Object Serialization Specification allows developers to manually define Serializable fields for a class by specifying them in the serialPersistentFields array. This feature will only work if serialPersistentFields is declared as private, static, and final. Also, specific to Groovy, the field must be of type ObjectStreamField[], and cannot be Object.
+
References:
+
* Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 485
+
* Sun Microsystems, Inc. Java Sun Tutorial
+ Example of violations:
+
+ class MyClass implements Serializable {
+ public ObjectStreamField[] serialPersistentFields = [ new ObjectStreamField("myField", List.class) ] as ObjectStreamField[]
+ }
+
+ // the JVM sees the field type as Object, which won't work
+ class MyOtherClass implements Serializable {
+ private static final serialPersistentFields = [ new ObjectStreamField("myField", List.class) ] as ObjectStreamField[]
+ }
+
]]>bug
@@ -5812,10 +5883,10 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for enums that define writeObject() or writeReplace() methods, or declare serialPersistentFields or serialVersionUID fields, all of which are ignored for enums.
-
From the javadoc for ObjectOutputStream:
-
-
Example of violations:
+ Checks for enums that define writeObject() or writeReplace() methods, or declare serialPersistentFields or serialVersionUID fields, all of which are ignored for enums.
+
From the javadoc for ObjectOutputStream:
+
The process by which enum constants are serialized cannot be customized; any class-specific writeObject and writeReplace methods defined by enum types are ignored during serialization. Similarly, any serialPersistentFields or serialVersionUID field declarations are also ignored--all enum types have a fixed serialVersionUID of 0L.
-]]>
+]]>bug
@@ -5839,12 +5909,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks if the size of a class exceeds the number of lines specified by the maxLines property.
- ]]>
+ Checks if the size of a class exceeds the number of lines specified by the maxLines property.]]>bugmaxLines
-
+ 1000
@@ -5854,31 +5923,43 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Calculates the for methods/classes and checks against configured threshold values.
-
The maxMethodComplexity property holds the threshold value for the cyclomatic complexity value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
-
The maxClassAverageMethodComplexity property holds the threshold value for the average cyclomatic complexity value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
-
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
- The value is calculated as follows:
-
-]]>
+ Calculates the Cyclomatic Complexity for methods/classes and checks against configured threshold values.
+
The maxMethodComplexity property holds the threshold value for the cyclomatic complexity value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
+
The maxClassAverageMethodComplexity property holds the threshold value for the average cyclomatic complexity value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
+
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
+ The cyclomatic complexity value is calculated as follows:
+
Start with a initial (default) value of one (1). Add one (1) for each occurrence of each of the following:
* This rule requires the GMetrics jar on the classpath. See GMetrics.
]]>bugignoreMethodNames
-
+ maxClassAverageMethodComplexity
- value allowed for a class, calculated as the average complexity of its methods or "closure fields". If zero or , then do not check average class-level complexity. ]]>
+ 20maxClassComplexity
- value allowed for a class, calculated as the total complexity of its methods or "closure fields". If zero or , then do not check total class-level complexity. ]]>
+ 0maxMethodComplexity
- value allowed for a single method (or "closure field"). If zero or , then do not check method-level complexity. ]]>
+ 20
@@ -5888,13 +5969,12 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks if the number of methods within a class exceeds the number of lines specified by the maxMethod property.
-
A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects.
- ]]>
+ Checks if the number of methods within a class exceeds the number of lines specified by the maxMethod property.
+
A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects.
]]>bugmaxMethods
-
+ 30
@@ -5904,17 +5984,17 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks if the size of a method exceeds the number of lines specified by the maxLines property.
-
Known Limitations:
-]]>
+ Checks if the size of a method exceeds the number of lines specified by the maxLines property.
+
Known Limitations:
+
* Annotations on a method are included in the size (line count) for that method.
]]>bugignoreMethodNames
-
+ maxLines
-
+ 100
@@ -5924,8 +6004,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for blocks or closures nested more deeply than a configured maximum number. Blocks include if, for, while, switch, try, catch, finally and synchronized blocks/statements, as well as closures.
-
Methods calls, constructor calls, and property access through Builder objects are ignore. For instance, this code does not cause a violation:
+ Checks for blocks or closures nested more deeply than a configured maximum number. Blocks include if, for, while, switch, try, catch, finally and synchronized blocks/statements, as well as closures.
+
Methods calls, constructor calls, and property access through Builder objects are ignore. For instance, this code does not cause a violation:
-]]>
+]]>bugignoreRegex
-
+ .*(b|B)uildermaxNestedBlockDepth
-
+ 5
@@ -5962,35 +6041,34 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Calculates the C.R.A.P. (Change Risk Anti-Patterns) metric score for methods/classes and checks against configured threshold values.
-
The metric score is based on the and test coverage for individual methods. A method with a value greater than the maxMethodCrapScore property causes a violation. Likewise, a class that has an (average method) value greater than the maxClassAverageMethodCrapScore property causes a violation.
-
NOTE: This rule requires the GMetrics[3] jar, version 0.5 (or later), on the classpath, as well as a Cobertura[4]-[6] XML coverage file. If either of these prerequisites is not available, this rule logs a warning messages and exits (i.e., does nothing).
-
The maxMethodCrapScore property holds the threshold value for the CRAP value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
-
The maxClassAverageMethodCrapScore property holds the threshold value for the average CRAP value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
-
NOTE: This rule does NOT treat as methods (unlike some of the other size/complexity rules).
-]]>
+ Calculates the C.R.A.P. (Change Risk Anti-Patterns) metric score for methods/classes and checks against configured threshold values.
+
The CRAP metric score is based on the cyclomatic complexity and test coverage for individual methods. A method with a CRAP value greater than the maxMethodCrapScore property causes a violation. Likewise, a class that has an (average method) CRAP value greater than the maxClassAverageMethodCrapScore property causes a violation.
+
NOTE: This rule requires the GMetrics[3] jar, version 0.5 (or later), on the classpath, as well as a Cobertura[4]-[6] XML coverage file. If either of these prerequisites is not available, this rule logs a warning messages and exits (i.e., does nothing).
+
The maxMethodCrapScore property holds the threshold value for the CRAP value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
+
The maxClassAverageMethodCrapScore property holds the threshold value for the average CRAP value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
+
NOTE: This rule does NOT treat closure fields as methods (unlike some of the other size/complexity rules).
]]>bugcoberturaXmlFile
-
+ ignoreMethodNames
-
+ maxClassAverageMethodCrapScore
- average metric value allowed for a class, calculated as the average CRAP value of its methods. If zero or , then do not check the average class-level CRAP value. ]]>
+ 30maxClassCrapScore
- metric value allowed for a class, calculated as the total CRAP value of its methods. If zero or , then do not check class-level CRAP value. ]]>
+ 0maxMethodCrapScore
- metric value allowed for a single method. If zero or , then do not check method-level complexity. ]]>
+ 30
@@ -6001,33 +6079,45 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Calculates the size metric for methods/classes and checks against configured threshold values.
-
The maxMethodAbcScore property holds the threshold value for the ABC score for each method. If this value is non-zero, a method with an ABC score greater than this value is considered a violation. The value does not have to be an integer (e.g., 1.7 is allowed).
-
The maxClassAverageMethodAbcScore property holds the threshold value for the average ABC score for each class. If this value is non-zero, a class with an average ABC score value greater than this value is considered a violation. The value does not have to be an integer.
-
The maxClassAbcScore property holds the threshold value for the total ABC score value for each class. If this value is non-zero, a class with a total ABC score greater than this value is considered a violation. The value does not have to be an integer.
-
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
- The score is calculated as follows: The metric measures size by counting the number of Assignments (A), Branches (B) and Conditions (C) and assigns a single numerical score calculated as:
-
|ABC| = sqrt((A*A)+(B*B)+(C*C))
-
The calculation rules for Groovy:
-]]>
+ Calculates the ABC size metric for methods/classes and checks against configured threshold values.
+
The maxMethodAbcScore property holds the threshold value for the ABC score for each method. If this value is non-zero, a method with an ABC score greater than this value is considered a violation. The value does not have to be an integer (e.g., 1.7 is allowed).
+
The maxClassAverageMethodAbcScore property holds the threshold value for the average ABC score for each class. If this value is non-zero, a class with an average ABC score value greater than this value is considered a violation. The value does not have to be an integer.
+
The maxClassAbcScore property holds the threshold value for the total ABC score value for each class. If this value is non-zero, a class with a total ABC score greater than this value is considered a violation. The value does not have to be an integer.
+
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
+ The ABC score is calculated as follows: The ABC metric measures size by counting the number of Assignments (A), Branches (B) and Conditions (C) and assigns a single numerical score calculated as:
+
|ABC| = sqrt((A*A)+(B*B)+(C*C))
+
The ABC Metric calculation rules for Groovy:
+
* Add one to the assignment count for each occurrence of an assignment operator, excluding constant declarations: = *= /= %= += <<= >>= &= |= ^= >>>=
+
* Add one to the assignment count for each occurrence of an increment or decrement operator (prefix or postfix): ++ --
+
* Add one to the branch count for each function call or class method call.
+
* Add one to the branch count for each occurrence of the new operator.
+
* Add one to the condition count for each use of a conditional operator: == != <= >= < > <=> =~ ==~
+
* Add one to the condition count for each use of the following keywords: else case default try catch ?
+
* Add one to the condition count for each unary conditional expression.
* See the Blog post describing guidelines for interpreting an ABC score
+
* This (Spanish) blog post about the eXcentia Sonar ABC Metric Plugin (for Java) includes a table of risk classifications for ABC scores for both methods and classes.
+
* See the GMetrics ABC metric. This includes a discussion of guidelines for interpreting ABC scores.
+
* This rule requires Groovy 1.6 (or later).
+
* This rule requires the GMetrics jar on the classpath. See GMetrics.
]]>bugignoreMethodNames
-
+ maxClassAbcScore
- score allowed for a class, calculated as the total ABC score of its methods or "closure fields". If zero or , then do not check class-level scores. ]]>
+ 0maxClassAverageMethodAbcScore
- score allowed for a class, calculated as the average score of its methods or "closure fields". If zero or , then do not check class-level average scores. ]]>
+ 60maxMethodAbcScore
- score allowed for a single method (or "closure field"). If zero or , then do not check method-level scores. ]]>
+ 60
@@ -6038,8 +6128,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks if the number of parameters in method/constructor exceeds the number of parameters specified by the maxParameters property.
-
Example of violations:
+ Checks if the number of parameters in method/constructor exceeds the number of parameters specified by the maxParameters property.
+
Example of violations:
void someMethod(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6) { // violation
}
@@ -6048,12 +6138,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
SampleClass(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) { // violation
}
}
-
-]]>
+]]>bugmaxParameters
-
+ 5
@@ -6065,24 +6154,24 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for unnecessary boolean expressions, including ANDing (&&) or ORing (||) with true, false, null, or a Map/List/String/Number literal.
-
This rule also checks for negation (!) of true, false, null, or a Map/List/String/Number literal.
-
Examples of violations include:
+ Checks for unnecessary boolean expressions, including ANDing (&&) or ORing (||) with true, false, null, or a Map/List/String/Number literal.
+
This rule also checks for negation (!) of true, false, null, or a Map/List/String/Number literal.
+
Examples of violations include:
- result = value && true // AND or OR with boolean constants
+ result = value && true // AND or OR with boolean constants
if (false || value) { .. }
- return value && Boolean.FALSE
+ return value && Boolean.FALSE
- result = null && value // AND or OR with null
+ result = null && value // AND or OR with null
- result = value && "abc" // AND or OR with String literal
+ result = value && "abc" // AND or OR with String literal
- result = value && 123 // AND or OR with Number literal
+ result = value && 123 // AND or OR with Number literal
result = 678.123 || true
- result = value && [x, y] // AND or OR with List literal
+ result = value && [x, y] // AND or OR with List literal
- result = [a:123] && value // AND or OR with Map literal
+ result = [a:123] && value // AND or OR with Map literal
result = !true // Negation of boolean constants
result = !false
@@ -6095,8 +6184,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
result = ![a:123] // Negation of Map literal
result = ![a,b] // Negation of List literal
-
-]]>
+]]>clumsy
@@ -6105,8 +6193,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for unnecessary if statements. The entire if statement, or at least the or block, are considered unnecessary for the four scenarios described below.
-
(1) When the and blocks contain only an explicit return of true and false constants. These cases can be replaced by a simple statement. Examples of violations include:
+ Checks for unnecessary if statements. The entire if statement, or at least the if or else block, are considered unnecessary for the four scenarios described below.
+
(1) When the if and else blocks contain only an explicit return of true and false constants. These cases can be replaced by a simple return statement. Examples of violations include:
if (someExpression) // can be replaced by: return someExpression
return true
@@ -6147,8 +6235,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
if (someExpression) { 123 }
doSomething()
}
-
-]]>
+]]>clumsy
@@ -6157,13 +6244,13 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for ternary expressions where the conditional expression always evaluates to a boolean and the and expressions are merely returning true and false constants. These cases can be replaced by a simple boolean expression. Examples of violations include:
+ Checks for ternary expressions where the conditional expression always evaluates to a boolean and the true and false expressions are merely returning true and false constants. These cases can be replaced by a simple boolean expression. Examples of violations include:
x==99 ? true : false // can be replaced by: x==99
- x && y ? true : false // can be replaced by: x && y
+ x && y ? true : false // can be replaced by: x && y
x||y ? false : true // can be replaced by: !(x||y)
- x >= 1 ? true: false // can be replaced by: x >= 1
- x < 99 ? Boolean.TRUE : Boolean.FALSE // can be replaced by: x < 99
+ x >= 1 ? true: false // can be replaced by: x >= 1
+ x < 99 ? Boolean.TRUE : Boolean.FALSE // can be replaced by: x < 99
!x ? true : false // can be replaced by: !x
@@ -6172,8 +6259,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
x ? 23 : 23 // can be replaced by: 23
x ? MAX_VALUE : MAX_VALUE // can be replaced by: MAX_VALUE
ready ? minValue : minValue // can be replaced by: minValue
-
-]]>
+]]>clumsy
@@ -6183,10 +6269,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- It is unnecessary to instantiate BigDecimal objects. Instead just use the decimal literal or the 'G' identifier to force the type, such as 123.45 or 123.45G.
-
This rule does not produce violations when the parameter evaluates to an integer/long, e.g. new BigDecimal(42), new BigDecimal(42L) or new BigDecimal("42"), because using the "G" suffix on an integer value produces a BigInteger, rather than a BigDecimal, e.g. 45G. So that means there is no way to produce a BigDecimal with exactly that value using a literal.
-
This rule also does not produce violations when the parameter is a double, e.g. new BigDecimal(12.3). That scenario is covered by the BigDecimalInstantiation rule, because that produces an unpredictable (double) value (and so it is , rather than ).
- ]]>
+ It is unnecessary to instantiate BigDecimal objects. Instead just use the decimal literal or the 'G' identifier to force the type, such as 123.45 or 123.45G.
+
This rule does not produce violations when the parameter evaluates to an integer/long, e.g. new BigDecimal(42), new BigDecimal(42L) or new BigDecimal("42"), because using the "G" suffix on an integer value produces a BigInteger, rather than a BigDecimal, e.g. 45G. So that means there is no way to produce a BigDecimal with exactly that value using a literal.
+
This rule also does not produce violations when the parameter is a double, e.g. new BigDecimal(12.3). That scenario is covered by the BigDecimalInstantiation rule, because that produces an unpredictable (double) value (and so it is unsafe, rather than unnecessary).
]]>clumsy
@@ -6196,8 +6281,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- It is unnecessary to instantiate BigInteger objects. Instead just use the literal with the 'G' identifier to force the type, such as 8G or 42G.
- ]]>
+ It is unnecessary to instantiate BigInteger objects. Instead just use the literal with the 'G' identifier to force the type, such as 8G or 42G.]]>clumsy
@@ -6207,16 +6291,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for direct call to a Boolean constructor. Use Boolean.valueOf() or the Boolean.TRUE and Boolean.FALSE constants instead of calling the Boolean() constructor directly.
-
Also checks for Boolean.valueOf(true) or Boolean.valueOf(false). Use the Boolean.TRUE or Boolean.FALSE constants instead.
-
Here is an example of code that produces a violation:
+ Checks for direct call to a Boolean constructor. Use Boolean.valueOf() or the Boolean.TRUE and Boolean.FALSE constants instead of calling the Boolean() constructor directly.
+
Also checks for Boolean.valueOf(true) or Boolean.valueOf(false). Use the Boolean.TRUE or Boolean.FALSE constants instead.
+
Here is an example of code that produces a violation:
-]]>
+]]>clumsy
@@ -6226,8 +6309,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule checks for excessively verbose methods of accessing the last element of an array or list. For instance, it is possible to access the last element of an array by performing array[array.length - 1], in Groovy it is simpler to either call array.last() or array[-1]. The same is true for lists. This violation is triggered whenever a get, getAt, or array-style access is used with an object size check.
-
Code like this all cause violations.
+ This rule checks for excessively verbose methods of accessing the last element of an array or list. For instance, it is possible to access the last element of an array by performing array[array.length - 1], in Groovy it is simpler to either call array.last() or array[-1]. The same is true for lists. This violation is triggered whenever a get, getAt, or array-style access is used with an object size check.
+
Code like this all cause violations.
def x = [0, 1, 2]
def a = x.get(x.size() -1)
@@ -6245,8 +6328,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def d = x.get(z.size() -1) // different objects
def e = x.get(z.length -1) // different objects
def f = x.getAt(z.size() -1) // different objects
-
-]]>
+]]>clumsy
@@ -6256,8 +6338,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Violations are triggered when a block does nothing but throw the original exception. In this scenario there is usually no need for a block, just let the exception be thrown from the original code. This condition frequently occurs when catching an exception for debugging purposes but then forgetting to take the catch statement out.
- ]]>
+ Violations are triggered when a catch block does nothing but throw the original exception. In this scenario there is usually no need for a catch block, just let the exception be thrown from the original code. This condition frequently occurs when catching an exception for debugging purposes but then forgetting to take the catch statement out.]]>clumsy
@@ -6267,11 +6348,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Some method calls to Object.collect(Closure) can be replaced with the spread operator. For instance, list.collect { it.multiply(2) } can be replaced by list*.multiply(2).
-
Examples of violations include:
+ Some method calls to Object.collect(Closure) can be replaced with the spread operator. For instance, list.collect { it.multiply(2) } can be replaced by list*.multiply(2).
+
@@ -6285,7 +6366,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
[1, 2, 3].collect { println it; it.multiply(5) }
// OK, closure has too many arguments
- [1, 2, 3].collect { a, b -> a.multiply(b) }
+ [1, 2, 3].collect { a, b -> a.multiply(b) }
// OK, closure statement references parameter multiple times
[1, 2, 3].collect { it.multiply(it) }
@@ -6300,8 +6381,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// in general the above examples can be rewritten like this:
[1, 2, 3]*.multiply(2)
["1", "2", "3"]*.bytes
-
-]]>
+]]>clumsy
@@ -6311,8 +6391,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for useless calls to collections. For any collection c, calling c.containsAll(c) should always be true, and c.retainAll(c) should have no effect.
- ]]>
+ Checks for useless calls to collections. For any collection c, calling c.containsAll(c) should always be true, and c.retainAll(c) should have no effect.]]>clumsy
@@ -6322,8 +6401,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule detects when a constructor is not necessary; i.e., when there's only one constructor, it's public, has an empty body, and takes no arguments, or else contains only a single call to super().
-
Example of violations:
+ This rule detects when a constructor is not necessary; i.e., when there's only one constructor, it's public, has an empty body, and takes no arguments, or else contains only a single call to super().
+
Example of violations:
class MyClass {
public MyClass() { // violation; constructor is not necessary
@@ -6335,8 +6414,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
super()
}
}
-
-]]>
+]]>clumsy
@@ -6346,8 +6424,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- It is unnecessary to instantiate Double objects. Instead just use the double literal with 'D' identifier to force the type, such as 123.45d or 0.42d.
- ]]>
+ It is unnecessary to instantiate Double objects. Instead just use the double literal with 'D' identifier to force the type, such as 123.45d or 0.42d.]]>clumsy
@@ -6357,8 +6434,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- It is unnecessary to instantiate Float objects. Instead just use the float literal with the 'F' identifier to force the type, such as 123.45F or 0.42f.
- ]]>
+ It is unnecessary to instantiate Float objects. Instead just use the float literal with the 'F' identifier to force the type, such as 123.45F or 0.42f.]]>clumsy
@@ -6368,8 +6444,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for explicit calls to getter/accessor methods which can, for the most part, be replaced by property access. A getter is defined as a method call that matches get[A-Z] but not getClass() or get[A-Z][A-Z] such as getURL(). Getters do not take method arguments.
-
These bits of code produce violations:
+ Checks for explicit calls to getter/accessor methods which can, for the most part, be replaced by property access. A getter is defined as a method call that matches get[A-Z] but not getClass() or get[A-Z][A-Z] such as getURL(). Getters do not take method arguments.
+
-]]>
+]]>clumsy
@@ -6395,8 +6470,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- String objects should be created with single quotes, and GString objects created with double quotes. Creating normal String objects with double quotes is confusing to readers.
-
Example of violations:
+ String objects should be created with single quotes, and GString objects created with double quotes. Creating normal String objects with double quotes is confusing to readers.
+
Example of violations:
def a = "I am a string" // violation
@@ -6427,8 +6502,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def j = '''i am a
string
'''
-
-]]>
+]]>clumsy
@@ -6438,7 +6512,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
+ Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
public class Foo {
// Replace this
@@ -6447,8 +6521,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// with this:
Class c = String.class;
}
-
-]]>
+]]>clumsy
@@ -6458,8 +6531,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- It is unnecessary to instantiate Integer objects. Instead just use the literal with the 'I' identifier to force the type, such as 8I or 42i.
- ]]>
+ It is unnecessary to instantiate Integer objects. Instead just use the literal with the 'I' identifier to force the type, such as 8I or 42i.]]>clumsy
@@ -6469,8 +6541,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- It is unnecessary to instantiate Long objects. Instead just use the literal with the 'L' identifier to force the type, such as 8L or 42L.
- ]]>
+ It is unnecessary to instantiate Long objects. Instead just use the literal with the 'L' identifier to force the type, such as 8L or 42L.]]>clumsy
@@ -6480,8 +6551,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Violations are triggered when an excessive set of consecutive statements all reference the same variable. This can be made more readable by using a with or identity block. By default, 5 references are allowed. You can override this property using the maxReferencesAllowed property on the rule.
-
These two bits of code produce violations:
+ Violations are triggered when an excessive set of consecutive statements all reference the same variable. This can be made more readable by using a with or identity block. By default, 5 references are allowed. You can override this property using the maxReferencesAllowed property on the rule.
+
These two bits of code produce violations:
def p1 = new Person()
p1.firstName = 'Hamlet'
@@ -6517,8 +6588,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
city = 'Basel'
zipCode = '4051'
}
-
-]]>
+]]>clumsy
@@ -6528,15 +6598,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Groovy contains the safe dereference operator. It can be used in boolean conditional statements to safely replace explicit x == null tests. Also, testing the 'this' or 'super' reference for null equality is pointless and can be removed.
-
Examples of violations:
+ Groovy contains the safe dereference operator. It can be used in boolean conditional statements to safely replace explicit x == null tests. Also, testing the 'this' or 'super' reference for null equality is pointless and can be removed.
+
Examples of violations:
- if (obj != null && obj.method()) { }
+ if (obj != null && obj.method()) { }
- if (obj != null && obj.prop) { }
+ if (obj != null && obj.prop) { }
// this is pointless and won't avoid NullPointerException
- if (obj.method() && obj != null ) { }
+ if (obj.method() && obj != null ) { }
if (this == null) { }
if (null == this) { }
@@ -6556,15 +6626,14 @@ println list.collectNested { it * 2 } // same functionality, better readability
if (obj?.method()) { }
// null safe dereference in ternary is OK
- (obj?.prop && obj?.prop2) ? x : y
+ (obj?.prop && obj?.prop2) ? x : y
// obj is reused in a parameter list, so OK
- if (obj != null && obj.method() && isValid(obj)) { }
+ if (obj != null && obj.method() && isValid(obj)) { }
// rule is not so complex yet...
- (obj != null && obj.prop && obj.method()) ? x : y
-
-]]>
+ (obj != null && obj.prop && obj.method()) ? x : y
+]]>clumsy
@@ -6574,25 +6643,24 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- There is no need to check for null before an instanceof; the instanceof keyword returns false when given a null argument.
-
Example:
+ There is no need to check for null before an instanceof; the instanceof keyword returns false when given a null argument.
+
Example:
- if (x != null && x instanceof MyClass) {
+ if (x != null && x instanceof MyClass) {
// should drop the "x != null" check
}
- if (x instanceof MyClass && x != null) {
+ if (x instanceof MyClass && x != null) {
// should drop the "x != null" check
}
// should drop the "x != null" check
- (x != null && x instanceof MyClass) ? foo : bar
+ (x != null && x instanceof MyClass) ? foo : bar
- if (x != null && x instanceof MyClass && x.isValid()) {
+ if (x != null && x instanceof MyClass && x.isValid()) {
// this is OK and causes no violation because the x.isValid() requires a non null reference
}
-
-]]>
+]]>clumsy
@@ -6602,8 +6670,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for an overriding method that merely calls the same method defined in a superclass. Remove it.
- ]]>
+ Checks for an overriding method that merely calls the same method defined in a superclass. Remove it.]]>clumsy
@@ -6613,8 +6680,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- In Groovy, the return keyword is often optional. If a statement is the last line in a method or closure then you do not need to have the return keyword.
- ]]>
+ In Groovy, the return keyword is often optional. If a statement is the last line in a method or closure then you do not need to have the return keyword.]]>clumsy
@@ -6624,12 +6690,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for direct call to the String constructor that accepts a String literal. In almost all cases, this is unnecessary. Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.
-
Here is an example of code that produces a violation:
+ Checks for direct call to the String constructor that accepts a String literal. In almost all cases, this is unnecessary. Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.
+
Here is an example of code that produces a violation:
def s = new String('abc')
-
-]]>
+]]>clumsy
@@ -6639,8 +6704,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Finds empty string literals which are being added. This is an inefficient way to convert any type to a String.
-
Examples:
+ Finds empty string literals which are being added. This is an inefficient way to convert any type to a String.
+
Examples:
// do not add empty strings to things
def a = '' + 123
@@ -6649,8 +6714,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// these examples are OK and do not trigger violations
def c = 456.toString()
def d = property?.toString() ?: ""
-
-]]>
+]]>clumsy
@@ -6660,8 +6724,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Violations occur when method calls to append(Object) are chained together with literals as parameters. The chained calls can be joined into one invocation.
-
Example of violations:
+ Violations occur when method calls to append(Object) are chained together with literals as parameters. The chained calls can be joined into one invocation.
+
Example of violations:
writer.append('foo').append('bar') // strings can be joined
writer.append('foo').append(5) // string and number can be joined
@@ -6676,8 +6740,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
writer.append().append('Hello') // no arg append is unknown
writer.append('a', 'b').append('Hello') // two arg append is unknown
-
-]]>
+]]>clumsy
@@ -6687,8 +6750,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Catches concatenation of two string literals on the same line. These can safely by joined. In Java, the Java compiler will join two String literals together and place them in the Constant Pool. However, Groovy will not because the plus() method may override the + operator.
-
Examples:
+ Catches concatenation of two string literals on the same line. These can safely by joined. In Java, the Java compiler will join two String literals together and place them in the Constant Pool. However, Groovy will not because the plus() method may override the + operator.
+
Examples:
// Violations
def a = 'Hello' + 'World' // should be 'HelloWorld'
@@ -6708,8 +6771,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def h = 'Hello' + null // OK because not a string
def i = 'Hello' + method() // OK because not a string
def j = 'Hello' - "$World" // OK because not +
-
-]]>
+]]>clumsy
@@ -6719,16 +6781,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Calling String.substring(0) always returns the original string. This code is meaningless.
-
Examples:
+ Calling String.substring(0) always returns the original string. This code is meaningless.
+
Examples:
string.substring(0) // violation
method().substring(0) // violation
prop.substring(1) // OK, not constant 0
prop.substring(0, 1) // OK, end is specified
-
-]]>
+]]>clumsy
@@ -6738,8 +6799,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- If a method has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private method() {}' is redundant and can be simplified to 'private method() {}'.
-
Examples of violations:
+ If a method has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private method() {}' is redundant and can be simplified to 'private method() {}'.
+
Examples of violations:
// def and private is redundant
def private method1() { return 4 }
@@ -6759,8 +6820,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
class MyClass {
def MyClass() {} // def is redundant
}
-
-]]>
+]]>clumsy
@@ -6770,16 +6830,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Any expression mod 1 (exp % 1) is guaranteed to always return zero. This code is probably an error, and should be either (exp & 1) or (exp % 2).
-
Examples:
+ Any expression mod 1 (exp % 1) is guaranteed to always return zero. This code is probably an error, and should be either (exp & 1) or (exp % 2).
+
Examples:
if (exp % 1) {} // violation
if (method() % 1) {} // violation
- if (exp & 1) {} // ok
+ if (exp & 1) {} // ok
if (exp % 2) {} // ok
-
-]]>
+]]>clumsy
@@ -6789,8 +6848,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- The 'public' modifier is not required on methods, constructors or classes.
-
Example of violations:
+ The 'public' modifier is not required on methods, constructors or classes.
+
Example of violations:
// violation on class
public class MyClass {
@@ -6800,8 +6859,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// violation on method
public void myMethod() {}
}
-
-]]>
+]]>clumsy
@@ -6811,8 +6869,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Method contains a pointless self-assignment to a variable or property. Either the code is pointless or the equals()/get() method has been overridden to have a side effect, which is a terrible way to code getters and violates the contract of equals().
-
Examples:
+ Method contains a pointless self-assignment to a variable or property. Either the code is pointless or the equals()/get() method has been overridden to have a side effect, which is a terrible way to code getters and violates the contract of equals().
+
Examples:
x = x // violation
def method(y) {
@@ -6823,8 +6881,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
x = y // acceptable
a.b = a.zz // acceptable
a.b = a().b // acceptable
-
-]]>
+]]>clumsy
@@ -6834,10 +6891,10 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Semicolons as line terminators are not required in Groovy: remove them. Do not use a semicolon as a replacement for empty braces on for and while loops; this is a confusing practice.
-
The rule contains a String property called 'excludePattern'. Any source code line matching this pattern will not trigger a violation. The default value is '\\s?\\*.*|/\\*.*|.*//.*|.*\\*/.*' This is to filter out comments. Any source line that even looks like it is a comment is ignored.
-
\s?\*.* == whitespace plus star character plus anything /\*.* == any line that contains the /* sequence .*//.* == any line that contains the // sequence .*\*/.* == any line that contains the */ sequence
-
Example of violations:
+ Semicolons as line terminators are not required in Groovy: remove them. Do not use a semicolon as a replacement for empty braces on for and while loops; this is a confusing practice.
+
The rule contains a String property called 'excludePattern'. Any source code line matching this pattern will not trigger a violation. The default value is '\\s?\\*.*|/\\*.*|.*//.*|.*\\*/.*' This is to filter out comments. Any source line that even looks like it is a comment is ignored.
+
\s?\*.* == whitespace plus star character plus anything /\*.* == any line that contains the /* sequence .*//.* == any line that contains the // sequence .*\*/.* == any line that contains the */ sequence
+
Example of violations:
package my.company.server; // violation
@@ -6849,8 +6906,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// this code is OK
println(value); println (otherValue)
-
-]]>
+]]>clumsy
@@ -6860,9 +6916,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- The field is marked as transient, but the class isn't Serializable, so marking it as transient has no effect. This may be leftover marking from a previous version of the code in which the class was transient, or it may indicate a misunderstanding of how serialization works.
-
Some Java frameworks change the semantics of the transient keyword. For instance, when using Terracotta the transient keyword may have slightly different semantics. You may need to turn this rule off depending on which Java frameworks are in use.
- Examples:
+ The field is marked as transient, but the class isn't Serializable, so marking it as transient has no effect. This may be leftover marking from a previous version of the code in which the class was transient, or it may indicate a misunderstanding of how serialization works.
+
Some Java frameworks change the semantics of the transient keyword. For instance, when using Terracotta the transient keyword may have slightly different semantics. You may need to turn this rule off depending on which Java frameworks are in use.
+ Examples:
class MyClass {
// class not serializable, violation occurs
@@ -6873,8 +6929,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// OK, class is serializable
transient String property
}
-
-]]>
+]]>clumsy
@@ -6884,12 +6939,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- A private method is marked final. Private methods cannot be overridden, so marking it final is unnecessary.
-
Example of violations:
+ A private method is marked final. Private methods cannot be overridden, so marking it final is unnecessary.
+
Example of violations:
private final method() {}
-
-]]>
+]]>clumsy
@@ -6899,8 +6953,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- When an if statement block ends with a return statement, then the else is unnecessary. The logic in the else branch can be run without being in a new scope.
-
Example of violations:
+ When an if statement block ends with a return statement, then the else is unnecessary. The logic in the else branch can be run without being in a new scope.
+
Example of violations:
if(value){
println 'Executing if logic...'
@@ -6916,8 +6970,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
return true
}
println 'Executing else logic...'
-
-]]>
+]]>clumsy
@@ -6927,12 +6980,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- If a method is called and the only parameter to that method is an inline closure then the parentheses of the method call can be omitted.
-
Example of violations:
+ If a method is called and the only parameter to that method is an inline closure then the parentheses of the method call can be omitted.
+
Example of violations:
[1,2,3].each() { println it }
-
-]]>
+]]>clumsy
@@ -6942,9 +6994,9 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for explicit package reference for classes that Groovy imports by default, such as java.lang.String, java.util.Map and groovy.lang.Closure, as well as classes that were explicitly imported.
-
You do not need to specify the package for any classes from , , , , and , as well as the classes and .
-
Examples of violations include:
+ Checks for explicit package reference for classes that Groovy imports by default, such as java.lang.String, java.util.Map and groovy.lang.Closure, as well as classes that were explicitly imported.
+
You do not need to specify the package for any classes from java.lang, java.util, java.io, java.net, groovy.lang and groovy.util, as well as the classes java.math.BigDecimal and java.math.BigInteger.
+
Examples of violations include:
// Field types
class MyClass {
@@ -6974,7 +7026,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
void init(String name, groovy.lang.Binding binding) { } // violation
// Closure parameter types
- def writeCount = { java.io.Writer writer, int count -> } // violation
+ def writeCount = { java.io.Writer writer, int count -> } // violation
// Extends and implements
class MyHashMap extends java.util.HashMap { } // violation
@@ -6989,8 +7041,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def dataSource = [:] as javax.sql.DataSource // violation
}
}
-
-]]>
+]]>clumsy
@@ -7000,8 +7051,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- If a variable has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private n = 2' is redundant and can be simplified to 'private n = 2'.
-
Examples of violations:
+ If a variable has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance 'def private n = 2' is redundant and can be simplified to 'private n = 2'.
+
Examples of violations:
// def and private is redundant
def private string1 = 'example'
@@ -7020,8 +7071,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// def and a type is redundant
def String string6 = 'example'
-
-]]>
+]]>clumsy
@@ -7031,16 +7081,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- To make a reference to a class, it is unnecessary to specify the '.class' identifier. For instance String.class can be shortened to String.
-
Example of violations:
+ To make a reference to a class, it is unnecessary to specify the '.class' identifier. For instance String.class can be shortened to String.
+
Example of violations:
// The '.class' identifier is unnecessary, violation occurs
def x = String.class
// Ok, unnecessary '.class' identifier has been excluded
def x = String
-
-]]>
+]]>clumsy
@@ -7050,8 +7099,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule finds instanceof checks that cannot possibly evaluate to true. For instance, checking that (!variable instanceof String) will never be true because the result of a not expression is always a boolean.
-
Example of violations:
+ This rule finds instanceof checks that cannot possibly evaluate to true. For instance, checking that (!variable instanceof String) will never be true because the result of a not expression is always a boolean.
+
Example of violations:
if (!variable instanceof String) { ... } // always false
def x = !variable instanceof String // always false
@@ -7061,8 +7110,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// this code is OK
if (!(variable instanceof String)) { ... }
-
-]]>
+]]>clumsy
@@ -7072,14 +7120,13 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- This rule finds usages of String.substring(int) and String.substring(int, int) that can be replaced by use of the subscript operator. For instance, var.substring(5) can be replaced with var[5..-1].
-
Note that the String.substring(beginIndex,endIndex) method specifies a range of beginIndex..endIndex-1, while Groovy's String subscript specifies an inclusive range. So, "123456".substring(1, 5) is equivalent to "123456"[1..4].
-
Example of violations:
+ This rule finds usages of String.substring(int) and String.substring(int, int) that can be replaced by use of the subscript operator. For instance, var.substring(5) can be replaced with var[5..-1].
+
Note that the String.substring(beginIndex,endIndex) method specifies a range of beginIndex..endIndex-1, while Groovy's String subscript specifies an inclusive range. So, "123456".substring(1, 5) is equivalent to "123456"[1..4].
+
Example of violations:
myVar.substring(5) // can use myVar[5..-1] instead
myVar.substring(1, 5) // can use myVar[1..4] instead
-
-]]>
+]]>clumsy
@@ -7089,8 +7136,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- If a field has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance, 'static def constraints = {}' is redundant and can be simplified to 'static constraints = {}.
-
Example of violations:
+ If a field has a visibility modifier or a type declaration, then the def keyword is unneeded. For instance, 'static def constraints = {}' is redundant and can be simplified to 'static constraints = {}.
+
Example of violations:
class MyClass {
// def is redundant
@@ -7111,8 +7158,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
// def and type is redundant
def Object field5 = { }
}
-
-]]>
+]]>clumsy
@@ -7122,8 +7168,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for unnecessary cast operations.
-
Example of violations:
+ Checks for unnecessary cast operations.
+
Example of violations:
int count = (int)123 // violation
def longValue = (long)123456L // violation
@@ -7131,8 +7177,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
String name = (String) "Joe" // violation
def list = (List)[1, 2, 3] // violation
def map = (Map)[a:1] // violation
-
-]]>
+]]>clumsy
@@ -7142,9 +7187,30 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for unnecessary calls to toString(). This includes:
-]]>
+ Checks for unnecessary calls to toString(). This includes:
+
* Calls to toString() on a String literal or expression
+
* Calls to toString() for the value assigned to a String field or variable (if checkAssignments is true).
]]>clumsy
+
+ checkAssignments
+
+ true
+
@@ -7153,8 +7219,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Check for the operator (?.) applied to constants and literals, or this or super, or constructor calls, all of which can never be null.
-
Example of violations:
+ Check for the safe navigation operator (?.) applied to constants and literals, or this or super, or constructor calls, all of which can never be null.
+
-]]>
+]]>clumsy
@@ -7181,7 +7246,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for array allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
+ Checks for array allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
int myMethod() {
new String[3] // unused
@@ -7199,8 +7264,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
}
def closure = { new Date[3] } // OK (last statement in block)
-
-]]>
+]]>bug
@@ -7209,8 +7273,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for object allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
-
By default, this rule does not analyze test files. This rule sets the default value of the property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'. Invoking constructors without using the result is a common pattern in tests.
+ Checks for object allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
+
By default, this rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'. Invoking constructors without using the result is a common pattern in tests.
int myMethod() {
new BigDecimal("23.45") // unused
@@ -7228,8 +7292,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
}
def closure = { new Date() } // OK (last statement in block)
-
-]]>
+]]>bug
@@ -7238,13 +7301,14 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for private fields that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes). By default, fields named serialVersionUID are ignored. The rule has a property named ignoreFieldNames, which can be set to ignore other field names as well. For instance, to ignore fields named 'fieldx', set the property to the 'fieldx, serialVersionUID'
-
Known limitations:
-]]>
+ Checks for private fields that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes). By default, fields named serialVersionUID are ignored. The rule has a property named ignoreFieldNames, which can be set to ignore other field names as well. For instance, to ignore fields named 'fieldx', set the property to the 'fieldx, serialVersionUID'
+
Known limitations:
+
* Does not recognize field access when field name is a GString (e.g. this."${fieldName}")
+
* Does not recognize access of private field of another instance (i.e. other than this)
]]>bugignoreFieldNames
-
+ serialVersionUID
@@ -7254,9 +7318,13 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for private methods that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
-
Known limitations:
-]]>
+ Checks for private methods that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
+
Known limitations:
+
* Does not recognize method reference through property access (e.g. getName() accessed as x.name)
+
* Does not recognize method invocations when method name is a GString (e.g. this."${methodName}"())
+
* Does not recognize invoking private method of another instance (i.e. other than this)
+
* Does not differentiate between multiple private methods with the same name but different parameters (i.e., overloaded)
+
* Does not check for unused constructors
]]>bug
@@ -7265,14 +7333,14 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for variables that are never referenced.
-
The rule has a property named ignoreVariableNames, which can be set to ignore some variable names. For instance, to ignore fields named 'unused', set the property to 'unused'.
-
Known limitations:
-]]>
+ Checks for variables that are never referenced.
+
The rule has a property named ignoreVariableNames, which can be set to ignore some variable names. For instance, to ignore fields named 'unused', set the property to 'unused'.
+
Known limitations:
+
* Incorrectly considers a variable referenced if another variable with the same name is referenced elsewhere (in another scope/block).
]]>bugignoreVariableNames
-
+
@@ -7282,9 +7350,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for parameters to private methods that are not referenced within the method body. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
-
Known limitations:
-]]>
+ Checks for parameters to private methods that are not referenced within the method body. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
+
Known limitations:
+
* Does not recognize parameter references within an inner class. See CodeNarc bug #3155974.
+
* Does not recognize parameter references when parameter name is a GString (e.g. println "${parameterName}")
+
* You can specify an ignore list using the 'ignoreRegex' property. By default, a parameter named 'ignore' or 'ignored' does not trigger a violation (the regex value is 'ignore|ignored'). You can add your own ignore list using this property.
]]>bug
@@ -7294,8 +7364,41 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule finds instances of method parameters not being used. It does not analyze private methods (that is done by the UnusedPrivateMethodParameter rule) or methods marked @Override.
-]]>
+ This rule finds instances of method parameters not being used. It does not analyze private methods (that is done by the UnusedPrivateMethodParameter rule) or methods marked @Override.
+
* This rule ignores main() methods. In Groovy, the main() method can either specify a void return type or else omit a return type (be dynamically typed). The main() method must have exactly one parameter. That parameter can either be typed as String[] or else the type can be omitted (be dynamically typed). And the main() method must be static.
+
* You can specify an ignore list of parameter names using the 'ignoreRegex' property. By default, a parameter named 'ignore' or 'ignored' does not trigger a violation (the regex value is 'ignore|ignored'). You can add your own ignore list using this property.
+
* You can specify a class name pattern to ignore using the 'ignoreClassRegex' property. By default classes named '*.Category' are ignored because they are category classes and have unused parameters in static methods.
+
Example of violations:
+
+ class MyClass {
+ def method(def param) {
+ // param is unused
+ }
+ }
+
+
+ class MyClass {
+ @Override
+ def otherMethod(def param) {
+ // this is OK because it overrides a super class
+ }
+ }
+
+ class MyCategory {
+ // Category classes are ignored by default
+ void myMethod1(String string, int value) { }
+ void myMethod1(String string, int value, name) { }
+ }
+
+ class MainClass1 {
+ // main() methods are ignored
+ public static void main(String[] args) { }
+ }
+ class MainClass2 {
+ // This is also a valid Groovy main() method
+ static main(args) { }
+ }
+
");
+ inParagraph = true;
+ } else {
+ descriptionBuilder.append(' ');
+ }
+ descriptionBuilder.append(line);
}
public boolean hasParameters() {
return parameters != null && !parameters.isEmpty();
}
+
+ public void replaceDescription(AptResult other) {
+ this.descriptionBuilder = new StringBuilder(other.getDescription());
+ }
}
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index d302240b..2b069da7 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -60,6 +60,7 @@
[a:123, b:456] ? x : y
[a, b, c] ? x : y
+
The rule also checks for the same types of constant values for the boolean expressions within the "short" ternary expressions, also known as the "Elvis" operator, e.g.:
true ?: y
null ?: y
@@ -261,6 +262,7 @@
}
}
+
And so does this:
class MyClass {
int hashCode() {
@@ -661,7 +663,7 @@
]]>
multi-threading
@@ -2006,7 +2014,8 @@
foo() ? foo(99) : 123 // OK
foo(x) ? foo() : 123 // OK
foo(1) ? foo(2) : 123 // OK
-]]>
+
+
NOTE: If the boolean and true expressions are the same method call, and that method call has side-effects, then converting it to a Elvis expression may produce different behavior. The method will only be called once, rather than twice. But relying on those side-effects as part of a ternary expression behavior is confusing, error-prone and just a bad idea. In any case, that code should be refactored to move the reliance on the side-effects out of the ternary expression.
]]>
bug
@@ -2072,7 +2081,7 @@
MAJOR
- Do not allow using the def keyword in code. Use a specific type instead.
+ Do not allow using the def keyword in code. Use a specific type instead.
NOTE: This rule applies to the text contents of a file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
int[] array2 = [1,
2 // there is no trailing comma
@@ -2283,6 +2293,7 @@
// the abstract modifier and adding protected constructors
}
+
The following examples all pass:
abstract class MyClass extends AbstractParent {
// OK because parent is named Abstract.*
@@ -2631,10 +2642,10 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for duplicate number literals within the current class.
+ This rule checks for duplicate number literals within the current class.
Code containing duplicate Number literals can usually be improved by declaring the Number as a constant field.
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
- * This rule does not search across several files at once, only in the current file, and only within the current class.
+
* This rule does not search across several files at once, only in the current file, and only within the current class.
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateNumberLiteral') annotation.
]]>bug
@@ -2650,10 +2661,10 @@ for (int i = 0; i < 100; ++i) {
MINOR
- This rule checks for duplicate String literals within the current class.
+ This rule checks for duplicate String literals within the current class.
Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
- * This rule does not search across several files at once, only in the current file, and only within the current class.
+
* This rule does not search across several files at once, only in the current file, and only within the current class.
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateStringLiteral') annotation.
]]>bug
@@ -2669,7 +2680,7 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- This rule checks for duplicate Map literals within the current class. This rule only checks for Maps where the keys and values are all constants or literals.
+ This rule checks for duplicate Map literals within the current class. This rule only checks for Maps where the keys and values are all constants or literals.
Code containing duplicate Map literals can usually be improved by declaring the Map as a constant field.
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
def name
def var1 = [(name):1, b:1, c:1]
@@ -2696,7 +2708,9 @@ for (int i = 0; i < 100; ++i) {
def var1 = [a:7+5]
def var2 = [a:7+5] // not a violation; contains a non-constant/literal expression
-
]]>
+
+
* This rule does not search across several files at once, only in the current file, and only within the current class.
+
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateMapLiteral') annotation.
]]>
bug
@@ -2706,7 +2720,7 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- This rule checks for duplicate List literals within the current class. This rule only checks for Lists where values are all constants or literals.
+ This rule checks for duplicate List literals within the current class. This rule only checks for Lists where values are all constants or literals.
Code containing duplicate List literals can usually be improved by declaring the List as a constant field.
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
def name
def var1 = [name, 'b', 'c']
@@ -2727,7 +2742,9 @@ for (int i = 0; i < 100; ++i) {
def var1 = [1, 7+5]
def var2 = [1, 7+5] // not a violation; contains a non-constant/literal expression
-
]]>
+
+
* This rule does not search across several files at once, only in the current file, and only within the current class.
+
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateListLiteral') annotation.
]]>bug
@@ -2886,6 +2903,7 @@ for (int i = 0; i < 100; ++i) {
throw RuntimeFailure() // ends in Failure, first letter Capitalized
throw RuntimeFault(foo) // ends in Fault, first letter Capitalized
+
The following code will not cause any exceptions:
throw new RuntimeException()
throw runtimeFailure() // first letter lowercase, assumed to be method call
@@ -2934,7 +2952,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for an exception constructor call without a throw as the last statement within a catch block. This rule treats any constructor call for a class named xxxException as an exception constructor call.
+ Checks for an exception constructor call without a throw as the last statement within a catch block. This rule treats any constructor call for a class named xxxException as an exception constructor call.
Example of violations:
void execute() {
@@ -3109,7 +3127,7 @@ for (int i = 0; i < 100; ++i) {
Checks that there is at least one space or whitespace following each comma. That includes checks for method and closure declaration parameter lists, method call parameter lists, Map literals and List literals.
Known limitations:
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
- Examples of violations:
+
Examples of violations:
def value = calculate(1,399, 'abc') // violation on parameter 399
@@ -3158,7 +3176,7 @@ for (int i = 0; i < 100; ++i) {
Known limitations:
* Does not catch violations of missing space around equals operator (=) within a declaration expression, e.g. def x=23
* Does not catch violations of certain ternary expressions and standalone elvis operator (?:) expressions
- Examples of violations:
+
Examples of violations:
def myMethod() {
3+ 5-x*23/ 100 // violation
@@ -3184,7 +3202,7 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace before each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
Known limitations:
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
- Examples of violations:
+
Examples of violations:
class MyClass{ } // violation
class MyOtherClass extends AbstractClass{ } // violation
@@ -3236,7 +3254,7 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace after each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
- Examples of violations:
+
Examples of violations:
class MyClass{int count } // violation
@@ -3288,9 +3306,9 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace after each closing brace ("\{") for method/class/interface declarations, closure expressions and block statements.
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
- Known limitations:
+
Known limitations:
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
- Examples of violations and exceptions:
+
Examples of violations and exceptions:
if (ready) { return 9 }else { } // violation
try { doStuff() }finally { } // violation
@@ -3319,7 +3337,7 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace before each closing brace ("\}") for method/class/interface declarations, closure expressions and block statements.
Known limitations:
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
- Examples of violations:
+
Examples of violations:
class MyClass { int count} // violation
@@ -3451,7 +3469,7 @@ for (int i = 0; i < 100; ++i) {
Checks that there is at least one space (blank) or whitespace around each closure arrow (->) symbol.
Known limitations:
* Does not catch violations if the closure arrow (->) is on a separate line from the start of the closure.
- Example of violations:
+
Example of violations:
def closure1 = {->} // violation
def closure2 = { ->} // violation
@@ -3647,7 +3665,7 @@ for (int i = 0; i < 100; ++i) {
This rule also ignores all fields annotated with the @Inject annotation.
You can configure this rule to ignore certain fields either by name or by type. This can be useful to ignore fields that hold references to (static) dependencies (such as DAOs or Service objects) or static configuration.
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
- [[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
+
[[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.
[[3]] At least one of the (standard) applyToClassNames, applyToFileNames or applyToFilesMatching properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule to apply to a specific set of classes or files.
[[4]] This rule will not catch violations of true statelessness/reentrancy if you define a final field whose value is itself mutable, e.g. a final HashMap.
]]>
@@ -3672,7 +3690,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for reference to any of the packages configured in packageNames.
+ Checks for reference to any of the packages configured in packageNames.
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
This rule can be useful for governance and enforcement of architectural layering. For instance, making sure that view or model classes, for instance, do not contain references to JDBC-specific packages (e.g. java.sql and javax.sql).
Here is an example configuration of this rule used to ensure that JDBC packages/classes are only referenced within DAO classes:
@@ -3690,7 +3708,8 @@ for (int i = 0; i < 100; ++i) {
description = 'Reference to JDBC packages should be restricted to DAO classes.'
}
}
-
]]>
+
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and packageNames, and (optionally) customized violationMessage and priority.
]]>bugpackageNames
@@ -3704,7 +3723,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Checks for reference to any of the classes configured in classNames.
+ Checks for reference to any of the classes configured in classNames.
Note that you can use the standard rule properties, such as applyToClassNames, doNotApplyToFileNames and applyToFilesMatching to only apply this rule to a subset of all classes/files. These rule properties are described in Standard Properties for Configuring Rules.
This rule can be useful for governance and enforcement of architectural layering. For instance, making sure that view or model classes, for instance, do not contain references to DAO classes (e.g., *Dao).
Here is an example configuration of this rule used to ensure that DAO classes are not referenced from within model classes:
@@ -3722,7 +3741,8 @@ for (int i = 0; i < 100; ++i) {
description = 'Do not reference DAOs from model classes.'
}
}
-
]]>
+
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and classNames, and (optionally) customized violationMessage and priority.
]]>bugclassNames
@@ -3759,6 +3779,7 @@ for (int i = 0; i < 100; ++i) {
protected static method3() { }
}
+
Example of violations for properties:
// IllegalClassMember.illegalPropertyModifiers = 'final'
@@ -3767,7 +3788,10 @@ for (int i = 0; i < 100; ++i) {
final property2 // violation
static property3
}
-
]]>
+
+
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and classNames, and (optionally) customized violationMessage and priority.
+
[[1]] At least one the illegalFieldModifiers, allowedFieldModifiers, illegalPropertyModifiers, allowedPropertyModifiers, illegalMethodModifiers or allowedMethodModifiers properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule with at least one kind of illegal or allowed class member.
+
[[2]] At least one of the (standard) applyToClassNames, applyToFileNames or applyToFilesMatching properties must be set (i.e., not null or empty) or else this rule does nothing. In other words, you must configure this rule to apply to a specific set of classes or files.
]]>bugallowedFieldModifiers
@@ -3841,7 +3865,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Rule that checks for public methods on Grails controller classes. Static methods are ignored.
+ Rule that checks for public methods on Grails controller classes. Static methods are ignored.
Grails controller actions and interceptors are defined as properties on the controller class. Public methods on a controller class are unnecessary. They break encapsulation and can be confusing.
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' folder. You can override this with a different regular expression value if appropriate.
This rule also sets the default value of applyToClassNames to only match class names ending in 'Controller'. You can override this with a different class name pattern (String with wildcards) if appropriate.
]]>
@@ -3857,7 +3881,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Rule that checks for references to the session object from within Grails controller and taglib classes.
+ Rule that checks for references to the session object from within Grails controller and taglib classes.
This rule is intended as a "governance" rule to enable monitoring and controlling access to the session from within application source code. Storing objects in the session may inhibit scalability and/or performance and should be carefully considered.
Note that this rule does not check for direct access to the session from within GSP (Groovy Server Pages) files.
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate session access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
@@ -3891,9 +3915,9 @@ for (int i = 0; i < 100; ++i) {
* All fields annotated with the @Inject annotation.
* All fields with names matching the ignoreFieldNames property.
* All fields with types matching the ignoreFieldTypes property.
- The ignoreFieldNames property of this rule is preconfigured to ignore the standard Grails service configuration field names ('scope', 'transactional') and the standard injected bean names ('dataSource', 'sessionFactory'), as well as all other field names ending with 'Service'.
+
The ignoreFieldNames property of this rule is preconfigured to ignore the standard Grails service configuration field names ('scope', 'transactional') and the standard injected bean names ('dataSource', 'sessionFactory'), as well as all other field names ending with 'Service'.
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/services' folder. You can override this with a different regular expression value if appropriate.
-
This rule also sets the default value of applyToClassNames to only match class names ending in 'Service'. You can override this with a different class name pattern (String with wildcards) if appropriate.
+
This rule also sets the default value of applyToClassNames to only match class names ending in 'Service'. You can override this with a different class name pattern (String with wildcards) if appropriate.
[[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.]]>
grails
@@ -3942,7 +3966,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Check for duplicate name in a Grails domain class mapping. Duplicate names/entries are legal, but can be confusing and error-prone.
+ Check for duplicate name in a Grails domain class mapping. Duplicate names/entries are legal, but can be confusing and error-prone.
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
Example of violations:
@@ -3968,7 +3992,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Check for duplicate name in a Grails domain class constraints. Duplicate names/entries are legal, but can be confusing and error-prone.
+ Check for duplicate name in a Grails domain class constraints. Duplicate names/entries are legal, but can be confusing and error-prone.
NOTE: This rule does not check that the values of the entries are duplicated, only that there are two entries with the same name.
Example of violations:
@@ -4074,7 +4098,9 @@ for (int i = 0; i < 100; ++i) {
a.compareTo(b) >= 0 // can be replaced by: a >= b
a.compareTo(b) < 0 // can be replaced by: a < b
a.compareTo(b) <= 0 // can be replaced by: a <= b
-
]]>
+
+
This rule can be configured to ignore this.compareTo(Object) using the ignoreThisReference property. It defaults to false, so even compareTo(x) will trigger a violation.
+
This rule also ignores all calls to super.compareTo(Object).
]]>groovyism
@@ -4266,7 +4292,7 @@ for (int i = 0; i < 100; ++i) {
MINOR
- A GString should not be used as a map key since its hashcode is not guaranteed to be stable. Consider calling key.toString().
+ A GString should not be used as a map key since its hashcode is not guaranteed to be stable. Consider calling key.toString().
Here is an example of code that produces a violation:
Map map = ["${someRef}" : 'invalid' ] // violation
@@ -4840,7 +4866,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
This rule detects JUnit calling assertEquals where the first parameter is a boolean. These assertions should be made by more specific methods, like assertTrue or assertFalse.
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
- All of the following examples can be simplified to assertTrue or remove the true literal:
+
All of the following examples can be simplified to assertTrue or remove the true literal:
If you'd like to add any method starting with 'ensure' to the ignores then you would set the value to this:
'assert.*,should.*,fail.*,verify.*,ensure.*'
]]>
@@ -5015,7 +5042,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- If Spock's @IgnoreRest annotation appears on any method, all non-annotated test methods are not executed. This behaviour is almost always unintended. It's fine to use @IgnoreRest locally during development, but when committing code, it should be removed.
+ If Spock's @IgnoreRest annotation appears on any method, all non-annotated test methods are not executed. This behaviour is almost always unintended. It's fine to use @IgnoreRest locally during development, but when committing code, it should be removed.
The specificationClassNames and specificationSuperclassNames properties determine which classes are considered Spock Specification classes.
Example of violations:
@@ -5072,7 +5099,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
+ Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
Example of violations:
@@ -5214,7 +5241,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
* For SLF4J and Logback: Does not catch Log instantiations if you specify the full package name for the LoggerFactory class: e.g. org.slf4j.LoggerFactory.getLogger(..)
* For Commons Logging: Does not catch Log instantiations if you specify the full package name for the LogFactory class: e.g. org.apache.commons.logging.LogFactory.getLog(..)
* For Java Logging API: Does not catch Logger instantiations if you specify the full package name for the Logger class: e.g. java.util.logging.Logger.getLogger(..)
- Here are examples of Log4J or Java Logging API code that cause violations:
+
Here are examples of Log4J or Java Logging API code that cause violations:
class MyClass {
private static final LOG = Logger.getLogger(SomeOtherClass) // violation
@@ -5222,6 +5249,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def log2 = Logger.getLogger(SomeOtherClass.class.name) // violation
}
+
Here are examples of Commons Logging code that cause violations:
class MyClass {
private static final LOG = LogFactory.getLog(SomeOtherClass) // violation
@@ -5229,6 +5257,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def log2 = LogFactory.getLog(SomeOtherClass.class.getName()) // violation
}
+
Here are examples of code that does NOT cause violations:
// Log4J or Java Logging API
@@ -5499,7 +5528,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Verifies that the names of the most commonly overridden methods of Object: equals, hashCode and toString, are correct.
+ Verifies that the names of the most commonly overridden methods of Object: equals, hashCode and toString, are correct.
Here are some examples of code that produces violations:
boolean equal(Object o) {} // violation
@@ -5592,7 +5621,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A package source file's path should match the package declaration.]]>
+ A package source file's path should match the package declaration.]]>buggroupId
@@ -5737,7 +5766,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
REFERENCES
[[1]] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 576
[[2]] The Enterprise JavaBeans 2.1 Specification Sun Microsystems
- By default, this rule is not applied to tests and test cases.
+
By default, this rule is not applied to tests and test cases.
Example of violations:
FileSystem.getFileSystem() // any method on FileSystem
@@ -5831,7 +5860,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A serialVersionUID is normally intended to be used with Serialization. It needs to be of type long, static, and final. Also, it should be declared private. Providing no modifier creates a Property and Groovy generates a getter, which is probably not intended.
+ A serialVersionUID is normally intended to be used with Serialization. It needs to be of type long, static, and final. Also, it should be declared private. Providing no modifier creates a Property and Groovy generates a getter, which is probably not intended.
From API javadoc for java.io.Serializable: It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.
]]>bug
@@ -5863,7 +5892,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
References:
* Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 485
* Sun Microsystems, Inc. Java Sun Tutorial
- Example of violations:
+
Example of violations:
class MyClass implements Serializable {
public ObjectStreamField[] serialPersistentFields = [ new ObjectStreamField("myField", List.class) ] as ObjectStreamField[]
@@ -5927,7 +5956,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
The maxMethodComplexity property holds the threshold value for the cyclomatic complexity value for each method. If this value is non-zero, a method with a cyclomatic complexity value greater than this value is considered a violation.
The maxClassAverageMethodComplexity property holds the threshold value for the average cyclomatic complexity value for each class. If this value is non-zero, a class with an average cyclomatic complexity value greater than this value is considered a violation.
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
- The cyclomatic complexity value is calculated as follows:
+
The cyclomatic complexity value is calculated as follows:
Start with a initial (default) value of one (1). Add one (1) for each occurrence of each of the following:
* if statement
* while statement
@@ -5937,7 +5966,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
@@ -6084,7 +6113,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
The maxClassAverageMethodAbcScore property holds the threshold value for the average ABC score for each class. If this value is non-zero, a class with an average ABC score value greater than this value is considered a violation. The value does not have to be an integer.
The maxClassAbcScore property holds the threshold value for the total ABC score value for each class. If this value is non-zero, a class with a total ABC score greater than this value is considered a violation. The value does not have to be an integer.
This rule treats "closure fields" as methods. If a class field is initialized to a Closure (ClosureExpression), then that Closure is analyzed and checked just like a method.
- The ABC score is calculated as follows: The ABC metric measures size by counting the number of Assignments (A), Branches (B) and Conditions (C) and assigns a single numerical score calculated as:
+
The ABC score is calculated as follows: The ABC metric measures size by counting the number of Assignments (A), Branches (B) and Conditions (C) and assigns a single numerical score calculated as:
|ABC| = sqrt((A*A)+(B*B)+(C*C))
The ABC Metric calculation rules for Groovy:
* Add one to the assignment count for each occurrence of an assignment operator, excluding constant declarations: = *= /= %= += <<= >>= &= |= ^= >>>=
@@ -6094,7 +6123,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
* Add one to the condition count for each use of a conditional operator: == != <= >= < > <=> =~ ==~
* Add one to the condition count for each use of the following keywords: else case default try catch ?
* Add one to the condition count for each unary conditional expression.
* See the Blog post describing guidelines for interpreting an ABC score
* This (Spanish) blog post about the eXcentia Sonar ABC Metric Plugin (for Java) includes a table of risk classifications for ABC scores for both methods and classes.
* See the GMetrics ABC metric. This includes a discussion of guidelines for interpreting ABC scores.
@@ -6213,6 +6242,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
return Boolean.FALSE
}
+
(2) When the if statement is the last statement in a block and the if and else blocks are only true and false expressions. This is an implicit return of true/false. For example, the if statement in the following code can be replaced by someExpression or someExpression as boolean:
(3) When the second-to-last statement in a block is an if statement with no else, where the block contains a single return statement, and the last statement in the block is a return statement, and one return statement returns a true expression and the other returns a false expression. This check is disabled by setting checkLastStatementImplicitElse to false. For example, the if statement in the following code can be replaced by return expression1:
(4) When either the if block or else block of an if statement that is not the last statement in a block contain only a single constant or literal expression. For example, the if statement in the following code has no effect and can be removed:
def myMethod() {
if (someExpression) { 123 }
@@ -6253,6 +6285,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
x < 99 ? Boolean.TRUE : Boolean.FALSE // can be replaced by: x < 99
!x ? true : false // can be replaced by: !x
+
The rule also checks for ternary expressions where the true and false expressions are the same constant or variable. Examples include:
x ? '123' : '123' // can be replaced by: '123'
x ? null : null // can be replaced by: null
@@ -6320,6 +6353,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
def f = x[(x.size() -1]
def d = x[(x.length -1]
+
All of this code is fine though:
def x = [0, 1, 2]
def a = x.last()
@@ -6355,6 +6389,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
assert [1, 2, 3].collect { x -> x.multiply(2) }
["1", "2", "3"].collect { it.bytes }
+
The following code does not produce violations:
[1, 2, 3].collect { it * it } // OK, closure parameter is referenced twice
@@ -6452,6 +6487,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
x.getFirstName()
x.getA()
+
These bits of code do not:
x.property
x.first
@@ -6570,6 +6606,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
p2.setCity('Basel')
p2.setZipCode('4051')
+
However, these two bits of code do not because they use either a with or identity block.
def p1 = new Person().with {
firstName = 'Hamlet'
@@ -6618,6 +6655,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
if (super != null) { }
if (null != super) { }
+
Examples of acceptable code:
// null check it OK
if (obj != null) { }
@@ -6731,6 +6769,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
writer.append('foo').append(5) // string and number can be joined
writer.append('Hello').append("$World") // GString can be joined
+
Example of passing code:
// usage not chained invocation
writer.append('Hello')
@@ -6918,7 +6957,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
The field is marked as transient, but the class isn't Serializable, so marking it as transient has no effect. This may be leftover marking from a previous version of the code in which the class was transient, or it may indicate a misunderstanding of how serialization works.
Some Java frameworks change the semantics of the transient keyword. For instance, when using Terracotta the transient keyword may have slightly different semantics. You may need to turn this rule off depending on which Java frameworks are in use.
- Examples:
+
Examples:
class MyClass {
// class not serializable, violation occurs
@@ -7041,7 +7080,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
def dataSource = [:] as javax.sql.DataSource // violation
}
}
-
]]>
+
+
Known limitations:
+
* Does not catch class declarations that explicitly extend java.lang.Object. For instance, class MyClass extends java.lang.Object { }. Just don't do that, okay?
+
* Does not catch class declarations that explicitly extend groovy.lang.Script. For instance, class MyScript extends groovy.lang.Script{ }. Don't do that, either!
+
* Does not catch unnecessary package references if they are the types of anonymous inner class definitions, for older versions of Groovy ( 1.7.10?). For instance, def runnable = new java.lang.Runnable() { ... }.
]]>clumsy
@@ -7190,7 +7233,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Checks for unnecessary calls to toString(). This includes:
* Calls to toString() on a String literal or expression
* Calls to toString() for the value assigned to a String field or variable (if checkAssignments is true).
- Example of violations:
+
Example of violations:
def name = "Joe".toString() // violation - string literal
def groupId = ((String)row.get('GroupID')).toString() // violation - string expression
@@ -7219,7 +7262,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Check for the safe navigation operator (?.) applied to constants and literals, or this or super, or constructor calls, all of which can never be null.
+ Check for the safe navigation operator (?.) applied to constants and literals, or this or super, or constructor calls, all of which can never be null.
class MyClass {
@Override
From 3d3a8f1959cfb96aab0960592b0693cb383b1ec3 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sat, 20 Apr 2019 20:12:29 +0200
Subject: [PATCH 61/89] Update CodeNarc to 0.26.0
---
codenarc-converter/CodeNarc | 2 +-
pom.xml | 2 +-
.../org/sonar/plugins/groovy/rules.xml | 50 +++++++++++++++----
3 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/codenarc-converter/CodeNarc b/codenarc-converter/CodeNarc
index 3bc7458f..e5c2da96 160000
--- a/codenarc-converter/CodeNarc
+++ b/codenarc-converter/CodeNarc
@@ -1 +1 @@
-Subproject commit 3bc7458f47be5f40e647a16d0f271a48b8838fef
+Subproject commit e5c2da96fde59213408f6cec29ddb25e0520030f
diff --git a/pom.xml b/pom.xml
index 1a78c3c9..26ddc3ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
org.codenarcCodeNarc
- 0.25.2
+ 0.26.0org.codehaus.groovy
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index 2b069da7..7cc3ff89 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -1,4 +1,4 @@
-
+
@@ -2645,6 +2645,7 @@ for (int i = 0; i < 100; ++i) {
This rule checks for duplicate number literals within the current class.
Code containing duplicate Number literals can usually be improved by declaring the Number as a constant field.
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
* This rule ignores Long/long values within enums, because the generated code may include generated long id values and produce false positive rule violations.
* This rule does not search across several files at once, only in the current file, and only within the current class.
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateNumberLiteral') annotation.
]]>bug
@@ -2721,6 +2722,7 @@ for (int i = 0; i < 100; ++i) {
This rule checks for duplicate List literals within the current class. This rule only checks for Lists where values are all constants or literals.
+
List literals within annotations are ignored.
Code containing duplicate List literals can usually be improved by declaring the List as a constant field.
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
Examples of violations:
@@ -4309,31 +4311,38 @@ for (int i = 0; i < 100; ++i) {
The groovy.lang.Immutable annotation has been deprecated and replaced by groovy.transform.Immutable. Do not use the Immutable in groovy.lang.
Example of violations:
- @Immutable
+ @Immutable // Violation (no import means groovy.lang.Immutable)
class Person { }
- @groovy.lang.Immutable
+ @groovy.lang.Immutable // Violation
class Person { }
import groovy.lang.Immutable as Imtl
- @Imtl
+ @Imtl // Violation
class Person { }
- // the following code is OK
- @groovy.transform.Immutable
+
+
Example of valid use of @Immutable:
+
+
+ @groovy.transform.Immutable // OK
class Person { }
- import groovy.transform.Immutable
+ import groovy.transform.Immutable // OK
@Immutable
class Person { }
import groovy.transform.*
- @Immutable
+ @Immutable // OK
class Person { }
import groovy.transform.Immutable as Imtl
- @Imtl
+ @Imtl // OK
class Person { }
+
+ @javax.annotation.concurrent.Immutable // OK
+ class MyClass { }
+
]]>groovyism
+
+ ignoreMethodsWithOverrideAnnotation
+
+ false
+
@@ -4776,6 +4790,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Rule that checks that if the JUnit setUp method is defined, that it includes a call to super.setUp().
+
This rule ignored methods annotated with @Before or @BeforeClass.
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -4786,6 +4801,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Rule that checks that if the JUnit tearDown method is defined, that it includes a call to super.tearDown().
+
This rule ignored methods annotated with @After or @AfterClass.
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>junit
@@ -6451,6 +6467,11 @@ println list.collectNested { it * 2 } // same functionality, better readability
}
]]>clumsy
+
+ ignoreAnnotations
+
+ false
+
@@ -6888,6 +6909,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
The 'public' modifier is not required on methods, constructors or classes.
+
Because of Groovy parsing limitations, this rule ignores methods (and constructors) that include Generic types in the method declaration.
Example of violations:
// violation on class
@@ -7444,6 +7466,16 @@ println list.collectNested { it * 2 } // same functionality, better readability
}
]]>bug
+
+ ignoreClassRegex
+
+ .*Category
+
+
+ ignoreRegex
+
+ ignore|ignored
+
From bf482ff6c85ab6f1095301a8e1792fec6a1b0916 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sat, 20 Apr 2019 21:32:42 +0200
Subject: [PATCH 62/89] Update CodeNarc to 0.27.0
---
codenarc-converter/CodeNarc | 2 +-
pom.xml | 2 +-
.../org/sonar/plugins/groovy/rules.xml | 70 ++++++++++++-------
3 files changed, 48 insertions(+), 26 deletions(-)
diff --git a/codenarc-converter/CodeNarc b/codenarc-converter/CodeNarc
index e5c2da96..8c0ef8fc 160000
--- a/codenarc-converter/CodeNarc
+++ b/codenarc-converter/CodeNarc
@@ -1 +1 @@
-Subproject commit e5c2da96fde59213408f6cec29ddb25e0520030f
+Subproject commit 8c0ef8fc4a401677c2e30361bd733e8772077623
diff --git a/pom.xml b/pom.xml
index 26ddc3ca..be29c7d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
org.codenarcCodeNarc
- 0.26.0
+ 0.27.0org.codehaus.groovy
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index 7cc3ff89..3ac2711f 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -1,4 +1,4 @@
-
+
@@ -2082,7 +2082,7 @@
Do not allow using the def keyword in code. Use a specific type instead.
-
NOTE: This rule applies to the text contents of a file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bugexcludeRegex
@@ -2133,7 +2133,8 @@
MAJOR
- Checks that all source files do not contain the tab character.]]>
+ Checks that all source files do not contain the tab character.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>bug
@@ -3000,7 +3001,8 @@ for (int i = 0; i < 100; ++i) {
Checks the location of the opening brace (\{) for classes. By default, requires them on the same line, but the sameLine property can be set to false to override this.
-
NOTE: This rule ignores annotation types, e.g. @interface MyAnnotation {}.
]]>
+
NOTE: This rule ignores annotation types, e.g. @interface MyAnnotation {}.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>conventionsameLine
@@ -3116,7 +3118,8 @@ for (int i = 0; i < 100; ++i) {
MINOR
- Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.]]>
+ Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>convention
@@ -3541,7 +3544,8 @@ for (int i = 0; i < 100; ++i) {
def id
-
]]>
+
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>convention
@@ -3551,7 +3555,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure there are no blank lines before the package declaration of a source code file.]]>
+ Makes sure there are no blank lines before the package declaration of a source code file.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>convention
@@ -3561,7 +3566,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Makes sure each source file ends with a newline character.]]>
+ Makes sure each source file ends with a newline character.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>convention
@@ -3576,7 +3582,8 @@ for (int i = 0; i < 100; ++i) {
import org.apache.commons.lang.StringUtils
class MyClass { } // violation
-
]]>
+
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>convention
@@ -3595,7 +3602,8 @@ for (int i = 0; i < 100; ++i) {
class MyClass {
void go() { /* ... */ }
}
-
]]>
+
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
convention
@@ -3605,7 +3613,8 @@ for (int i = 0; i < 100; ++i) {
MAJOR
- Checks that no lines of source code end with whitespace characters.]]>
+ Checks that no lines of source code end with whitespace characters.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>convention
@@ -3618,7 +3627,7 @@ for (int i = 0; i < 100; ++i) {
Checks for a specified illegal regular expression within the source code.
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and regex, and (optionally) customized violationMessage and priority.
-
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bugregex
@@ -3633,7 +3642,7 @@ for (int i = 0; i < 100; ++i) {
Checks for a specified regular expression that must exist within the source code.
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and regex, and (optionally) customized violationMessage and priority.
-
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bugregex
@@ -3648,7 +3657,7 @@ for (int i = 0; i < 100; ++i) {
Checks for a specified text string that must exist within the source code.
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and string, and (optionally) customized violationMessage and priority.
-
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bugstring
@@ -3837,7 +3846,7 @@ for (int i = 0; i < 100; ++i) {
Checks for a specified illegal string within the source code.
A RuleSet can contain any number of instances of this rule, but each should be configured with a unique rule name and string, and (optionally) customized violationMessage and priority.
-
NOTE: This rule applies to the text contents of an entire file rather than a specific class, so it does not support the applyToClassNames and doNotApplyToClassNames configuration properties.
]]>
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bugstring
@@ -4572,7 +4581,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for a duplicate import statements.]]>
+ Checks for a duplicate import statements.
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>bug
@@ -4581,7 +4591,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for an import of a class that is within the same package as the importing class.]]>
+ Checks for an import of a class that is within the same package as the importing class.
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>bug
@@ -4590,7 +4601,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for an import from any package that is already automatically imported for Groovy files. A Groovy file does not need to include an import for classes from java.lang, java.util, java.io, java.net, groovy.lang and groovy.util, as well as the classes java.math.BigDecimal and java.math.BigInteger.]]>
+ Checks for an import from any package that is already automatically imported for Groovy files. A Groovy file does not need to include an import for classes from java.lang, java.util, java.io, java.net, groovy.lang and groovy.util, as well as the classes java.math.BigDecimal and java.math.BigInteger.
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>bug
@@ -4602,7 +4614,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
Checks for import statements for classes that are never referenced within the source file. Also checks static imports.
Known limitations:
* Does not check for unused imports containing wildcards (e.g. import org.codenarc.*)
-
* Misses unused imports if the class/alias name is contained within strings, comments or other (longer) names (i.e., if that string shows up almost anywhere within the source code).
]]>
+
* Misses unused imports if the class/alias name is contained within strings, comments or other (longer) names (i.e., if that string shows up almost anywhere within the source code).
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bug
@@ -4619,7 +4632,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
import sun.misc.foo as Foo
public class MyClass{}
-]]>
+
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bug
@@ -4637,7 +4651,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
import static foo.bar
public class MyClass{}
-]]>
+
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
bugcomesBefore
@@ -4659,7 +4674,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
import static foo.bar.*
public class MyClass{}
-]]>
+
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.]]>
bug
@@ -5627,7 +5643,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Reports files containing only one top level class / enum / interface which is named differently than the file.
]]>
+ Reports files containing only one top level class / enum / interface which is named differently than the file.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>bug
@@ -5637,7 +5654,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- A package source file's path should match the package declaration.]]>
+ A package source file's path should match the package declaration.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>buggroupId
@@ -7391,6 +7409,10 @@ println list.collectNested { it * 2 } // same functionality, better readability
* Does not differentiate between multiple private methods with the same name but different parameters (i.e., overloaded)
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
+ Do not allow using the def keyword in code. Use a specific type instead.]]>bugexcludeRegex
@@ -2138,6 +2137,57 @@
bug
+
+
+ org.codenarc.rule.convention.CouldBeSwitchStatementRule
+ MAJOR
+
+
+ Checks for three of more if statements that could be converted to a switch. Only applies to equality and instanceof.
+
Example of violations:
+
+ if (x == 1) { // violation
+ y = x
+ } else if (x == 2) {
+ y = x * 2
+ } else if (x == 3) {
+ y = x * 3
+ } else {
+ y = 0
+ }
+
+ if (y instanceof Integer) { // violation
+ x = y + 1
+ }
+ if (y instanceof String) {
+ x = y + '1'
+ } else if (y instanceof Boolean) {
+ x = !y
+ } else {
+ x = null
+ }
+
+ if (x == 1) { // OK
+ y = x
+ }
+ if (x == 2) {
+ y = x * 2
+ } else {
+ y = 0
+ }
+
+ if (!x && y) { // OK
+ doSomething()
+ } else if (!x && z) {
+ doSomethingElse()
+ } else if (!x && i) {
+ doAnotherThing()
+ }
+
+
* This rule is not able to determine if the class extends a superclass that itself implements Comparable, or if it implements an interface that extends Comparable. In those cases, this rule produces a false violation.
]]>
design
@@ -3887,19 +3939,6 @@ for (int i = 0; i < 100; ++i) {
-
- org.codenarc.rule.grails.GrailsSessionReferenceRule
- MINOR
-
-
- Rule that checks for references to the session object from within Grails controller and taglib classes.
-
This rule is intended as a "governance" rule to enable monitoring and controlling access to the session from within application source code. Storing objects in the session may inhibit scalability and/or performance and should be carefully considered.
-
Note that this rule does not check for direct access to the session from within GSP (Groovy Server Pages) files.
-
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate session access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
-
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
Here are examples of Commons Logging code that cause violations:
@@ -5294,12 +5333,12 @@ println list.collectNested { it * 2 } // same functionality, better readability
// Log4J or Java Logging API
class MyClass {
- private static final LOG = Logger.getLogger(MyClass) // ok
- def log2 = Logger.getLogger(MyClass.class) // ok
- private static log3 = Logger.getLogger(MyClass.getClass().getName()) // ok
- private static log4 = Logger.getLogger(MyClass.getClass().name) // ok
- private static log5 = Logger.getLogger(MyClass.class.getName()) // ok
- private static log6 = Logger.getLogger(MyClass.class.name) // ok
+ private static final LOG = LoggerFactory.getLogger(MyClass) // ok
+ def log2 = LoggerFactory.getLogger(MyClass.class) // ok
+ private static log3 = LoggerFactory.getLogger(MyClass.getClass().getName()) // ok
+ private static log4 = LoggerFactory.getLogger(MyClass.getClass().name) // ok
+ private static log5 = LoggerFactory.getLogger(MyClass.class.getName()) // ok
+ private static log6 = LoggerFactory.getLogger(MyClass.class.name) // ok
}
// Commons Logging
@@ -6197,12 +6236,21 @@ println list.collectNested { it * 2 } // same functionality, better readability
void someMethod(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6) { // violation
}
+ @Override
+ void someMethod(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) { // no violation if ignoreOverriddenMethods == true
+ }
+
class SampleClass {
SampleClass(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) { // violation
}
}
]]>
bug
+
+ ignoreOverriddenMethods
+
+ true
+
maxParameters
@@ -7322,6 +7370,29 @@ println list.collectNested { it * 2 } // same functionality, better readability
clumsy
+
+
+ org.codenarc.rule.unnecessary.UnnecessarySetterRule
+ MAJOR
+
+
+ Checks for explicit calls to setter methods which can, for the most part, be replaced by assignment to property. A setter is defined as a method call that matches set[A-Z] but not set[A-Z][A-Z] such as setURL(). Setters take one method argument.
+
]]>
+ clumsy
+
+
@@ -7384,7 +7455,8 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for private fields that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes). By default, fields named serialVersionUID are ignored. The rule has a property named ignoreFieldNames, which can be set to ignore other field names as well. For instance, to ignore fields named 'fieldx', set the property to the 'fieldx, serialVersionUID'
+ Checks for private fields that are not referenced within the same class. Note that the private modifier is not currently "respected" by Groovy code (i.e., Groovy can access private members within other classes).
+
By default, fields named serialVersionUID, and fields annotated with groovy.lang.Delegate are ignored. The rule has a property named ignoreFieldNames, which can be set to ignore other field names as well. For instance, to also ignore fields named 'fieldx', set the property to the 'fieldx, serialVersionUID'
Known limitations:
* Does not recognize field access when field name is a GString (e.g. this."${fieldName}")
* Does not recognize access of private field of another instance (i.e. other than this)
]]>
@@ -7420,7 +7492,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- Checks for variables that are never referenced.
+ Checks for variables that are never referenced. An assignment to the variable is not considered a reference.
The rule has a property named ignoreVariableNames, which can be set to ignore some variable names. For instance, to ignore fields named 'unused', set the property to 'unused'.
Known limitations:
* Incorrectly considers a variable referenced if another variable with the same name is referenced elsewhere (in another scope/block).
class EventListener {
EventListener(EventPublisher publisher) {
- publisher.register(this)
+ publisher.register(this)
new WorkThread(publisher, this).start()
new AnotherWorkThread(listener: this)
- }
+ }
}
]]>multi-threading
@@ -2188,6 +2188,86 @@
bug
+
+
+ org.codenarc.rule.convention.FieldTypeRequiredRule
+ MAJOR
+
+
+ Checks that field types are explicitly specified (and not using def).
+
Example of violations:
+
+ class MyClass {
+ public static final NAME = "joe" // violation
+ private static count = 0 // violation
+
+ private def name = NAME // violation
+ protected final date = new Date() // violation
+
+ def defaultName // violation
+ def maxSoFar = -1L // violation
+ }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.InvertedConditionRule
+ MAJOR
+
+
+ An inverted condition is one where a constant expression is used on the left hand side of the equals comparision. Such conditions can be confusing especially when used in assertions where the expected value is by convention placed on the right hand side of the comparision.
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.MethodReturnTypeRequiredRule
+ MAJOR
+
+
+ Checks that method return types are not dynamic, that is they are explicitly stated and different than def.
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.VariableTypeRequiredRule
+ MAJOR
+
+
+ Checks that variable types are explicitly specified in declarations (and not using def).
+
Example of violations:
+
+ class MyClass {
+ void doStuff() {
+ final NAME = "joe" // violation
+ def count = 0, max = 99 // violation
+ def defaultName // violation
+ }
+ }
+
]]>
+ bug
+
+
@@ -2299,6 +2379,7 @@
If you implement a compareTo method then you should also implement the Comparable interface. If you don't then you could possibly get an exception if the Groovy == operator is invoked on your object. This is an issue fixed in Groovy 1.8 but present in previous versions.
+
This rule has a single enhancedMode property which defaults to false. When set to true, this rule will run in enhanced mode and will not produce a violation when a class implements compareTo and extends a class that itself implements Comparable.
Here is an example of code that produces a violation:
class BadClass {
@@ -2306,7 +2387,7 @@
}
Known limitations:
-
* This rule is not able to determine if the class extends a superclass that itself implements Comparable, or if it implements an interface that extends Comparable. In those cases, this rule produces a false violation.
]]>
+
* When not running in enhanced mode, this rule is not able to determine if the class extends a superclass that itself implements Comparable, or if it implements an interface that extends Comparable. In those cases, this rule produces a false violation.
]]>
design
@@ -2364,7 +2445,8 @@
MINOR
- If a class defines a "void close()" then that class should implement java.io.Closeable.]]>
+ If a class defines a void close() method then that class should implement java.io.Closeable.
+
This rule has a single enhancedMode property which defaults to false. When set to true, this rule will run in enhanced mode and will not produce a violation when a class implements close and extends a class that itself implements Closeable.
]]>design
@@ -2803,6 +2885,27 @@ for (int i = 0; i < 100; ++i) {
bug
+
+
+
+
+ org.codenarc.rule.enhanced.MissingOverrideAnnotationRule
+ MAJOR
+
+
+ Checks for methods that override a method in a superclass or implement a method in an interface but are not annotated with @Override.
+
Consistent use of @Override annotation helps in spotting situations when the intent was to override a method but because of a mistake in method signature that is not the case. Additionally, applying @Override annotation to all overridden methods helps in spotting unnecessary methods which no longer override any methods after removing them from superclasses or implemented interfaces because such annotated methods will cause compilation errors.
]]>
+ bug
+
+
@@ -3670,6 +3773,184 @@ for (int i = 0; i < 100; ++i) {
convention
+
+
+ org.codenarc.rule.formatting.BlockEndsWithBlankLineRule
+ MAJOR
+
+
+ Checks that code blocks such as method bodies, closures and control structure bodies do not end with an empty line.
+
]]>
+ convention
+
+
+
+
+ org.codenarc.rule.formatting.BlockStartsWithBlankLineRule
+ MAJOR
+
+
+ Checks that code blocks such as method bodies, closures and control structure bodies do not start with an empty line.
+
]]>
+ convention
+
+
+
+
+ org.codenarc.rule.formatting.IndentationRule
+ MAJOR
+
+
+ Check the indentation (spaces only; not tabs) for class, field and method declarations, and statements.
+
This rule is limited, and somewhat opinionated. The default is 4 spaces per indentation level.
+
Known Limitations include:
+
* Checks spaces only (not tabs)
+
* Does not check comments
+
* Does not check line-continuations (i.e., checks only the first line of a statement)
+
* Does not check multiple statements/members on the same line (only checks the first one)
+
* Does not check Map entry expressions
+
* Does not check calls to this() and super() within a constructor
+
* When classes, methods or fields have annotations, the indentation of the annotation is checked, not the actual member. And only the first annotation is checked, if there is more than one.
]]>
+ convention
+
+ spacesPerIndentLevel
+
+ 4
+
+
+
@@ -3945,7 +4226,7 @@ for (int i = 0; i < 100; ++i) {
Rule that checks for references to the servletContext object from within Grails controller and taglib classes.
-
This rule is intended as a "governance" rule to enable monitoring and controlling access to the servletContext from within application source code. Storing objects in the servletContext may inhibit scalability and/or performance and should be carefully considered. Furthermore, access to the servletContext is not synchronized, so reading/writing objects from the servletConext must be manually synchronized, as described in The Definitive Guide to Grails (2nd edition).
+
This rule is intended as a "governance" rule to enable monitoring and controlling access to the servletContext from within application source code. Storing objects in the servletContext may inhibit scalability and/or performance and should be carefully considered. Furthermore, access to the servletContext is not synchronized, so reading/writing objects from the servletContext must be manually synchronized, as described in The Definitive Guide to Grails (2nd edition).
Note that this rule does not check for direct access to the servletContext from within GSP (Groovy Server Pages) files.
Enabling this rule may make most sense in a team environment where team members exhibit a broad range of skill and experience levels. Appropriate servletContext access can be configured as exceptions to this rule by configuring either the doNotApplyToFilenames or doNotApplyToFilesMatching property of the rule. And, as always, it is easy to just turn off the rule if it does not make sense it your environment.
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/controllers' or 'grails-app/taglib' folders. You can override this with a different regular expression value if appropriate.
]]>
@@ -4654,7 +4935,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Known limitations:
* Does not check for unused imports containing wildcards (e.g. import org.codenarc.*)
* Misses unused imports if the class/alias name is contained within strings, comments or other (longer) names (i.e., if that string shows up almost anywhere within the source code).
-
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.]]>
bug
@@ -4706,16 +4987,21 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Wildcard imports, static or otherwise, should not be used.
+ Checks for wildcard (star) imports. If the ignoreStaticImports property is true, then do not check static imports.
Example of violations:
- import my.something.*
- import static foo.bar.*
+ import static foo.bar.* // violation (unless ignoreStaticImports is true)
+ import my.something.* // violation
public class MyClass{}
-
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.]]>
+
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
* Zero-argument methods with names starting with "test"
* The setUp() and tearDown() methods
* Methods annotated with @Test
-
* Methods annotated with @Before and @After
-
* Methods annotated with @BeforeClass and @AfterClass
+
* Methods annotated with @Before, @BeforeAll, @BeforeClass and @BeforeEach
+
* Methods annotated with @After, @AfterAll, @AfterClass and @AfterEach
+
* Methods annotated with @Disabled and @Ignore
* Methods annotated with @Override
Public, non-test methods on a test class violate conventional usage of test classes, and they typically break encapsulation unnecessarily.
Public, non-test methods may also hide unintentional 'Lost Tests'. For instance, the test method declaration may (unintentionally) include methods parameters, and thus be ignored by JUnit. Or the method may (unintentionally) not follow the "test.." naming convention and not have the @Test annotation, and thus be ignored by JUnit.
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
junit
+
+ ignoreMethodsWithAnnotations
+
+ After,AfterAll,AfterClass,
+
@@ -5412,7 +5704,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
regex
- ([A-Z]\w*\$?)*
+ ([A-Z]\\w*\\$?)*
@@ -5477,7 +5769,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
regex
- [a-z]\w*
+ [a-z]\\w*
@@ -5496,7 +5788,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
regex
- [a-z]+[a-z0-9]*(\.[a-z0-9]+)*
+ [a-z]+[a-z0-9]*(\\.[a-z0-9]+)*
@@ -5947,7 +6239,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Classes that implement Serializable should define a serialVersionUID. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If you don't define serialVersionUID, the system will make one by hashing most of your class's features. Then if you change anything, the UID will change and Java won't let you reload old data.
An example of a missing serialVersionUID:
- class MyClass imlements Serializable {
+ class MyClass implements Serializable {
// missing serialVersionUID
}
]]>
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
index d2ad3c28..e306d112 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
@@ -42,7 +42,7 @@ public void test() {
assertThat(repository.language()).isEqualTo(Groovy.KEY);
List rules = repository.rules();
- assertThat(rules).hasSize(348);
+ assertThat(rules).hasSize(356);
List missingDebt = new LinkedList<>();
for (Rule rule : rules) {
From 50a5a0fc52011c509e48bf86ba3966dbba0b3735 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 27 Jun 2019 00:45:38 +0200
Subject: [PATCH 65/89] Update CodeNarc to 1.2
---
codenarc-converter/CodeNarc | 2 +-
.../plugins/groovy/codenarc/Converter.java | 11 +
.../groovy/codenarc/ConverterTest.java | 5 +-
pom.xml | 2 +-
.../org/sonar/plugins/groovy/cost.csv | 6 +
.../org/sonar/plugins/groovy/rules.xml | 230 +++++++++++++++---
.../codenarc/CodeNarcRulesDefinitionTest.java | 2 +-
7 files changed, 214 insertions(+), 44 deletions(-)
diff --git a/codenarc-converter/CodeNarc b/codenarc-converter/CodeNarc
index 4d882392..c969a1ce 160000
--- a/codenarc-converter/CodeNarc
+++ b/codenarc-converter/CodeNarc
@@ -1 +1 @@
-Subproject commit 4d88239251309f50fa2e353cd4a067bcd0317945
+Subproject commit c969a1ce9e6dd2b0372419fc768379f80262d124
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
index 27e3fe8b..51496845 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
@@ -568,6 +568,17 @@ public static Multimap loadRules(Path aptDir)
org.codenarc.rule.formatting.BlockStartsWithBlankLineRule.class,
org.codenarc.rule.formatting.IndentationRule.class);
+ insertRules(
+ rules,
+ "1.2",
+ props,
+ parametersByRule,
+ org.codenarc.rule.convention.StaticFieldsBeforeInstanceFieldsRule.class,
+ org.codenarc.rule.convention.StaticMethodsBeforeInstanceMethodsRule.class,
+ org.codenarc.rule.convention.PublicMethodsBeforeNonPublicMethodsRule.class,
+ org.codenarc.rule.grails.GrailsDomainStringPropertyMaxSizeRule.class,
+ org.codenarc.rule.convention.NoJavaUtilDateRule.class);
+
return rules;
}
diff --git a/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java b/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
index 5970378f..6b404f9b 100644
--- a/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
+++ b/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
@@ -147,9 +147,10 @@ private static void assertSimilarXml(Path generatedRulesXML, Path rulesFromPlugi
* - MisorderedStaticImportsRule : description of 'comesBefore' parameter missing in apt files
* - FileCreateTempFileRule: link to website
* - BracesForIfElseRule: default value of parameters should be true, not 'the same as sameLine'
- * - JUnitTestMethodWithoutAssertRule, UnnecessaryObjectReferencesRule: Non-matching open & close tags
+ * - JUnitTestMethodWithoutAssertRule, UnnecessaryObjectReferencesRule,
+ * GrailsDomainStringPropertyMaxSizeRule: Non-matching open & close tags
*/
- Assert.assertEquals(5, nbrDiff);
+ Assert.assertEquals(6, nbrDiff);
}
private static String getRuleKey(Node rule) {
diff --git a/pom.xml b/pom.xml
index 69558f39..7351aefc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
org.codenarcCodeNarc
- 1.1
+ 1.2org.codehaus.groovy
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
index f6a219d0..778e3845 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
@@ -83,8 +83,13 @@ org.codenarc.rule.convention.InvertedIfElseRule;linear;10min
org.codenarc.rule.convention.LongLiteralWithLowerCaseLRule;linear;5min
org.codenarc.rule.convention.MethodReturnTypeRequiredRule;linear;5min
org.codenarc.rule.convention.NoDefRule;linear;5min
+org.codenarc.rule.convention.NoJavaUtilDateRule;linear;5min
org.codenarc.rule.convention.NoTabCharacterRule;linear;2min
org.codenarc.rule.convention.ParameterReassignmentRule;linear;20min
+org.codenarc.rule.convention.PublicMethodsBeforeNonPublicMethodsRule;linear;5min
+org.codenarc.rule.convention.PublicMethodsBeforeNonPublicMethodsRule>;linear;5min
+org.codenarc.rule.convention.StaticFieldsBeforeInstanceFieldsRule;linear;5min
+org.codenarc.rule.convention.StaticMethodsBeforeInstanceMethodsRule;linear;5min
org.codenarc.rule.convention.TernaryCouldBeElvisRule;linear;10min
org.codenarc.rule.convention.TrailingCommaRule;linear;5min
org.codenarc.rule.convention.VariableTypeRequiredRule;linear;5min
@@ -179,6 +184,7 @@ org.codenarc.rule.generic.StatelessClassRule.fixed;linear;20min
org.codenarc.rule.grails.GrailsDomainHasEqualsRule;linear;20min
org.codenarc.rule.grails.GrailsDomainHasToStringRule;linear;20min
org.codenarc.rule.grails.GrailsDomainReservedSqlKeywordNameRule;linear;20min
+org.codenarc.rule.grails.GrailsDomainStringPropertyMaxSizeRule;linear;5min
org.codenarc.rule.grails.GrailsDomainWithServiceReferenceRule;linear;20min
org.codenarc.rule.grails.GrailsDuplicateConstraintRule;linear;20min
org.codenarc.rule.grails.GrailsDuplicateMappingRule;linear;20min
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index 57ea97fe..865ca921 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -1,4 +1,4 @@
-
+
@@ -2209,6 +2209,10 @@
}
]]>
bug
+
+ ignoreFieldNames
+
+
@@ -2264,6 +2268,104 @@
def defaultName // violation
}
}
+]]>
+ bug
+
+ ignoreVariableNames
+
+
+
+
+
+
+ org.codenarc.rule.convention.StaticFieldsBeforeInstanceFieldsRule
+ MAJOR
+
+
+ Enforce that all static fields are above all instance fields within a class
+
Example of violations:
+
+ class MyClass {
+ public static final int COUNT = 99
+
+ public String f1
+
+ public static final String F1 = "xxx" // violation
+ private static String F4 // violation
+ static F5 = new Date() // violation
+
+ protected String f2
+ }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.StaticMethodsBeforeInstanceMethodsRule
+ MAJOR
+
+
+ Enforce that all static methods within each visibility level (public, protected, private) are above all instance methods within that same visibility level. In other words, public static methods must be above public instance methods, protected static methods must be above protected instance methods and private static methods must be above private instance methods.
+
Example of violations:
+
+ class MyClass {
+ // Public
+ public static int staticMethod1() { }
+ public String method1() { }
+ int method2() { }
+ static final String staticMethod2(int id) { } // violation
+
+ // Protected
+ protected String method3() { }
+ protected static staticMethod3() { } // violation
+
+ // Private
+ private int method4() { }
+ private int method5() { }
+ private static staticMethod4() { } // violation
+ private String method5() { }
+ }
+ }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.PublicMethodsBeforeNonPublicMethodsRule
+ MAJOR
+
+
+ Enforce that all public methods are above protected and private methods.
+
Example of violations:
+
+ class MyClass {
+ public static int staticMethod1() { }
+
+ protected String method1() { }
+
+ static final String staticMethod2() { } // violation
+ public String method2() { } // violation
+
+ private int method3(int id) { }
+ }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.convention.NoJavaUtilDateRule
+ MINOR
+
+
+ Do not use the java.util.Date class. Prefer the classes in the java.time.* packages. This rule checks for construction of new java.util.Date objects.
+
Example of violations:
+
+ def timestamp = new Date() // violation
+ Date myDate = new java.util.Date() // violation
+ Date startTime = new Date(123456789L) // violation
]]>bug
@@ -2689,7 +2791,7 @@
Here are a couple references that discuss the problems with using instanceof and the preference for using polymorphism instead:
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Spec.groovy', 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
Example of violations:
class MyClass {
@@ -2779,7 +2881,7 @@ for (int i = 0; i < 100; ++i) {
This rule checks for duplicate number literals within the current class.
Code containing duplicate Number literals can usually be improved by declaring the Number as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Spec.groovy', 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
* This rule ignores Long/long values within enums, because the generated code may include generated long id values and produce false positive rule violations.
* This rule does not search across several files at once, only in the current file, and only within the current class.
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateNumberLiteral') annotation.
]]>
@@ -2799,7 +2901,7 @@ for (int i = 0; i < 100; ++i) {
This rule checks for duplicate String literals within the current class.
Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Spec.groovy', 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
* This rule does not search across several files at once, only in the current file, and only within the current class.
* You can suppress the error by annotating a class or method with the @SuppressWarnings('DuplicateStringLiteral') annotation.
]]>bug
@@ -2818,7 +2920,7 @@ for (int i = 0; i < 100; ++i) {
This rule checks for duplicate Map literals within the current class. This rule only checks for Maps where the keys and values are all constants or literals.
Code containing duplicate Map literals can usually be improved by declaring the Map as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Spec.groovy', 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
Examples of violations:
def var1 = [a:1, b:null, c:Boolean.FALSE, d:'x', e:true]
@@ -2859,7 +2961,7 @@ for (int i = 0; i < 100; ++i) {
This rule checks for duplicate List literals within the current class. This rule only checks for Lists where values are all constants or literals.
List literals within annotations are ignored.
Code containing duplicate List literals can usually be improved by declaring the List as a constant field.
-
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
+
By default, the rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Spec.groovy', 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'.
Examples of violations:
def var1 = [1, null, Boolean.FALSE, 'x', true]
@@ -3334,7 +3436,6 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace around each binary operator, including: +, -, *, /, >>, <<, &&, ||, &, |, ?:, =, "as".
Do not check dot ('.') operator. Do not check unary operators (!, +, -, ++, --, ?.). Do not check array ('[') operator.
Known limitations:
-
* Does not catch violations of missing space around equals operator (=) within a declaration expression, e.g. def x=23
* Does not catch violations of certain ternary expressions and standalone elvis operator (?:) expressions
Examples of violations:
@@ -3351,6 +3452,11 @@ for (int i = 0; i < 100; ++i) {
}
]]>convention
+
+ ignoreParameterDefaultValueAssignments
+
+ true
+
@@ -3360,6 +3466,7 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace before each opening brace ("\{") for method/class/interface declarations, closure expressions and block statements.
+
A closure expression a preceded by an opening parenthesis, an opening square brace ([), or a dollar sign ($) within a GString does not cause a violation.
Known limitations:
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
Examples of violations:
@@ -3402,7 +3509,7 @@ for (int i = 0; i < 100; ++i) {
conventioncheckClosureMapEntryValue
-
+ true
@@ -3448,12 +3555,12 @@ for (int i = 0; i < 100; ++i) {
conventioncheckClosureMapEntryValue
-
+ trueignoreEmptyBlock
-
+ false
@@ -3465,7 +3572,7 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace after each closing brace ("\{") for method/class/interface declarations, closure expressions and block statements.
-
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
+
A closure expression followed by a dot operator (.), a comma, a closing parenthesis, a closing square brace (]), the spread-dot operator (*.), a semicolon or the null-safe operator (?.) does not cause a violation.
Known limitations:
* May not catch actual violations if the source line contains unicode character literals, e.g. '\\u00A0'
Examples of violations and exceptions:
@@ -3477,13 +3584,14 @@ for (int i = 0; i < 100; ++i) {
assert list.every { it.isReady() }, "Error" // no violation for comma
def m = [a:123, b:{ println 7 },c:99] // no violation for comma
processItems(list.select { it.isReady() }) // no violation for closing parenthesis
+ processItems([{ named("a") }, { named("b")}]) // no violation for closing square bracket
def names = records.findAll { it.age > 1 }*.name // no violation for spread operator
list?.collect { it?.type }?.join(',') // no violation for null-safe operator
]]>conventioncheckClosureMapEntryValue
-
+ true
@@ -3531,12 +3639,12 @@ for (int i = 0; i < 100; ++i) {
conventioncheckClosureMapEntryValue
-
+ trueignoreEmptyBlock
-
+ false
@@ -4250,7 +4358,7 @@ class MyClass { // CORRECT
This rule sets the default value of applyToFilesMatching to only match files under the 'grails-app/services' folder. You can override this with a different regular expression value if appropriate.
This rule also sets the default value of applyToClassNames to only match class names ending in 'Service'. You can override this with a different class name pattern (String with wildcards) if appropriate.
[[1]] The ignoreFieldTypes property matches the field type name as indicated in the field declaration, only including a full package specification IF it is included in the source code. For example, the field declaration BigDecimal value matches an ignoreFieldTypes value of BigDecimal, but not java.lang.BigDecimal.
-
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.]]>
+
[[2]] There is one exception for the ignoreFieldTypes property: if the field is declared with a modifier/type of def, then the type resolves to java.lang.Object.
]]>
grailsaddToIgnoreFieldName
@@ -4392,6 +4500,48 @@ class MyClass { // CORRECT
grails
+
+
+ org.codenarc.rule.grails.GrailsDomainStringPropertyMaxSizeRule
+ MINOR
+
+
+ String properties in Grails domain classes have to define maximum size otherwise the property is mapped to VARCHAR(255) causing runtime exceptions to occur. To fix this issue either declare size or maxSize constraint for the property inside constraints DSL closure of your Grails domain class or declare the type of the property inside mapping DSL closure. If you use the second option inside mapping DSL closure then please pay attention that the value of type is not checked so using for example VARCHAR(50) would still cause runtime exceptions.
+
Example of violations:
+
+ // both firstName and lastName will probably have database limit of 255 characters
+ // which is not validated by Grails validation causing runtime JDBC exception
+ class Person {
+
+ String firstName
+ String lastName
+
+ static constraints = {
+ firstName nullable:true
+ lastName nullable:true
+ }
+ }
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5102,7 +5252,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
* assertFalse([])
* assertFalse([:)
* assertNull(null)
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5122,7 +5272,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
* Methods annotated with @Override
Public, non-test methods on a test class violate conventional usage of test classes, and they typically break encapsulation unnecessarily.
Public, non-test methods may also hide unintentional 'Lost Tests'. For instance, the test method declaration may (unintentionally) include methods parameters, and thus be ignored by JUnit. Or the method may (unintentionally) not follow the "test.." naming convention and not have the @Test annotation, and thus be ignored by JUnit.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junitignoreMethodsWithAnnotations
@@ -5138,7 +5288,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Rule that checks that if the JUnit setUp method is defined, that it includes a call to super.setUp().
This rule ignored methods annotated with @Before or @BeforeClass.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5149,7 +5299,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Rule that checks that if the JUnit tearDown method is defined, that it includes a call to super.tearDown().
This rule ignored methods annotated with @After or @AfterClass.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5159,7 +5309,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Rule that checks checks for JUnit setUp() methods that contain only a call to super.setUp(). The method is then unnecessary.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Here is an example of a violation:
class MyTest extends TestCase {
@@ -5177,7 +5327,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Rule that checks checks for JUnit tearDown() methods that contain only a call to super.tearDown(). The method is then unnecessary.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Here is an example of a violation:
class MyTest extends TestCase {
@@ -5206,7 +5356,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5217,7 +5367,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
In unit tests, if a condition is expected to be false then there is no sense using assertTrue with the negation operator. For instance, assertTrue(!condition) can always be simplified to assertFalse(condition).
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5228,7 +5378,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
This rule detects JUnit calling assertEquals where the first parameter is a boolean. These assertions should be made by more specific methods, like assertTrue or assertFalse.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
All of the following examples can be simplified to assertTrue or remove the true literal:
assertEquals(true, foo())
@@ -5260,7 +5410,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
This rule detects JUnit calling assertEquals where the first or second parameter is null. These assertion should be made against the assertNull method instead.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5271,7 +5421,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
This rule detects JUnit calling assertTrue or assertFalse where the first or second parameter is an Object#is() call testing for reference equality. These assertion should be made against the assertSame or assertNotSame method instead.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5292,7 +5442,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
In unit tests, if a condition is expected to be true then there is no sense using assertFalse with the negation operator. For instance, assertFalse(!condition) can always be simplified to assertTrue(condition).
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
]]>
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
]]>
junit
@@ -5379,7 +5529,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
In a unit test, catching an exception and immediately calling Assert.fail() is pointless and hides the stack trace. It is better to rethrow the exception or not catch the exception at all.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Example of violations:
public void testSomething() {
@@ -5444,7 +5594,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named test* that is not annotated with the JUnit 4 @Test annotation.
Note: This rule should be disabled for Grails 2.x projects, since the Grails test framework can use AST Transformations to automatically annotate test methods.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Example of violations:
import org.junit.Test
@@ -5463,7 +5613,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Check for throws clauses on JUnit test methods. That is not necessary in Groovy.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Example of violations:
@Test
@@ -5492,7 +5642,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Checks for public fields on a JUnit test class. There is usually no reason to have a public field (even a constant) on a test class.
Fields within interfaces and fields annotated with @Rule are ignored.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Example of violations:
import org.junit.Test
@@ -5532,7 +5682,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Checks for public properties defined on JUnit test classes. There is typically no need to expose a public property (with public getter and setter methods) on a test class.
-
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Test', 'Tests' or 'TestCase'.
+
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Example of violations:
import org.junit.Test
@@ -7668,7 +7818,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for explicit calls to setter methods which can, for the most part, be replaced by assignment to property. A setter is defined as a method call that matches set[A-Z] but not set[A-Z][A-Z] such as setURL(). Setters take one method argument.
+ Checks for explicit calls to setter methods which can, for the most part, be replaced by assignment to property. A setter is defined as a method call that matches set[A-Z] but not set[A-Z][A-Z] such as setURL(). Setters take one method argument. Setter calls within an expression are ignored.
These bits of code produce violations:
x.setProperty(1)
@@ -7677,10 +7827,12 @@ println list.collectNested { it * 2 } // same functionality, better readability
These bits of code do not:
- x.set(1)
- x.setup(2)
- x.setURL('')
- x.setSomething('arg1', 'arg2')
+ x.set(1) // Nothing after "set"
+ x.setup(2) // The letter after "set" must be capitalized
+ x.setURL('') // But setters with multiple capital letters after "set" are ignored
+ x.setSomething('arg1', 'arg2') // Setter must have exactly one argument
+ if (!file.setExecutable(true)) { } // Set method called within expression
+ def count = x.setCount(92) // Set method called within expression
]]>clumsy
@@ -7720,7 +7872,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
Checks for object allocations that are not assigned or used, unless it is the last statement within a block (because it may be the intentional return value). Examples include:
-
By default, this rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Test.groovy', 'Tests.groovy' or 'TestCase.groovy'. Invoking constructors without using the result is a common pattern in tests.
+
By default, this rule does not analyze test files. This rule sets the default value of the doNotApplyToFilesMatching property to ignore file names ending in 'Spec.groovy, ''Test.groovy', 'Tests.groovy' or 'TestCase.groovy'. Invoking constructors without using the result is a common pattern in tests.
int myMethod() {
new BigDecimal("23.45") // unused
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
index e306d112..ea8c7037 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
@@ -42,7 +42,7 @@ public void test() {
assertThat(repository.language()).isEqualTo(Groovy.KEY);
List rules = repository.rules();
- assertThat(rules).hasSize(356);
+ assertThat(rules).hasSize(361);
List missingDebt = new LinkedList<>();
for (Rule rule : rules) {
From fbdc5464a99664111aa81c96404ba45cdc37f34f Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 27 Jun 2019 21:19:46 +0200
Subject: [PATCH 66/89] Update CodeNarc to 1.3
---
codenarc-converter/CodeNarc | 2 +-
.../plugins/groovy/codenarc/Converter.java | 23 +-
.../plugins/groovy/codenarc/RuleSet.java | 1 +
pom.xml | 2 +-
.../org/sonar/plugins/groovy/cost.csv | 15 +
.../org/sonar/plugins/groovy/rules.xml | 520 +++++++++++++++++-
.../codenarc/CodeNarcRulesDefinitionTest.java | 2 +-
7 files changed, 544 insertions(+), 21 deletions(-)
diff --git a/codenarc-converter/CodeNarc b/codenarc-converter/CodeNarc
index c969a1ce..bc349adb 160000
--- a/codenarc-converter/CodeNarc
+++ b/codenarc-converter/CodeNarc
@@ -1 +1 @@
-Subproject commit c969a1ce9e6dd2b0372419fc768379f80262d124
+Subproject commit bc349adb93083b8a32f3164165e8a5753a83feee
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
index 51496845..aad9bba4 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
@@ -398,7 +398,8 @@ public static Multimap loadRules(Path aptDir)
org.codenarc.rule.formatting.BracesForIfElseRule.class,
org.codenarc.rule.formatting.BracesForMethodRule.class,
org.codenarc.rule.formatting.BracesForTryCatchFinallyRule.class,
- org.codenarc.rule.formatting.ClassJavadocRule.class,
+ // moved from formatting into comments in 1.3
+ org.codenarc.rule.comments.ClassJavadocRule.class,
org.codenarc.rule.groovyism.AssignCollectionUniqueRule.class);
insertRules(
@@ -579,6 +580,26 @@ public static Multimap loadRules(Path aptDir)
org.codenarc.rule.grails.GrailsDomainStringPropertyMaxSizeRule.class,
org.codenarc.rule.convention.NoJavaUtilDateRule.class);
+ insertRules(
+ rules,
+ "1.3",
+ props,
+ parametersByRule,
+ org.codenarc.rule.formatting.ClassEndsWithBlankLineRule.class,
+ org.codenarc.rule.formatting.ClassStartsWithBlankLineRule.class,
+ org.codenarc.rule.groovyism.ExplicitCallToPutAtMethodRule.class,
+ org.codenarc.rule.comments.JavadocEmptyFirstLineRule.class,
+ org.codenarc.rule.comments.JavadocEmptyLastLineRule.class,
+ org.codenarc.rule.comments.JavadocConsecutiveEmptyLinesRule.class,
+ org.codenarc.rule.comments.JavadocEmptySeeTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptyParamTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptyReturnTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptyThrowsTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptyExceptionTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptyAuthorTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptySinceTagRule.class,
+ org.codenarc.rule.comments.JavadocEmptyVersionTagRule.class);
+
return rules;
}
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleSet.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleSet.java
index ac04da3d..bae19e93 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleSet.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/RuleSet.java
@@ -24,6 +24,7 @@
public enum RuleSet {
BASIC("basic"),
BRACES("braces"),
+ COMMENTS("comments"), // new in 1.3
CONCURRENCY("concurrency"),
CONVENTION("convention"), // new in 0.16
DESIGN("design"),
diff --git a/pom.xml b/pom.xml
index 7351aefc..db128b6d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
org.codenarcCodeNarc
- 1.2
+ 1.3org.codehaus.groovy
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
index 778e3845..d60f08c3 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
@@ -46,6 +46,18 @@ org.codenarc.rule.braces.ElseBlockBracesRule;linear;5min
org.codenarc.rule.braces.ForStatementBracesRule;linear;5min
org.codenarc.rule.braces.IfStatementBracesRule;linear;5min
org.codenarc.rule.braces.WhileStatementBracesRule;linear;5min
+org.codenarc.rule.comments.ClassJavadocRule;linear;5min
+org.codenarc.rule.comments.JavadocConsecutiveEmptyLinesRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyAuthorTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyExceptionTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyFirstLineRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyLastLineRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyParamTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyReturnTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptySeeTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptySinceTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyThrowsTagRule;linear;5min
+org.codenarc.rule.comments.JavadocEmptyVersionTagRule;linear;5min
org.codenarc.rule.concurrency.BusyWaitRule;linear;1h
org.codenarc.rule.concurrency.DoubleCheckedLockingRule;linear;1d
org.codenarc.rule.concurrency.InconsistentPropertyLockingRule;linear;20min
@@ -150,7 +162,9 @@ org.codenarc.rule.formatting.BracesForForLoopRule;linear;5min
org.codenarc.rule.formatting.BracesForIfElseRule;linear;5min
org.codenarc.rule.formatting.BracesForMethodRule;linear;5min
org.codenarc.rule.formatting.BracesForTryCatchFinallyRule;linear;5min
+org.codenarc.rule.formatting.ClassEndsWithBlankLineRule;linear;5min
org.codenarc.rule.formatting.ClassJavadocRule;linear;10min
+org.codenarc.rule.formatting.ClassStartsWithBlankLineRule;linear;5min
org.codenarc.rule.formatting.ClosureStatementOnOpeningLineOfMultipleLineClosureRule;linear;10min
org.codenarc.rule.formatting.ConsecutiveBlankLinesRule;linear;5min
org.codenarc.rule.formatting.FileEndsWithoutNewlineRule;linear;5min
@@ -210,6 +224,7 @@ org.codenarc.rule.groovyism.ExplicitCallToMultiplyMethodRule;linear;5min
org.codenarc.rule.groovyism.ExplicitCallToOrMethodRule;linear;5min
org.codenarc.rule.groovyism.ExplicitCallToPlusMethodRule;linear;5min
org.codenarc.rule.groovyism.ExplicitCallToPowerMethodRule;linear;5min
+org.codenarc.rule.groovyism.ExplicitCallToPutAtMethodRule;linear;5min
org.codenarc.rule.groovyism.ExplicitCallToRightShiftMethodRule;linear;5min
org.codenarc.rule.groovyism.ExplicitCallToXorMethodRule;linear;5min
org.codenarc.rule.groovyism.ExplicitHashMapInstantiationRule;linear;5min
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index 865ca921..3eba5cc2 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -1,4 +1,4 @@
-
+
@@ -929,6 +929,360 @@
bug
+
+
+
+
+ org.codenarc.rule.comments.ClassJavadocRule
+ MINOR
+
+
+ Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyFirstLineRule
+ MAJOR
+
+
+ Check for javadoc comments with an empty top line.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * // violation
+ * Sample class
+ *
+ * @author Some Developer
+ */
+ class MyClass {
+
+ /**
+ * // violation
+ * Return the calculated count of some stuff,
+ * starting with the specified startIndex.
+ *
+ * @param startIndex - the starting index
+ * @return the full count
+ * @throws RuntimeException
+ */
+ int countThings(int startIndex) {
+ }
+ }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyLastLineRule
+ MAJOR
+
+
+ Check for javadoc comments with an empty line at the bottom.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Sample class
+ *
+ * @author Some Developer
+ * // violation
+ */
+ class MyClass {
+
+ /**
+ * Return the calculated count of some stuff,
+ * starting with the specified startIndex.
+ *
+ * @param startIndex - the starting index
+ * @return the full count
+ * @throws RuntimeException
+ * // violation
+ */
+ int countThings(int startIndex) {
+ }
+ }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.comments.JavadocConsecutiveEmptyLinesRule
+ MAJOR
+
+
+ Checks for javadoc comments with more than one consecutive empty line.
+
Known limitation: Only the first occurrence of consecutive empty lines within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Description
+ *
+ * // violation
+ * @param startIndex - the starting index
+ * @return the full count
+ * @throws RuntimeException
+ *
+ * NOTE: Only the first occurrence of consecutive empty lines
+ * within a javadoc comment is found, so the following
+ * lines are not flagged as violations!!!
+ *
+ *
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptySeeTagRule
+ MAJOR
+
+
+ Checks for empty @see tags within javadoc.
+
Known limitation: Only the first occurrence of an empty @see within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Sample class
+ *
+ * @see // violation
+ */
+ class MyClass {
+
+ /**
+ * Return the calculated count of some stuff,
+ * starting with the specified startIndex.
+ *
+ * @param startIndex - the starting index
+ * @return the full count
+ * @throws RuntimeException
+ * @see // violation
+ *
+ * NOTE: Only the first occurrence of an empty @see tag
+ * within a javadoc comment is found, so the
+ * following line is not flagged as a violation!!!
+ * @see
+ */
+ int countThings(int startIndex) { }
+
+ /**
+ *@see // violation
+ */
+ String name = 'joe'
+ }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyParamTagRule
+ MAJOR
+
+
+ Checks for empty @param tags within javadoc
+
Known limitation: Only the first occurrence of an empty @param within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param // violation
+ * @return the full count
+ * @throws RuntimeException
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyReturnTagRule
+ MAJOR
+
+
+ Checks for empty @return tags within javadoc.
+
Known limitation: Only the first occurrence of an empty @return within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex - the starting index
+ * @return // violation
+ * @throws RuntimeException
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyThrowsTagRule
+ MAJOR
+
+
+ Checks for empty @throws tag within javadoc.
+
Known limitation: Only the first occurrence of an empty @throws within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex - the starting index
+ * @return the count
+ * @throws // violation
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyExceptionTagRule
+ MAJOR
+
+
+ Checks for empty @exception tag within javadoc.
+
Known limitation: Only the first occurrence of an empty @exception within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex - the starting index
+ * @return the count
+ * @exception // violation
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyAuthorTagRule
+ MAJOR
+
+
+ Checks for empty @author tags within javadoc.
+
Known limitation: Only the first occurrence of an empty @author within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex - the starting index
+ * @return the count
+ * @author // violation
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptySinceTagRule
+ MAJOR
+
+
+ Checks for empty @since tags within javadoc.
+
Known limitation: Only the first occurrence of an empty @since within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex - the starting index
+ * @return the count
+ * @since // violation
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocEmptyVersionTagRule
+ MAJOR
+
+
+ Checks for empty @version tags within javadoc.
+
Known limitation: Only the first occurrence of an empty @version within a javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex - the starting index
+ * @return the count
+ * @version // violation
+ */
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
@@ -2124,6 +2478,16 @@
true
+
+ ignoreSingleElementList
+
+ true
+
+
+ ignoreSingleElementMap
+
+ true
+
@@ -2361,12 +2725,15 @@
Do not use the java.util.Date class. Prefer the classes in the java.time.* packages. This rule checks for construction of new java.util.Date objects.
+
If the class imports another Date class, then references to new Date() will not cause a violation.
Example of violations:
def timestamp = new Date() // violation
Date myDate = new java.util.Date() // violation
Date startTime = new Date(123456789L) // violation
-
]]>
+
+
Known limitations:
+
* Will cause an incorrect violation if the source code is referring to a different Date class from the current package. In that case, it may be better to just disable this rule (either per class or globally).
]]>bug
@@ -3369,17 +3736,6 @@ for (int i = 0; i < 100; ++i) {
-
-
- org.codenarc.rule.formatting.ClassJavadocRule
- MINOR
-
-
- Makes sure each class and interface definition is preceded by javadoc. Enum definitions are not checked, due to strange behavior in the Groovy AST. By default, only the main class in a file is checked for Javadoc. The main class is defined as the class that has the same name as the source file, for instance MyClass is the main class in MyClass.groovy but the class MyOtherClass defined in the same source file is not the main class. To check all the classes in the file set the rule property applyToNonMainClasses to true.
-
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>
- convention
-
-
org.codenarc.rule.formatting.SpaceAfterCommaRule
@@ -3436,7 +3792,7 @@ for (int i = 0; i < 100; ++i) {
Check that there is at least one space (blank) or whitespace around each binary operator, including: +, -, *, /, >>, <<, &&, ||, &, |, ?:, =, "as".
Do not check dot ('.') operator. Do not check unary operators (!, +, -, ++, --, ?.). Do not check array ('[') operator.
Known limitations:
-
* Does not catch violations of certain ternary expressions and standalone elvis operator (?:) expressions
+
* Does not catch violations of certain ternary expressions and standalone elvis operator (?:) expressions. * Does not catch violations of missing space around the equals operator (=) for fields initialization if the field is annotated.
+
+
+ org.codenarc.rule.formatting.ClassEndsWithBlankLineRule
+ MAJOR
+
+
+ Check whether the class ends with a blank line. By default, it enforces that there must be a blank line before the closing class brace, except if the class is empty and is written in a single line. A blank line is defined as any line that does not contain any visible characters. This rule can be configured with the following properties:
+
Example of violations:
+
If ignoreSingleLineClasses is true and blankLineRequired is true
+
+ class Foo {
+ int a
+
+ void hi() {
+ }
+ }
+
+
If ignoreSingleLineClasses is false and blankLineRequired is true
+
+ class Foo extends Bar<String> { }
+
+
If ignoreSingleLineClasses is true and blankLineRequired is false
+
+ class Foo {
+ int a
+
+ void hi() {
+ }
+
+ }
+
+
If ignoreSingleLineClasses is false and blankLineRequired is false
+
+ class Foo {
+ int a
+
+ void hi() {
+ }
+
+ }
+
]]>
+ convention
+
+ blankLineRequired
+
+ true
+
+
+ ignoreSingleLineClasses
+
+ true
+
+
+
+
+
+ org.codenarc.rule.formatting.ClassStartsWithBlankLineRule
+ MAJOR
+
+
+ Check whether the class starts with a blank line. By default, it enforces that there must be a blank line after the opening class brace, except if the class is empty and is written in a single line. A blank line is defined as any line that does not contain any visible characters. This rule can be configured with the following properties:
+
Example of violations:
+
If ignoreSingleLineClasses is true and blankLineRequired is true
+
+ class Foo {
+ int a
+
+ void hi() {
+ }
+ }
+
+
If ignoreSingleLineClasses is false and blankLineRequired is true
+
+ class Foo extends Bar<String> { }
+
+
If ignoreSingleLineClasses is true and blankLineRequired is false
+
+ class Foo {
+
+ int a
+
+ void hi() {
+ }
+
+ }
+
+
If ignoreSingleLineClasses is false and blankLineRequired is false
+
+ class Foo {
+ int a
+
+ void hi() {
+ }
+
+ }
+
]]>
+ convention
+
+ blankLineRequired
+
+ true
+
+
+ ignoreSingleLineClasses
+
+ true
+
+
+
@@ -5044,6 +5509,22 @@ println list.collectNested { it * 2 } // same functionality, better readability
groovyism
+
+
+ org.codenarc.rule.groovyism.ExplicitCallToPutAtMethodRule
+ MINOR
+
+
+ Detects when the `map.putAt(k, v)` method is called directly rather than using `map[k] = v`.
+
This rule can be configured to ignore this.putAt(k, v) using the ignoreThisReference property. It defaults to false, so even putAt(k, v) will trigger a violation.
+
This rule also ignores all calls to super.putAt(k, v).
+
Example of violations:
+
+ map.putAt(k, v) // violation
+
]]>
+ groovyism
+
+
@@ -5137,16 +5618,21 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for wildcard (star) imports. If the ignoreStaticImports property is true, then do not check static imports.
+ Checks for wildcard (star) imports. If the ignoreStaticImports property is true, then do not check static imports. Similarly, do not check the standard imports if ignoreImports is true.
Example of violations:
import static foo.bar.* // violation (unless ignoreStaticImports is true)
- import my.something.* // violation
+ import my.something.* // violation (unless ignoreImports is true)
public class MyClass{}
NOTE: This is a file-based rule, rather than a typical AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
]]>bug
+
+ ignoreImports
+
+ false
+
ignoreStaticImports
@@ -5592,7 +6078,7 @@ println list.collectNested { it * 2 } // same functionality, better readability
MINOR
- This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named test* that is not annotated with the JUnit 4 @Test annotation.
+ This rule checks for classes that import JUnit 4 classes and contain a public, instance, void, no-arg method named test* that is not abstract and not annotated with the JUnit 4 @Test annotation.
Note: This rule should be disabled for Grails 2.x projects, since the Grails test framework can use AST Transformations to automatically annotate test methods.
This rule sets the default value of the applyToClassNames property to only match class names ending in 'Spec', 'Test', 'Tests' or 'TestCase'.
Example of violations:
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
index ea8c7037..d6ec3193 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
@@ -42,7 +42,7 @@ public void test() {
assertThat(repository.language()).isEqualTo(Groovy.KEY);
List rules = repository.rules();
- assertThat(rules).hasSize(361);
+ assertThat(rules).hasSize(375);
List missingDebt = new LinkedList<>();
for (Rule rule : rules) {
From 6f09fdd42d201a6fa0977bd58d5d5beae2e1195d Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 27 Jun 2019 22:17:51 +0200
Subject: [PATCH 67/89] Update CodeNarc to 1.4
---
codenarc-converter/CodeNarc | 2 +-
.../plugins/groovy/codenarc/Converter.java | 10 +
pom.xml | 2 +-
.../org/sonar/plugins/groovy/cost.csv | 4 +
.../org/sonar/plugins/groovy/rules.xml | 195 +++++++++++++++---
.../codenarc/CodeNarcRulesDefinitionTest.java | 2 +-
6 files changed, 188 insertions(+), 27 deletions(-)
diff --git a/codenarc-converter/CodeNarc b/codenarc-converter/CodeNarc
index bc349adb..e32d9bd5 160000
--- a/codenarc-converter/CodeNarc
+++ b/codenarc-converter/CodeNarc
@@ -1 +1 @@
-Subproject commit bc349adb93083b8a32f3164165e8a5753a83feee
+Subproject commit e32d9bd5a182e70ff330dc34a811307e4c420377
diff --git a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
index aad9bba4..eaad4aa8 100644
--- a/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
+++ b/codenarc-converter/src/main/java/org/sonar/plugins/groovy/codenarc/Converter.java
@@ -600,6 +600,16 @@ public static Multimap loadRules(Path aptDir)
org.codenarc.rule.comments.JavadocEmptySinceTagRule.class,
org.codenarc.rule.comments.JavadocEmptyVersionTagRule.class);
+ insertRules(
+ rules,
+ "1.4",
+ props,
+ parametersByRule,
+ org.codenarc.rule.convention.CompileStaticRule.class,
+ org.codenarc.rule.comments.JavadocMissingParamDescriptionRule.class,
+ org.codenarc.rule.comments.JavadocMissingThrowsDescriptionRule.class,
+ org.codenarc.rule.comments.JavadocMissingExceptionDescriptionRule.class);
+
return rules;
}
diff --git a/pom.xml b/pom.xml
index db128b6d..d997c9fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
org.codenarcCodeNarc
- 1.3
+ 1.4org.codehaus.groovy
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
index d60f08c3..79037e59 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/cost.csv
@@ -58,6 +58,9 @@ org.codenarc.rule.comments.JavadocEmptySeeTagRule;linear;5min
org.codenarc.rule.comments.JavadocEmptySinceTagRule;linear;5min
org.codenarc.rule.comments.JavadocEmptyThrowsTagRule;linear;5min
org.codenarc.rule.comments.JavadocEmptyVersionTagRule;linear;5min
+org.codenarc.rule.comments.JavadocMissingExceptionDescriptionRule;linear;5min
+org.codenarc.rule.comments.JavadocMissingParamDescriptionRule;linear;5min
+org.codenarc.rule.comments.JavadocMissingThrowsDescriptionRule;linear;5min
org.codenarc.rule.concurrency.BusyWaitRule;linear;1h
org.codenarc.rule.concurrency.DoubleCheckedLockingRule;linear;1d
org.codenarc.rule.concurrency.InconsistentPropertyLockingRule;linear;20min
@@ -84,6 +87,7 @@ org.codenarc.rule.concurrency.UseOfNotifyMethodRule;linear;20min
org.codenarc.rule.concurrency.VolatileArrayFieldRule;linear;1h
org.codenarc.rule.concurrency.VolatileLongOrDoubleFieldRule;linear;1h
org.codenarc.rule.concurrency.WaitOutsideOfWhileLoopRule;linear;1h
+org.codenarc.rule.convention.CompileStaticRule;linear;5min
org.codenarc.rule.convention.ConfusingTernaryRule;linear;10min
org.codenarc.rule.convention.CouldBeElvisRule;linear;10min
org.codenarc.rule.convention.CouldBeSwitchStatementRule;linear;5min
diff --git a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
index 3eba5cc2..3b8c94fb 100644
--- a/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
+++ b/sonar-groovy-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml
@@ -1,4 +1,4 @@
-
+
@@ -967,7 +967,7 @@
*
* @param startIndex - the starting index
* @return the full count
- * @throws RuntimeException
+ * @throws RuntimeException when the Singularity occurs
*/
int countThings(int startIndex) {
}
@@ -1000,7 +1000,7 @@
*
* @param startIndex - the starting index
* @return the full count
- * @throws RuntimeException
+ * @throws RuntimeException when life finds a way
* // violation
*/
int countThings(int startIndex) {
@@ -1027,7 +1027,7 @@
* // violation
* @param startIndex - the starting index
* @return the full count
- * @throws RuntimeException
+ * @throws RuntimeException if you are not pure of spirit
*
* NOTE: Only the first occurrence of consecutive empty lines
* within a javadoc comment is found, so the following
@@ -1064,7 +1064,7 @@
*
* @param startIndex - the starting index
* @return the full count
- * @throws RuntimeException
+ * @throws RuntimeException when you least expect it
* @see // violation
*
* NOTE: Only the first occurrence of an empty @see tag
@@ -1104,7 +1104,7 @@
*
* @param // violation
* @return the full count
- * @throws RuntimeException
+ * @throws RuntimeException upon self-reflection
*/
int countThings(int startIndex) { }
]]>
@@ -1132,7 +1132,7 @@
*
* @param startIndex - the starting index
* @return // violation
- * @throws RuntimeException
+ * @throws RuntimeException if you don't say "please"
*/
int countThings(int startIndex) { }
]]>
@@ -1283,6 +1283,90 @@
+
+
+ org.codenarc.rule.comments.JavadocMissingParamDescriptionRule
+ MAJOR
+
+
+ Checks for missing description within Javadoc @param tags.
+
Known limitation: Only the first occurrence of a missing description for a @param javadoc comment is found
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex // violation
+ * @return the full count
+ * @throws RuntimeException if it senses fear
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocMissingThrowsDescriptionRule
+ MAJOR
+
+
+ Checks for missing description within Javadoc @throws tags.
+
Known limitation: Only the first occurrence of a missing description for a @throws javadoc comment is found
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex the starting index; must be >= 0
+ * @return the full count
+ * @throws RuntimeException // violation
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
+
+
+ org.codenarc.rule.comments.JavadocMissingExceptionDescriptionRule
+ MAJOR
+
+
+ Checks for missing description within @exception javadoc tags.
+
Known limitation: Only the first occurrence of a missing description for an @exception javadoc comment is found.
+
NOTE: This is a file-based rule, rather than an AST-based rule, so the applyToClassNames and doNotApplyToClassNames rule configuration properties are not available. See Standard Properties for Configuring Rules.
+
Example of violations:
+
+ /**
+ * Return the calculated count of some stuff.
+ *
+ * @param startIndex the starting index; must be >= 0
+ * @return the full count
+ * @exception RuntimeException // violation
+ */
+ int countThings(int startIndex) { }
+
]]>
+ bug
+
+ allowMultiline
+
+ false
+
+
+
@@ -2737,6 +2821,16 @@
bug
+
+
+ org.codenarc.rule.convention.CompileStaticRule
+ MINOR
+
+
+ Enforces classes are annotated either with one of the @CompileStatic, @GrailsCompileStatic or @CompileDynamic annotations.]]>
+ bug
+
+
@@ -4296,6 +4390,15 @@ for (int i = 0; i < 100; ++i) {
println 'switch'
// violation
}
+
+ // Known Limitation: If a Closure is within another expression and the closing brace is not followed by anything else on the same line
+
+ def list = [
+ 123,
+ { id ->
+ // Known limitation: should be a violation, but is not
+ }
+ ]
]]>convention
@@ -4378,6 +4481,7 @@ for (int i = 0; i < 100; ++i) {
* Does not check line-continuations (i.e., checks only the first line of a statement)
* Does not check multiple statements/members on the same line (only checks the first one)
* Does not check Map entry expressions
+
* Does not check List expressions
* Does not check calls to this() and super() within a constructor
* When classes, methods or fields have annotations, the indentation of the annotation is checked, not the actual member. And only the first annotation is checked, if there is more than one.
Example of violations:
@@ -4421,9 +4525,14 @@ class MyClass { // CORRECT
MAJOR
- Check whether the class ends with a blank line. By default, it enforces that there must be a blank line before the closing class brace, except if the class is empty and is written in a single line. A blank line is defined as any line that does not contain any visible characters. This rule can be configured with the following properties:
+ Check whether the class ends with a blank line. By default, it enforces that there must be a blank line before the closing class brace, except:
+
* If the class is synthetic (generated)
+
* If the class is empty and is written in a single line
+
* If the class is a Script class
+
A blank line is defined as any line that does not contain any visible characters.
+
This rule can be configured with the following properties:
Example of violations:
-
If ignoreSingleLineClasses is true and blankLineRequired is true
+
If ignoreSingleLineClasses is true and blankLineRequired is true
class Foo {
int a
@@ -4432,11 +4541,11 @@ class MyClass { // CORRECT
}
}
-
If ignoreSingleLineClasses is false and blankLineRequired is true
+
If ignoreSingleLineClasses is false and blankLineRequired is true
class Foo extends Bar<String> { }
-
If ignoreSingleLineClasses is true and blankLineRequired is false
+
If ignoreSingleLineClasses is true and blankLineRequired is false
class Foo {
int a
@@ -4446,7 +4555,7 @@ class MyClass { // CORRECT
}
-
If ignoreSingleLineClasses is false and blankLineRequired is false
+
If ignoreSingleLineClasses is false and blankLineRequired is false
class Foo {
int a
@@ -4462,6 +4571,11 @@ class MyClass { // CORRECT
true
+
+ ignoreInnerClasses
+
+ false
+
ignoreSingleLineClasses
@@ -4475,9 +4589,14 @@ class MyClass { // CORRECT
MAJOR
- Check whether the class starts with a blank line. By default, it enforces that there must be a blank line after the opening class brace, except if the class is empty and is written in a single line. A blank line is defined as any line that does not contain any visible characters. This rule can be configured with the following properties:
+ Check whether the class starts with a blank line. By default, it enforces that there must be a blank line after the opening class brace, except:
+
* If the class is synthetic (generated)
+
* If the class is empty and is written in a single line
+
* If the class is a Script class
+
A blank line is defined as any line that does not contain any visible characters.
+
This rule can be configured with the following properties:
Example of violations:
-
If ignoreSingleLineClasses is true and blankLineRequired is true
+
If ignoreSingleLineClasses is true and blankLineRequired is true
class Foo {
int a
@@ -4486,11 +4605,11 @@ class MyClass { // CORRECT
}
}
-
If ignoreSingleLineClasses is false and blankLineRequired is true
+
If ignoreSingleLineClasses is false and blankLineRequired is true
class Foo extends Bar<String> { }
-
If ignoreSingleLineClasses is true and blankLineRequired is false
+
If ignoreSingleLineClasses is true and blankLineRequired is false
class Foo {
@@ -4501,7 +4620,7 @@ class MyClass { // CORRECT
}
-
If ignoreSingleLineClasses is false and blankLineRequired is false
+
If ignoreSingleLineClasses is false and blankLineRequired is false
class Foo {
int a
@@ -4514,12 +4633,17 @@ class MyClass { // CORRECT
conventionblankLineRequired
-
+ true
+
+ ignoreInnerClasses
+
+ false
+
ignoreSingleLineClasses
-
+ true
@@ -5325,13 +5449,24 @@ class MyClass { // CORRECT
MINOR
- The Collections.unique() method mutates the list and returns the list as a value. If you are assigning the result of unique() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs. This violation is triggered when a unique() method call appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
+ The Collections.unique() method mutates the list and returns the list as a value. If you are assigning the result of unique() to a variable, then you probably don't realize that you're also modifying the original list as well. This is frequently the cause of subtle bugs.
+
This violation is triggered when a unique() method call that mutates the target collection appears as the right hand side of an assignment, or when it appears as the first method call in a series of chained method calls.
Example of violations:
- def a = myList.unique()
- def b = myList.unique() { it }
- def c = myList.unique().findAll { x < 1 }
+ def a = myList.unique() // No-argument
+
+ def x = myList.unique() { it } // Single-argument: Closure
+ def y = myList.unique { it % 2 }
+
+ def c = myList.unique().findAll { x < 1 } // Chained method call
+ def comparator = { o1, o2 -> o1 <=> o2 }
+ def x = myList.unique(comparator) // Single-argument: Comparator
+
+ def x = myList.unique(true) // Single-argument: boolean true
+
+ def x = myList.unique(true, comparator) // Two arguments: boolean true and Comparator
+ def y = myList.unique(true) { it } // Two arguments: boolean true and Closure
]]>groovyism
@@ -7494,13 +7629,16 @@ println list.collectNested { it * 2 } // same functionality, better readability
MAJOR
- Checks for explicit calls to getter/accessor methods which can, for the most part, be replaced by property access. A getter is defined as a method call that matches get[A-Z] but not getClass() or get[A-Z][A-Z] such as getURL(). Getters do not take method arguments.
+ Checks for explicit calls to getter/accessor methods which can, for the most part, be replaced by property access. A getter is defined as a no-argument method call that matches get[A-Z] but not getClass() or get[A-Z][A-Z] such as getURL().
These bits of code produce violations:
x.getProperty()
x.getFirst()
x.getFirstName()
x.getA()
+
+ x.isFirst() // Violation if checkIsMethods is true
+ x.isA() // Violation if checkIsMethods is true
These bits of code do not:
@@ -7513,6 +7651,15 @@ println list.collectNested { it * 2 } // same functionality, better readability
x.getProperty('key')
]]>clumsy
+
+ checkIsMethods
+
+ true
+
+
+ ignoreMethodNames
+
+
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
index d6ec3193..c0d15e47 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/CodeNarcRulesDefinitionTest.java
@@ -42,7 +42,7 @@ public void test() {
assertThat(repository.language()).isEqualTo(Groovy.KEY);
List rules = repository.rules();
- assertThat(rules).hasSize(375);
+ assertThat(rules).hasSize(379);
List missingDebt = new LinkedList<>();
for (Rule rule : rules) {
From a27f6641a1ab5fbd6f7b997ba7407fb0793f4f27 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sat, 29 Jun 2019 12:59:59 +0200
Subject: [PATCH 68/89] Minor README updates
---
README.md | 59 +++++++++++++++++++++++++++++++++++++------------------
1 file changed, 40 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
index 18f3f094..5a5c4a41 100644
--- a/README.md
+++ b/README.md
@@ -11,13 +11,16 @@ Get test builds from [AppVeyor](https://ci.appveyor.com/project/TobiX/sonar-groo
This plugin enables analysis of Groovy within SonarQube.
-It leverages [CodeNarc](http://codenarc.sourceforge.net/) to raise issues against coding rules, [GMetrics](http://gmetrics.sourceforge.net/) for cyclomatic complexity and [Cobertura](http://cobertura.sourceforge.net/) or [JaCoCo](http://www.eclemma.org/jacoco/) for code coverage.
+It leverages [CodeNarc](http://codenarc.sourceforge.net/) to raise issues
+against coding rules, [GMetrics](http://gmetrics.sourceforge.net/) for
+cyclomatic complexity and [Cobertura](http://cobertura.sourceforge.net/) or
+[JaCoCo](http://www.eclemma.org/jacoco/) for code coverage.
Plugin | 1.4/1.5 | 1.6
----------|---------|---------
-CodeNarc | 0.25.2 | 0.25.2
-GMetrics | 0.7 | 0.7
-SonarQube | 5.6-6.7 | 6.7-7.5
+CodeNarc | 0.25.2 | 1.4
+GMetrics | 0.7 | 1.0
+SonarQube | 5.6-6.7 | 6.7-7.8
## Steps to Analyze a Groovy Project
1. Install SonarQube Server
@@ -28,34 +31,52 @@ SonarQube | 5.6-6.7 | 6.7-7.5
1. Follow the link provided at the end of the analysis to browse your project's quality in SonarQube UI
## Notes
-*CodeNarc*
-It is possible to reuse a previously generated report from CodeNarc by setting the `sonar.groovy.codenarc.reportPaths` property.
-*Groovy File Suffixes*
-It is possible to define multiple groovy file suffixes to be recognized by setting the `sonar.groovy.file.suffixes` property. Note that by default, only files having `.groovy` as extension will be analyzed.
+*CodeNarc*: It is possible to reuse a previously generated report from CodeNarc
+by setting the `sonar.groovy.codenarc.reportPaths` property.
-*Unit Tests Execution Reports*
-Import unit tests execution reports (JUnit XML format) by setting the sonar.junit.reportsPath property. Default location is _target/surefire-reports_.
+*Groovy File Suffixes*: It is possible to define multiple groovy file suffixes
+to be recognized by setting the `sonar.groovy.file.suffixes` property. Note
+that by default, only files having `.groovy` as extension will be analyzed.
-*JaCoCo and Binaries*
-The groovy plugin requires access to source binaries when analyzing JaCoCo reports. Consequently, property `sonar.groovy.binaries` has to be configured for the analysis (comma-separated paths to binary folders). For Maven and gradle projects, the property is automatically set.
+*Unit Tests Execution Reports*: Import unit tests execution reports (JUnit XML
+format) by setting the sonar.junit.reportsPath property. Default location is
+_target/surefire-reports_.
+
+*JaCoCo and Binaries*: The groovy plugin requires access to source binaries
+when analyzing JaCoCo reports. Consequently, property `sonar.groovy.binaries`
+has to be configured for the analysis (comma-separated paths to binary
+folders). For Maven and gradle projects, the property is automatically set.
## Coverage Results Import
-The Groovy Plugin does not generate its own test coverage report, but re-uses the ones generated by Cobertura or JaCoCo.
+
+The Groovy Plugin does not generate its own test coverage report, but re-uses
+the ones generated by Cobertura or JaCoCo.
### Code Coverage with Cobertura
+
To display code coverage data:
-1. Prior to the SonarQube analysis, execute your unit tests and generate the Cobertura XML report.
-1. Import this report while running the SonarQube analysis by setting the `sonar.groovy.cobertura.reportPath` property to the path to the Cobertura XML report. The path may be absolute or relative to the project base directory.
+1. Prior to the SonarQube analysis, execute your unit tests and generate the
+ Cobertura XML report.
+1. Import this report while running the SonarQube analysis by setting the
+ `sonar.groovy.cobertura.reportPath` property to the path to the Cobertura
+ XML report. The path may be absolute or relative to the project base
+ directory.
### Code Coverage with JaCoCo
+
To display code coverage data:
-1. Prior to the SonarQube analysis, execute your tests and generate the JaCoCo exec file(s).
-1. In order to be able to read the exec report file, and as JaCoCo bases its analysis on binaries, set the `sonar.groovy.binaries` property.
-1. Set the `sonar.groovy.jacoco.reportPath` property to the path to the JaCoCo exec file related to your unit tests.
-1. (Optional) If you are running integration tests on top of your unit tests, you may want to set the `sonar.groovy.jacoco.itReportPath` to the path to JaCoCo exec file related to the integration tests.
+1. Prior to the SonarQube analysis, execute your tests and generate the JaCoCo
+ exec file(s).
+1. In order to be able to read the exec report file, and as JaCoCo bases its
+ analysis on binaries, set the `sonar.groovy.binaries` property.
+1. Set the `sonar.groovy.jacoco.reportPath` property to the path to the JaCoCo
+ exec file related to your unit tests.
+1. (Optional) If you are running integration tests on top of your unit tests,
+ you may want to set the `sonar.groovy.jacoco.itReportPath` to the path to
+ JaCoCo exec file related to the integration tests.
1. Run the SonarQube analysis.
## Contributions
From 1ace6cc0bdb550b319a8e3f7bd58571aa76c80b6 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sat, 29 Jun 2019 16:11:26 +0200
Subject: [PATCH 69/89] Add changelog
---
CHANGELOG.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 CHANGELOG.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..1915f257
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,64 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+
+## [Unreleased]
+
+### Added
+- This changelog
+
+### Changed
+- Moved project from SonarSource to community
+- Update plugin to be compatible with SonarQube 6.7-7.8
+- Analyze plugin on SonarCloud
+- Do CI builds on Travis & AppVeyor
+- Integrate codenarc converter into the default build
+- Include CodeNarc as a git submodule (so the converter can run on Travis)
+- Fix a bunch of deprecated constructs
+- Only report overall JaCoCo test coverage
+- Updated CodeNarc to 1.4 & GMetrics to 1.0
+
+### Fixed
+- fix multiple codenarc files (pmayweg#60)
+- Fix bug in JaCoCo package name handling (pmayweg#74)
+- Update JaCoCo for Java 10+ support
+- Remove old metrics (fixes #6)
+
+### Removed
+- Coupling metrics, since SonarQube doesn't support them anymore
+
+## [1.5] - 2017-05-10
+
+Please see the Git history for older changes
+
+## [1.4-RC1] - 2016-08-05
+
+## [1.3.1] - 2015-12-02
+
+## [1.3] - 2015-11-06
+
+## [1.2] - 2015-08-12
+
+## [1.1.1] - 2015-05-28
+
+## [1.1] - 2015-03-17
+
+## [1.0.1] - 2014-03-14
+
+## [1.0] - 2014-02-24
+
+## [0.6] - 2012-08-06
+
+[Unreleased]: https://github.com/Inform-Software/sonar-groovy/compare/1.5...HEAD
+[1.5]: https://github.com/Inform-Software/sonar-groovy/compare/1.4-RC1..1.5
+[1.4-RC1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3.1..1.4-RC1
+[1.3.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3..1.3.1
+[1.3]: https://github.com/Inform-Software/sonar-groovy/compare/1.2..1.3
+[1.2]: https://github.com/Inform-Software/sonar-groovy/compare/1.1.1..1.2
+[1.1.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.1..1.1.1
+[1.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.0.1..1.1
+[1.0.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.0..1.0.1
+[1.0]: https://github.com/Inform-Software/sonar-groovy/compare/0.6..1.0
+[0.6]: https://github.com/Inform-Software/sonar-groovy/releases/tag/0.6
+
From 6f5204d09ba474b1c88138a689fa1e343f622475 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sat, 29 Jun 2019 16:48:07 +0200
Subject: [PATCH 70/89] Fix diff ranges in changelog
---
CHANGELOG.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1915f257..ab8d3668 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -51,14 +51,14 @@ Please see the Git history for older changes
## [0.6] - 2012-08-06
[Unreleased]: https://github.com/Inform-Software/sonar-groovy/compare/1.5...HEAD
-[1.5]: https://github.com/Inform-Software/sonar-groovy/compare/1.4-RC1..1.5
-[1.4-RC1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3.1..1.4-RC1
-[1.3.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3..1.3.1
-[1.3]: https://github.com/Inform-Software/sonar-groovy/compare/1.2..1.3
-[1.2]: https://github.com/Inform-Software/sonar-groovy/compare/1.1.1..1.2
-[1.1.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.1..1.1.1
-[1.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.0.1..1.1
-[1.0.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.0..1.0.1
-[1.0]: https://github.com/Inform-Software/sonar-groovy/compare/0.6..1.0
+[1.5]: https://github.com/Inform-Software/sonar-groovy/compare/1.4-RC1...1.5
+[1.4-RC1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3.1...1.4-RC1
+[1.3.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3...1.3.1
+[1.3]: https://github.com/Inform-Software/sonar-groovy/compare/1.2...1.3
+[1.2]: https://github.com/Inform-Software/sonar-groovy/compare/1.1.1...1.2
+[1.1.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.1...1.1.1
+[1.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.0.1...1.1
+[1.0.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.0...1.0.1
+[1.0]: https://github.com/Inform-Software/sonar-groovy/compare/0.6...1.0
[0.6]: https://github.com/Inform-Software/sonar-groovy/releases/tag/0.6
From 6d2e724ac1d5805e045fb3dfb6fdbb9c48eb4a37 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sun, 30 Jun 2019 14:22:01 +0200
Subject: [PATCH 71/89] Update parent and dependencies
---
.mvn/maven.config | 1 +
codenarc-converter/pom.xml | 12 +++----
.../groovy/codenarc/ConverterTest.java | 3 +-
pom.xml | 31 +++++--------------
sonar-groovy-plugin/pom.xml | 14 ++++-----
5 files changed, 22 insertions(+), 39 deletions(-)
create mode 100644 .mvn/maven.config
diff --git a/.mvn/maven.config b/.mvn/maven.config
new file mode 100644
index 00000000..c7de7245
--- /dev/null
+++ b/.mvn/maven.config
@@ -0,0 +1 @@
+-Pcoverage
diff --git a/codenarc-converter/pom.xml b/codenarc-converter/pom.xml
index 488234a7..0adeea5d 100644
--- a/codenarc-converter/pom.xml
+++ b/codenarc-converter/pom.xml
@@ -1,7 +1,5 @@
-
+4.0.0
@@ -15,8 +13,7 @@
Sonar CodeNarc Converter
- true
- 1.6.4
+ 1.6.5
@@ -27,7 +24,8 @@
com.googlecode.java-diff-utilsdiffutils
- 1.2.1
+ 1.3.0
+ testorg.sonarsource.sonarqube
@@ -46,7 +44,7 @@
com.google.guavaguava
- 27.0.1-jre
+ 28.0-jrecommons-io
diff --git a/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java b/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
index 6b404f9b..06589f09 100644
--- a/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
+++ b/codenarc-converter/src/test/java/org/sonar/plugins/groovy/codenarc/ConverterTest.java
@@ -22,7 +22,6 @@
import static org.junit.Assume.assumeTrue;
import com.google.common.collect.Lists;
-import difflib.Delta;
import difflib.DiffUtils;
import difflib.Patch;
import java.io.IOException;
@@ -78,7 +77,7 @@ static void showDelta(String ruleName, List s1, List s2) {
"------------------------------------------------------------------------------------------");
log.info("DIFFERENCE in {}", ruleName);
Patch p = DiffUtils.diff(s1, s2);
- for (Delta delta : p.getDeltas()) {
+ for (Object delta : p.getDeltas()) {
log.info("{}", delta);
}
}
diff --git a/pom.xml b/pom.xml
index d997c9fa..1ac4fced 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.parentparent
- 49
+ 52org.sonarsource.groovy
@@ -55,7 +55,8 @@
scm:git:git@github.com:Inform-Software/sonar-groovy.git
- scm:git:git@github.com:Inform-Software/sonar-groovy.git
+ scm:git:git@github.com:Inform-Software/sonar-groovy.git
+ https://github.com/Inform-Software/sonar-groovyHEAD
@@ -71,11 +72,11 @@
6.70.7.4.201502262128
- 0.8.2
- 2.4.16
+ 2.4.173.11
-
- sonar-groovy
+
+ true
+ 3.3.9SonarSource SA & Community
@@ -138,7 +139,7 @@
org.assertjassertj-core
- 3.11.1
+ 3.12.2test
@@ -162,21 +163,5 @@
-
-
- org.jacoco
- jacoco-maven-plugin
- ${jacoco.version}
-
-
- prepare-agent
-
- prepare-agent
- prepare-agent-integration
-
-
-
-
-
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index 264e93e0..b3158a65 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -26,9 +26,9 @@
- com.google.code.findbugs
- jsr305
- 3.0.2
+ com.github.spotbugs
+ spotbugs-annotations
+ 3.1.12provided
@@ -44,7 +44,7 @@
org.apache.antant
- 1.10.5
+ 1.10.6commons-io
@@ -62,7 +62,7 @@
com.fasterxml.woodstoxwoodstox-core
- 5.2.0
+ 5.2.1
@@ -73,7 +73,7 @@
org.jacocoorg.jacoco.core
- ${jacoco.version}
+ ${version.jacoco.plugin}
@@ -94,7 +94,7 @@
org.mockitomockito-core
- 2.23.4
+ 2.28.2test
From 8b4057ab0d0d5651b74022d6da2cf8612ec727a2 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Wed, 3 Jul 2019 00:26:11 +0200
Subject: [PATCH 72/89] Add support for SonarQube 7.9
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 905ae517..18b197f7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,7 @@ env:
- SONAR_VERSION=7.6
- SONAR_VERSION=7.7
- SONAR_VERSION=7.8
+- SONAR_VERSION=7.9
# Install step is redundant
install: true
From 3e386467d5ff4ae3f496cb63423b35bb3f89eefd Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 4 Jul 2019 21:05:16 +0200
Subject: [PATCH 73/89] Travis: Test against Java 8 & 11
---
.github/travis-build.sh | 3 ++-
.travis.yml | 4 +---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/.github/travis-build.sh b/.github/travis-build.sh
index 3b5103bd..9cd8b991 100755
--- a/.github/travis-build.sh
+++ b/.github/travis-build.sh
@@ -11,7 +11,8 @@ then
elif [ -n "$SONAR_SCANNER_HOME" ]
then
# Only run SonarQube analysis on one Travis-CI matrix configuration
- add="sonar:sonar $add"
+ # (namely: empty $SONAR_VERSION and Java 8
+ java -Xmx32m -version 2>&1 | grep -q 1.8.0 && add="sonar:sonar $add"
fi
mvn -B -V -e -Dstyle.color=always verify $add
diff --git a/.travis.yml b/.travis.yml
index 18b197f7..aa58fdcf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,11 +2,9 @@ language: java
jdk:
- openjdk8
+- openjdk11
env:
- SONAR_VERSION=
-- SONAR_VERSION=7.5
-- SONAR_VERSION=7.6
-- SONAR_VERSION=7.7
- SONAR_VERSION=7.8
- SONAR_VERSION=7.9
From 028c327120a95ee260eaee73eeda74035d27d7b2 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 4 Jul 2019 21:38:21 +0200
Subject: [PATCH 74/89] Configure maven-release-plugin
---
pom.xml | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 1ac4fced..d31feab1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,8 +74,6 @@
0.7.4.2015022621282.4.173.11
-
- true3.3.9SonarSource SA & Community
@@ -161,6 +159,16 @@
fmt-maven-plugin2.8
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.3
+
+ true
+ @{project.version}
+ install
+
+
From 612d9fddd92cabac62c19bad70bfd605fa273998 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 4 Jul 2019 21:59:37 +0200
Subject: [PATCH 75/89] [maven-release-plugin] prepare release 1.6
---
codenarc-converter/pom.xml | 2 +-
groovy-jacoco-previous/pom.xml | 2 +-
pom.xml | 4 ++--
sonar-groovy-plugin/pom.xml | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/codenarc-converter/pom.xml b/codenarc-converter/pom.xml
index 0adeea5d..ad9a0c42 100644
--- a/codenarc-converter/pom.xml
+++ b/codenarc-converter/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.6-SNAPSHOT
+ 1.6sonar-codenarc-converter
diff --git a/groovy-jacoco-previous/pom.xml b/groovy-jacoco-previous/pom.xml
index 54763f3b..39635797 100644
--- a/groovy-jacoco-previous/pom.xml
+++ b/groovy-jacoco-previous/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.6-SNAPSHOT
+ 1.6groovy-jacoco-previous
diff --git a/pom.xml b/pom.xml
index d31feab1..81c6e3cc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
org.sonarsource.groovygroovy
- 1.6-SNAPSHOT
+ 1.6pomSonar Groovy
@@ -58,7 +58,7 @@
scm:git:git@github.com:Inform-Software/sonar-groovy.git
https://github.com/Inform-Software/sonar-groovy
- HEAD
+ 1.6GitHub
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index b3158a65..38c0379f 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.6-SNAPSHOT
+ 1.6sonar-groovy-plugin
From 3e026570585a9cf51cd73faab02ba24a377850f6 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 4 Jul 2019 21:59:44 +0200
Subject: [PATCH 76/89] [maven-release-plugin] prepare for next development
iteration
---
codenarc-converter/pom.xml | 2 +-
groovy-jacoco-previous/pom.xml | 2 +-
pom.xml | 4 ++--
sonar-groovy-plugin/pom.xml | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/codenarc-converter/pom.xml b/codenarc-converter/pom.xml
index ad9a0c42..be426258 100644
--- a/codenarc-converter/pom.xml
+++ b/codenarc-converter/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.6
+ 1.7-SNAPSHOTsonar-codenarc-converter
diff --git a/groovy-jacoco-previous/pom.xml b/groovy-jacoco-previous/pom.xml
index 39635797..4c727bfb 100644
--- a/groovy-jacoco-previous/pom.xml
+++ b/groovy-jacoco-previous/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.6
+ 1.7-SNAPSHOTgroovy-jacoco-previous
diff --git a/pom.xml b/pom.xml
index 81c6e3cc..6025848d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
org.sonarsource.groovygroovy
- 1.6
+ 1.7-SNAPSHOTpomSonar Groovy
@@ -58,7 +58,7 @@
scm:git:git@github.com:Inform-Software/sonar-groovy.git
https://github.com/Inform-Software/sonar-groovy
- 1.6
+ HEADGitHub
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index 38c0379f..6e123bb9 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.6
+ 1.7-SNAPSHOTsonar-groovy-plugin
From 3219bb6dc250489a7a8277f775fc7f826c1a909a Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Thu, 4 Jul 2019 22:03:37 +0200
Subject: [PATCH 77/89] Update README and CHANGELOG
---
CHANGELOG.md | 5 ++++-
README.md | 10 +++++-----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab8d3668..9ef1bb01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
+## [1.6] - 2019-07-04
+
### Added
- This changelog
@@ -50,7 +52,8 @@ Please see the Git history for older changes
## [0.6] - 2012-08-06
-[Unreleased]: https://github.com/Inform-Software/sonar-groovy/compare/1.5...HEAD
+[Unreleased]: https://github.com/Inform-Software/sonar-groovy/compare/1.6...HEAD
+[1.6]: https://github.com/Inform-Software/sonar-groovy/compare/1.5...1.6
[1.5]: https://github.com/Inform-Software/sonar-groovy/compare/1.4-RC1...1.5
[1.4-RC1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3.1...1.4-RC1
[1.3.1]: https://github.com/Inform-Software/sonar-groovy/compare/1.3...1.3.1
diff --git a/README.md b/README.md
index 5a5c4a41..24c3e51d 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,11 @@ against coding rules, [GMetrics](http://gmetrics.sourceforge.net/) for
cyclomatic complexity and [Cobertura](http://cobertura.sourceforge.net/) or
[JaCoCo](http://www.eclemma.org/jacoco/) for code coverage.
-Plugin | 1.4/1.5 | 1.6
-----------|---------|---------
-CodeNarc | 0.25.2 | 1.4
-GMetrics | 0.7 | 1.0
-SonarQube | 5.6-6.7 | 6.7-7.8
+Plugin | 1.4/1.5 | 1.6 | 1.7
+----------|---------|---------|-----
+CodeNarc | 0.25.2 | 1.4 | 1.4
+GMetrics | 0.7 | 1.0 | 1.0
+SonarQube | 5.6-6.7 | 6.7-7.9 | 7.9
## Steps to Analyze a Groovy Project
1. Install SonarQube Server
From 0999d2bc9878f80a04bfc5528959b4e6898bfa38 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Tue, 10 Dec 2019 14:34:02 +0100
Subject: [PATCH 78/89] Remove backward compatibility hacks
This makes the oldest supported SonarQube version 7.8.
---
.travis.yml | 2 +-
CHANGELOG.md | 4 +
README.md | 2 +-
pom.xml | 2 +-
sonar-groovy-plugin/pom.xml | 5 --
.../plugins/groovy/GroovyPluginTest.java | 23 +----
.../codenarc/ActiveRulesBuilderWrapper.java | 88 ++-----------------
7 files changed, 18 insertions(+), 108 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index aa58fdcf..9e1c7632 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,8 +5,8 @@ jdk:
- openjdk11
env:
- SONAR_VERSION=
-- SONAR_VERSION=7.8
- SONAR_VERSION=7.9
+#- SONAR_VERSION=8.0 - not compatible yet
# Install step is redundant
install: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ef1bb01..4570bb8b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
+### Changed
+- Remove backwards compatibility hacks (drop support for everything older then
+ SonarQube 7.8)
+
## [1.6] - 2019-07-04
### Added
diff --git a/README.md b/README.md
index 24c3e51d..4b32a052 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Plugin | 1.4/1.5 | 1.6 | 1.7
----------|---------|---------|-----
CodeNarc | 0.25.2 | 1.4 | 1.4
GMetrics | 0.7 | 1.0 | 1.0
-SonarQube | 5.6-6.7 | 6.7-7.9 | 7.9
+SonarQube | 5.6-6.7 | 6.7-7.9 | 7.8-7.9
## Steps to Analyze a Groovy Project
1. Install SonarQube Server
diff --git a/pom.xml b/pom.xml
index 6025848d..a4b36031 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,7 +70,7 @@
- 6.7
+ 7.80.7.4.2015022621282.4.173.11
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index 6e123bb9..a9ecff99 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -13,12 +13,7 @@
Sonar Groovy PluginCode Analyzer for Groovy
- https://github.com/Inform-Software/sonar-groovy
-
org.sonar.plugins.groovy.GroovyPluginGroovy
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java
index 7168780c..c0653eb9 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/GroovyPluginTest.java
@@ -21,38 +21,23 @@
import static org.assertj.core.api.Assertions.assertThat;
-import groovy.lang.Binding;
-import groovy.lang.GroovyShell;
import org.junit.Test;
import org.sonar.api.Plugin;
+import org.sonar.api.SonarEdition;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarRuntime;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.utils.Version;
public class GroovyPluginTest {
- public static final Version VERSION_6_7 = Version.create(6, 7);
+ public static final Version VERSION_7_9 = Version.create(7, 9);
@Test
public void testExtensions() {
GroovyPlugin plugin = new GroovyPlugin();
- Binding b = new Binding();
- Class> edition = null;
- String call = "rt.forSonarQube(ver, scanner)";
- try {
- edition = Class.forName("org.sonar.api.SonarEdition");
- call = "rt.forSonarQube(ver, scanner, ed.COMMUNITY)";
- } catch (ClassNotFoundException e) {
- // SKIP on old SonarQube
- }
- b.setVariable("ver", VERSION_6_7);
- b.setVariable("scanner", SonarQubeSide.SCANNER);
- b.setVariable("ed", edition);
- b.setVariable("rt", SonarRuntimeImpl.class);
- GroovyShell sh = new GroovyShell(b);
-
- SonarRuntime runtime = (SonarRuntime) sh.evaluate(call);
+ SonarRuntime runtime =
+ SonarRuntimeImpl.forSonarQube(VERSION_7_9, SonarQubeSide.SCANNER, SonarEdition.COMMUNITY);
Plugin.Context context = new Plugin.Context(runtime);
plugin.define(context);
assertThat(context.getExtensions()).hasSize(14);
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/ActiveRulesBuilderWrapper.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/ActiveRulesBuilderWrapper.java
index a8558a3d..065f13e4 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/ActiveRulesBuilderWrapper.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/codenarc/ActiveRulesBuilderWrapper.java
@@ -19,11 +19,6 @@
*/
package org.sonar.plugins.groovy.codenarc;
-import static org.assertj.core.api.Assertions.fail;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.rule.internal.NewActiveRule;
@@ -32,106 +27,37 @@
public class ActiveRulesBuilderWrapper {
private ActiveRulesBuilder builder = new ActiveRulesBuilder();
- private Object lastRule;
+ private NewActiveRule.Builder lastRule;
boolean newType = false;
- Class> builderClass = null;
- private Constructor> ruleConstructor;
- private Method nameSetter;
- private Method internalKeySetter;
- private Method paramSetter;
- private Method activateMethod;
- private Method createMethod;
- private Method buildMethod;
- private Method addRuleMethod;
-
- public ActiveRulesBuilderWrapper() {
- try {
- builderClass = Class.forName("org.sonar.api.batch.rule.internal.NewActiveRule$Builder");
- newType = true;
- } catch (ClassNotFoundException e) {
- try {
- builderClass = Class.forName("org.sonar.api.batch.rule.internal.NewActiveRule");
- } catch (ClassNotFoundException e1) {
- fail("Could not initialize NewActiveRule", e1);
- }
- }
- try {
- nameSetter = builderClass.getMethod("setName", String.class);
- internalKeySetter = builderClass.getMethod("setInternalKey", String.class);
- paramSetter = builderClass.getMethod("setParam", String.class, String.class);
- if (newType) {
- ruleConstructor = builderClass.getConstructor();
- createMethod = builderClass.getMethod("setRuleKey", RuleKey.class);
- buildMethod = builderClass.getMethod("build");
- addRuleMethod = builder.getClass().getMethod("addRule", NewActiveRule.class);
- } else {
- createMethod = builder.getClass().getMethod("create", RuleKey.class);
- activateMethod = builderClass.getMethod("activate");
- }
- } catch (NoSuchMethodException | SecurityException e) {
- fail("Could not look up a method", e);
- }
- }
public ActiveRulesBuilderWrapper addRule(String key) {
addLastRule();
RuleKey ruleKey = RuleKey.of(CodeNarcRulesDefinition.REPOSITORY_KEY, key);
- try {
- if (newType) {
- lastRule = ruleConstructor.newInstance();
- createMethod.invoke(lastRule, ruleKey);
- } else {
- lastRule = createMethod.invoke(builder, ruleKey);
- }
- } catch (IllegalAccessException
- | IllegalArgumentException
- | InvocationTargetException
- | InstantiationException e) {
- fail("Could not create new rule builder.", e);
- }
+ lastRule = new NewActiveRule.Builder();
+ lastRule.setRuleKey(ruleKey);
setInternalKey(key);
return this;
}
public ActiveRulesBuilderWrapper setName(String name) {
- try {
- nameSetter.invoke(lastRule, name);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- fail("Could not execute 'setName'", e);
- }
+ lastRule.setName(name);
return this;
}
public ActiveRulesBuilderWrapper setInternalKey(String key) {
- try {
- internalKeySetter.invoke(lastRule, key);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- fail("Could not execute 'setInternalKey'", e);
- }
+ lastRule.setInternalKey(key);
return this;
}
public ActiveRulesBuilderWrapper addParam(String key, String value) {
- try {
- paramSetter.invoke(lastRule, key, value);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- fail("Could not execute 'setParam'", e);
- }
+ lastRule.setParam(key, value);
return this;
}
private void addLastRule() {
if (lastRule != null) {
- try {
- if (newType) {
- addRuleMethod.invoke(builder, buildMethod.invoke(lastRule));
- } else {
- activateMethod.invoke(lastRule);
- }
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- fail("Could not add rule to active rules.", e);
- }
+ builder.addRule(lastRule.build());
lastRule = null;
}
}
From a8b75bcc1b2d8976dd3cb43fe7cf8a90c66ed06d Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Tue, 10 Dec 2019 15:09:12 +0100
Subject: [PATCH 79/89] Minor dependency updates
---
CHANGELOG.md | 1 +
codenarc-converter/pom.xml | 4 ++--
pom.xml | 8 ++++----
sonar-groovy-plugin/pom.xml | 2 +-
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4570bb8b..863a95ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed
- Remove backwards compatibility hacks (drop support for everything older then
SonarQube 7.8)
+- Minor dependency updates
## [1.6] - 2019-07-04
diff --git a/codenarc-converter/pom.xml b/codenarc-converter/pom.xml
index be426258..374e13ce 100644
--- a/codenarc-converter/pom.xml
+++ b/codenarc-converter/pom.xml
@@ -13,7 +13,7 @@
Sonar CodeNarc Converter
- 1.6.5
+ 1.7
@@ -44,7 +44,7 @@
com.google.guavaguava
- 28.0-jre
+ 28.1-jrecommons-io
diff --git a/pom.xml b/pom.xml
index a4b36031..f5093254 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.parentparent
- 52
+ 53org.sonarsource.groovy
@@ -125,7 +125,7 @@
org.slf4jslf4j-simple
- 1.7.26
+ 1.7.28
@@ -137,7 +137,7 @@
org.assertjassertj-core
- 3.12.2
+ 3.14.0test
@@ -157,7 +157,7 @@
com.coveofmt-maven-plugin
- 2.8
+ 2.9org.apache.maven.plugins
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index a9ecff99..457a4ba2 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -89,7 +89,7 @@
org.mockitomockito-core
- 2.28.2
+ 3.2.0test
From d536102dcf9faaf46cc733f96edac4361cb0de96 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Tue, 10 Dec 2019 15:47:23 +0100
Subject: [PATCH 80/89] Drop compatibility with JaCoCo < 0.7.5
Unfortunately, some tests were still using old, unreproducible binary
JaCoCo files. These tests have been removed.
---
CHANGELOG.md | 3 +
groovy-jacoco-previous/pom.xml | 77 --------------
pom.xml | 2 -
sonar-groovy-plugin/pom.xml | 5 -
.../groovy/jacoco/JaCoCoReportMerger.java | 23 +----
.../groovy/jacoco/JaCoCoReportReader.java | 97 +++++++-----------
.../groovy/jacoco/JaCoCoItSensorTest.java | 39 ++-----
.../jacoco/JaCoCoOverallSensorTest.java | 97 ++----------------
.../groovy/jacoco/JaCoCoReportMergerTest.java | 16 ++-
.../groovy/jacoco/JaCoCoReportReaderTest.java | 9 +-
.../groovy/jacoco/JaCoCoSensorTest.java | 15 +--
.../jacoco/JaCoCoItSensorTests/jacoco-it.exec | Bin 19056 -> 0 bytes
.../JaCoCoOverallSensorTests/jacoco-it.exec | Bin 19056 -> 0 bytes
.../JaCoCoOverallSensorTests/jacoco-ut.exec | Bin 19764 -> 0 bytes
14 files changed, 76 insertions(+), 307 deletions(-)
delete mode 100644 groovy-jacoco-previous/pom.xml
delete mode 100644 sonar-groovy-plugin/src/test/resources/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTests/jacoco-it.exec
delete mode 100644 sonar-groovy-plugin/src/test/resources/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTests/jacoco-it.exec
delete mode 100644 sonar-groovy-plugin/src/test/resources/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTests/jacoco-ut.exec
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 863a95ae..f3f9aedc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
SonarQube 7.8)
- Minor dependency updates
+### Removed
+- Compatibility with JaCoCo older the 0.7.5 (released in mid-2015)
+
## [1.6] - 2019-07-04
### Added
diff --git a/groovy-jacoco-previous/pom.xml b/groovy-jacoco-previous/pom.xml
deleted file mode 100644
index 4c727bfb..00000000
--- a/groovy-jacoco-previous/pom.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
- 4.0.0
-
-
- org.sonarsource.groovy
- groovy
- 1.7-SNAPSHOT
-
-
- groovy-jacoco-previous
-
-
- This module shades the required classes of previous version of JaCoCo to allow analysis of two JaCoCo binary format.
-
-
-
-
- org.jacoco
- org.jacoco.core
- ${jacoco.previous.version}
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
-
-
- package
-
- shade
-
-
-
-
- *:*
-
- org/jacoco/core/data/ExecutionDataReader*
- org/jacoco/core/data/ExecutionDataWriter*
- org/jacoco/core/analysis/Analyzer*
- org/jacoco/core/analysis/CoverageNodeImpl*
- org/jacoco/core/internal/**
-
-
-
-
-
- org.jacoco.core.data.ExecutionDataReader
- org.jacoco.previous.core.data.ExecutionDataReader
-
-
- org.jacoco.core.data.ExecutionDataWriter
- org.jacoco.previous.core.data.ExecutionDataWriter
-
-
- org.jacoco.core.analysis.Analyzer
- org.jacoco.previous.core.analysis.Analyzer
-
-
- org.jacoco.core.analysis.CoverageNodeImpl
- org.jacoco.previous.core.analysis.CoverageNodeImpl
-
-
- org.jacoco.core.internal
- org.jacoco.previous.core.internal
-
-
-
-
-
-
-
-
-
diff --git a/pom.xml b/pom.xml
index f5093254..7b7f3be9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,7 +48,6 @@
- groovy-jacoco-previoussonar-groovy-plugincodenarc-converter
@@ -71,7 +70,6 @@
7.8
- 0.7.4.2015022621282.4.173.113.3.9
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index 457a4ba2..ac4c0c59 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -26,11 +26,6 @@
3.1.12provided
-
- ${project.groupId}
- groovy-jacoco-previous
- ${project.version}
- org.sonarsource.sonarqubesonar-plugin-api
diff --git a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMerger.java b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMerger.java
index c0be1ede..52f21436 100644
--- a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMerger.java
+++ b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMerger.java
@@ -25,7 +25,6 @@
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import org.apache.commons.lang.BooleanUtils;
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.data.ExecutionDataWriter;
import org.jacoco.core.data.IExecutionDataVisitor;
@@ -50,16 +49,12 @@ private JaCoCoReportMerger() {}
public static void mergeReports(Path reportOverall, File... reports) {
SessionInfoStore infoStore = new SessionInfoStore();
ExecutionDataStore dataStore = new ExecutionDataStore();
- boolean isCurrentVersionFormat = loadSourceFiles(infoStore, dataStore, reports);
+ loadSourceFiles(infoStore, dataStore, reports);
try (OutputStream fos = Files.newOutputStream(reportOverall);
BufferedOutputStream outputStream = new BufferedOutputStream(fos)) {
Object visitor;
- if (isCurrentVersionFormat) {
- visitor = new ExecutionDataWriter(outputStream);
- } else {
- visitor = new org.jacoco.previous.core.data.ExecutionDataWriter(outputStream);
- }
+ visitor = new ExecutionDataWriter(outputStream);
infoStore.accept((ISessionInfoVisitor) visitor);
dataStore.accept((IExecutionDataVisitor) visitor);
} catch (IOException e) {
@@ -68,22 +63,12 @@ public static void mergeReports(Path reportOverall, File... reports) {
}
}
- private static boolean loadSourceFiles(
+ private static void loadSourceFiles(
ISessionInfoVisitor infoStore, IExecutionDataVisitor dataStore, File... reports) {
- Boolean isCurrentVersionFormat = null;
for (File report : reports) {
if (report.isFile()) {
- JaCoCoReportReader jacocoReportReader =
- new JaCoCoReportReader(report).readJacocoReport(dataStore, infoStore);
- boolean reportFormatIsCurrent = jacocoReportReader.useCurrentBinaryFormat();
- if (isCurrentVersionFormat == null) {
- isCurrentVersionFormat = reportFormatIsCurrent;
- } else if (!isCurrentVersionFormat.equals(reportFormatIsCurrent)) {
- throw new IllegalStateException(
- "You are trying to merge two different JaCoCo binary formats. Please use only one version of JaCoCo.");
- }
+ new JaCoCoReportReader(report).readJacocoReport(dataStore, infoStore);
}
}
- return BooleanUtils.isNotFalse(isCurrentVersionFormat);
}
}
diff --git a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReader.java b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReader.java
index 33019f62..af167ad1 100644
--- a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReader.java
+++ b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReader.java
@@ -37,108 +37,87 @@
public class JaCoCoReportReader {
- @Nullable
- private final File jacocoExecutionData;
- private final boolean useCurrentBinaryFormat;
+ // Visible for testing
+ static final String INCOMPATIBLE_JACOCO_ERROR =
+ "You are using an incompatible JaCoCo binary format version, please consider upgrading to a supported JaCoCo version (0.8.x).";
+
+ @Nullable private final File jacocoExecutionData;
public JaCoCoReportReader(@Nullable File jacocoExecutionData) {
this.jacocoExecutionData = jacocoExecutionData;
- this.useCurrentBinaryFormat = isCurrentReportFormat(jacocoExecutionData);
+ verifyCurrentReportFormat(jacocoExecutionData);
}
/**
* Read JaCoCo report determining the format to be used.
+ *
* @param executionDataVisitor visitor to store execution data.
* @param sessionInfoStore visitor to store info session.
* @return true if binary format is the latest one.
* @throws IOException in case of error or binary format not supported.
*/
- public JaCoCoReportReader readJacocoReport(IExecutionDataVisitor executionDataVisitor, ISessionInfoVisitor sessionInfoStore) {
+ public JaCoCoReportReader readJacocoReport(
+ IExecutionDataVisitor executionDataVisitor, ISessionInfoVisitor sessionInfoStore) {
if (jacocoExecutionData == null) {
return this;
}
JaCoCoExtensions.logger().info("Analysing {}", jacocoExecutionData);
- try (InputStream inputStream = new BufferedInputStream(new FileInputStream(jacocoExecutionData))) {
- if (useCurrentBinaryFormat) {
- ExecutionDataReader reader = new ExecutionDataReader(inputStream);
- reader.setSessionInfoVisitor(sessionInfoStore);
- reader.setExecutionDataVisitor(executionDataVisitor);
- reader.read();
- } else {
- org.jacoco.previous.core.data.ExecutionDataReader reader = new org.jacoco.previous.core.data.ExecutionDataReader(inputStream);
- reader.setSessionInfoVisitor(sessionInfoStore);
- reader.setExecutionDataVisitor(executionDataVisitor);
- reader.read();
- }
+ try (InputStream inputStream =
+ new BufferedInputStream(new FileInputStream(jacocoExecutionData))) {
+ ExecutionDataReader reader = new ExecutionDataReader(inputStream);
+ reader.setSessionInfoVisitor(sessionInfoStore);
+ reader.setExecutionDataVisitor(executionDataVisitor);
+ reader.read();
} catch (IOException e) {
- throw new IllegalArgumentException(String.format("Unable to read %s", jacocoExecutionData.getAbsolutePath()), e);
+ throw new IllegalArgumentException(
+ String.format("Unable to read %s", jacocoExecutionData.getAbsolutePath()), e);
}
return this;
}
- private static boolean isCurrentReportFormat(@Nullable File jacocoExecutionData) {
+ private static void verifyCurrentReportFormat(@Nullable File jacocoExecutionData) {
if (jacocoExecutionData == null) {
- return true;
+ return;
}
try (DataInputStream dis = new DataInputStream(new FileInputStream(jacocoExecutionData))) {
byte firstByte = dis.readByte();
- if (firstByte != ExecutionDataWriter.BLOCK_HEADER || dis.readChar() != ExecutionDataWriter.MAGIC_NUMBER) {
+ if (firstByte != ExecutionDataWriter.BLOCK_HEADER
+ || dis.readChar() != ExecutionDataWriter.MAGIC_NUMBER) {
throw new IllegalStateException();
}
- char version = dis.readChar();
- boolean isCurrentFormat = version == ExecutionDataWriter.FORMAT_VERSION;
- if (!isCurrentFormat) {
- JaCoCoExtensions.logger().warn("You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.");
+ if (dis.readChar() != ExecutionDataWriter.FORMAT_VERSION) {
+ throw new IllegalArgumentException(
+ INCOMPATIBLE_JACOCO_ERROR);
}
- return isCurrentFormat;
} catch (IOException | IllegalStateException e) {
- throw new IllegalArgumentException(String.format("Unable to read %s to determine JaCoCo binary format.", jacocoExecutionData.getAbsolutePath()), e);
+ throw new IllegalArgumentException(
+ String.format(
+ "Unable to read %s to determine JaCoCo binary format.",
+ jacocoExecutionData.getAbsolutePath()),
+ e);
}
}
- public boolean useCurrentBinaryFormat() {
- return this.useCurrentBinaryFormat;
- }
-
- /**
- * Caller must guarantee that {@code classFiles} are actually class file.
- */
- public CoverageBuilder analyzeFiles(ExecutionDataStore executionDataStore, Collection classFiles) {
+ /** Caller must guarantee that {@code classFiles} are actually class file. */
+ public CoverageBuilder analyzeFiles(
+ ExecutionDataStore executionDataStore, Collection classFiles) {
CoverageBuilder coverageBuilder = new CoverageBuilder();
- if (useCurrentBinaryFormat) {
- Analyzer analyzer = new Analyzer(executionDataStore, coverageBuilder);
- for (File classFile : classFiles) {
- analyzeClassFile(analyzer, classFile);
- }
- } else {
- org.jacoco.previous.core.analysis.Analyzer analyzer = new org.jacoco.previous.core.analysis.Analyzer(executionDataStore, coverageBuilder);
- for (File classFile : classFiles) {
- analyzeClassFile(analyzer, classFile);
- }
+ Analyzer analyzer = new Analyzer(executionDataStore, coverageBuilder);
+ for (File classFile : classFiles) {
+ analyzeClassFile(analyzer, classFile);
}
return coverageBuilder;
}
- /**
- * Caller must guarantee that {@code classFile} is actually class file.
- */
- private static void analyzeClassFile(org.jacoco.previous.core.analysis.Analyzer analyzer, File classFile) {
- try (InputStream inputStream = new FileInputStream(classFile)) {
- analyzer.analyzeClass(inputStream, classFile.getPath());
- } catch (IOException e) {
- // (Godin): in fact JaCoCo includes name into exception
- JaCoCoExtensions.logger().warn("Exception during analysis of file " + classFile.getAbsolutePath(), e);
- }
- }
-
+ /** Caller must guarantee that {@code classFile} is actually class file. */
private static void analyzeClassFile(Analyzer analyzer, File classFile) {
try (InputStream inputStream = new FileInputStream(classFile)) {
analyzer.analyzeClass(inputStream, classFile.getPath());
} catch (IOException e) {
// (Godin): in fact JaCoCo includes name into exception
- JaCoCoExtensions.logger().warn("Exception during analysis of file " + classFile.getAbsolutePath(), e);
+ JaCoCoExtensions.logger()
+ .warn("Exception during analysis of file " + classFile.getAbsolutePath(), e);
}
}
-
}
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
index 8382080c..8e28c7c1 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
@@ -20,11 +20,9 @@
package org.sonar.plugins.groovy.jacoco;
import static org.assertj.core.api.Assertions.assertThat;
-
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -34,7 +32,6 @@
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
-import org.sonar.api.batch.sensor.internal.SensorContextTester;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.scan.filesystem.PathResolver;
@@ -47,18 +44,15 @@ public class JaCoCoItSensorTest {
@Rule public final TemporaryFolder tmpDir = new TemporaryFolder();
- private Path outputDir;
- private InputFile inputFile;
private MapSettings settings =
new MapSettings(new PropertyDefinitions(JaCoCoConfiguration.getPropertyDefinitions()));
- private JaCoCoConfiguration configuration;
private JaCoCoSensor sensor;
@Before
- public void setUp() throws Exception {
- outputDir = tmpDir.newFolder().toPath();
+ public void setUp() throws IOException {
+ Path outputDir = tmpDir.newFolder().toPath();
Files.copy(
- TestUtils.getResource(getClass(), "../JaCoCoItSensorTests/jacoco-it.exec"),
+ TestUtils.getResource(getClass(), "../JaCoCoSensor_0_7_5/jacoco-ut.exec"),
outputDir.resolve("jacoco-it.exec"));
Files.copy(
TestUtils.getResource(getClass(), "../Hello.class.toCopy"),
@@ -71,14 +65,14 @@ public void setUp() throws Exception {
settings.setProperty(JaCoCoConfiguration.IT_REPORT_PATH_PROPERTY, "jacoco-it.exec");
DefaultFileSystem fileSystem = new DefaultFileSystem(outputDir);
- inputFile =
+ InputFile inputFile =
TestInputFileBuilder.create("", "example/Hello.groovy")
.setLanguage(Groovy.KEY)
.setType(Type.MAIN)
.setLines(50)
.build();
fileSystem.add(inputFile);
- configuration = new JaCoCoConfiguration(settings, fileSystem);
+ JaCoCoConfiguration configuration = new JaCoCoConfiguration(settings, fileSystem);
sensor =
new JaCoCoSensor(
@@ -86,7 +80,7 @@ public void setUp() throws Exception {
}
@Test
- public void test_description() {
+ public void testDescription() {
DefaultSensorDescriptor defaultSensorDescriptor = new DefaultSensorDescriptor();
sensor.describe(defaultSensorDescriptor);
assertThat(defaultSensorDescriptor.languages()).containsOnly(Groovy.KEY);
@@ -103,25 +97,4 @@ public void should_Execute_On_Project_only_if_exec_exists() {
assertThat(sensor.shouldExecuteOnProject()).isFalse();
}
- @Test
- public void test_read_execution_data() throws IOException {
- SensorContextTester context = SensorContextTester.create(Paths.get("."));
- context.fileSystem().setWorkDir(tmpDir.newFolder().toPath());
- sensor.execute(context);
-
- int[] oneHitlines = {9, 10, 25};
- int[] zeroHitlines = {14, 15, 17, 21, 29, 30, 32, 33, 38, 42, 47};
- int[] conditionLines = {14, 29, 30};
-
- for (int zeroHitline : zeroHitlines) {
- assertThat(context.lineHits(":example/Hello.groovy", zeroHitline)).isEqualTo(0);
- }
- for (int oneHitline : oneHitlines) {
- assertThat(context.lineHits(":example/Hello.groovy", oneHitline)).isEqualTo(1);
- }
- for (int conditionLine : conditionLines) {
- assertThat(context.conditions(":example/Hello.groovy", conditionLine)).isEqualTo(2);
- assertThat(context.coveredConditions(":example/Hello.groovy", conditionLine)).isEqualTo(0);
- }
- }
}
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java
index c338acc1..9e5c40b2 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java
@@ -20,7 +20,7 @@
package org.sonar.plugins.groovy.jacoco;
import static org.assertj.core.api.Assertions.assertThat;
-
+import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.Before;
@@ -43,22 +43,18 @@ public class JaCoCoOverallSensorTest {
@Rule public final TemporaryFolder tmpDir = new TemporaryFolder();
- private JaCoCoConfiguration configuration;
private JaCoCoSensor sensor;
- private Path outputDir;
- private InputFile inputFile;
private MapSettings settings = new MapSettings();
- private SensorContextTester context;
@Before
- public void before() throws Exception {
- outputDir = tmpDir.newFolder().toPath();
+ public void before() throws IOException {
+ Path outputDir = tmpDir.newFolder().toPath();
Files.copy(
- TestUtils.getResource(getClass(), "../JaCoCoOverallSensorTests/jacoco-ut.exec"),
+ TestUtils.getResource(getClass(), "../JaCoCoSensor_0_7_5/jacoco-ut.exec"),
outputDir.resolve("jacoco-ut.exec"));
Files.copy(
- TestUtils.getResource(getClass(), "../JaCoCoOverallSensorTests/jacoco-it.exec"),
+ TestUtils.getResource(getClass(), "../JaCoCoSensor_0_7_5/jacoco-ut.exec"),
outputDir.resolve("jacoco-it.exec"));
Files.copy(
TestUtils.getResource(getClass(), "../Hello.class.toCopy"),
@@ -69,10 +65,10 @@ public void before() throws Exception {
settings.setProperty(GroovyPlugin.SONAR_GROOVY_BINARIES, ".");
- context = SensorContextTester.create(outputDir);
+ SensorContextTester context = SensorContextTester.create(outputDir);
context.fileSystem().setWorkDir(tmpDir.newFolder().toPath());
- inputFile =
+ InputFile inputFile =
TestInputFileBuilder.create("", "example/Hello.groovy")
.setLanguage(Groovy.KEY)
.setType(Type.MAIN)
@@ -80,7 +76,7 @@ public void before() throws Exception {
.build();
context.fileSystem().add(inputFile);
- configuration = new JaCoCoConfiguration(settings, context.fileSystem());
+ JaCoCoConfiguration configuration = new JaCoCoConfiguration(settings, context.fileSystem());
sensor =
new JaCoCoSensor(
configuration,
@@ -111,83 +107,6 @@ public void should_Execute_On_Project_only_if_at_least_one_exec_exists() {
assertThat(sensor.shouldExecuteOnProject()).isFalse();
}
- @Test
- public void test_read_execution_data_with_IT_and_UT() {
- configReports(true, true);
-
- sensor.execute(context);
-
- int[] oneHitlines = {9, 10, 14, 15, 17, 21, 25, 29, 32, 33, 42, 47};
- int[] zeroHitlines = {30, 38};
- int[] conditionLines = {14, 29, 30};
- int[] coveredConditions = {2, 1, 0};
-
- verifyOverallMetrics(context, zeroHitlines, oneHitlines, conditionLines, coveredConditions);
- }
-
- private void verifyOverallMetrics(
- SensorContextTester context,
- int[] zeroHitlines,
- int[] oneHitlines,
- int[] conditionLines,
- int[] coveredConditions) {
- for (int zeroHitline : zeroHitlines) {
- assertThat(context.lineHits(inputFile.key(), zeroHitline)).isEqualTo(0);
- }
- for (int oneHitline : oneHitlines) {
- assertThat(context.lineHits(inputFile.key(), oneHitline)).isEqualTo(1);
- }
-
- for (int i = 0; i < conditionLines.length; i++) {
- int line = conditionLines[i];
- assertThat(context.conditions(inputFile.key(), line)).isEqualTo(2);
- assertThat(context.coveredConditions(inputFile.key(), line)).isEqualTo(coveredConditions[i]);
- }
- }
-
- @Test
- public void test_read_execution_data_with_IT_and_UT_and_binaryDirs_being_absolute() {
- configReports(true, true);
- settings.setProperty(GroovyPlugin.SONAR_GROOVY_BINARIES, outputDir.toAbsolutePath().toString());
-
- sensor.execute(context);
-
- int[] oneHitlines = {9, 10, 14, 15, 17, 21, 25, 29, 32, 33, 42, 47};
- int[] zeroHitlines = {30, 38};
- int[] conditionLines = {14, 29, 30};
- int[] coveredConditions = {2, 1, 0};
-
- verifyOverallMetrics(context, zeroHitlines, oneHitlines, conditionLines, coveredConditions);
- }
-
- @Test
- public void test_read_execution_data_with_only_UT() {
- configReports(true, false);
-
- sensor.execute(context);
-
- int[] oneHitlines = {9, 10, 14, 15, 17, 21, /* 25 not covered in UT */ 29, 32, 33, 42, 47};
- int[] zeroHitlines = {25, 30, 38};
- int[] conditionLines = {14, 29, 30};
- int[] coveredConditions = {2, 1, 0};
-
- verifyOverallMetrics(context, zeroHitlines, oneHitlines, conditionLines, coveredConditions);
- }
-
- @Test
- public void test_read_execution_data_with_only_IT() {
- configReports(false, true);
-
- sensor.execute(context);
-
- int[] oneHitlines = {9, 10, 25};
- int[] zeroHitlines = {14, 15, 17, 21, 29, 30, 32, 33, 38, 42, 47};
- int[] conditionLines = {14, 29, 30};
- int[] coveredConditions = {0, 0, 0};
-
- verifyOverallMetrics(context, zeroHitlines, oneHitlines, conditionLines, coveredConditions);
- }
-
private void configReports(boolean utReport, boolean itReport) {
settings.setProperty(
JaCoCoConfiguration.REPORT_PATH_PROPERTY, utReport ? "jacoco-ut.exec" : "notexist-ut.exec");
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMergerTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMergerTest.java
index 9d986147..ccc051ae 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMergerTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportMergerTest.java
@@ -33,23 +33,21 @@ public class JaCoCoReportMergerTest {
@Rule public ExpectedException exception = ExpectedException.none();
@Test
- public void merge_different_format_should_fail() {
- exception.expect(IllegalStateException.class);
- exception.expectMessage(
- "You are trying to merge two different JaCoCo binary formats. Please use only one version of JaCoCo.");
+ public void mergeDifferentFormatShouldFail1() {
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage(JaCoCoReportReader.INCOMPATIBLE_JACOCO_ERROR);
merge("jacoco-0.7.5.exec", "jacoco-it-0.7.4.exec");
}
@Test
- public void merge_different_format_should_fail_() {
- exception.expect(IllegalStateException.class);
- exception.expectMessage(
- "You are trying to merge two different JaCoCo binary formats. Please use only one version of JaCoCo.");
+ public void mergeDifferentFormatShouldFail2() {
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage(JaCoCoReportReader.INCOMPATIBLE_JACOCO_ERROR);
merge("jacoco-0.7.4.exec", "jacoco-it-0.7.5.exec");
}
@Test
- public void merge_same_format_should_not_fail() throws Exception {
+ public void merge_same_format_should_not_fail() {
merge("jacoco-0.7.5.exec", "jacoco-it-0.7.5.exec");
}
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReaderTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReaderTest.java
index cf5a79db..d492469e 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReaderTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoReportReaderTest.java
@@ -56,19 +56,12 @@ public void reading_file_no_tfound_should_do_nothing() {
}
@Test
- public void not_existing_class_files_should_not_be_analyzed_for_current() {
+ public void notExistingClassFilesShouldNotBeAnalyzed() {
File report = TestUtils.getResource("/org/sonar/plugins/groovy/jacoco/JaCoCo_incompatible_merge/jacoco-0.7.5.exec");
Collection classFile = Arrays.asList(dummy);
new JaCoCoReportReader(report).analyzeFiles(null, classFile);
}
- @Test
- public void not_existing_class_files_should_not_be_analyzed_for_previous() {
- File report = TestUtils.getResource("/org/sonar/plugins/groovy/jacoco/JaCoCo_incompatible_merge/jacoco-0.7.4.exec");
- Collection classFile = Arrays.asList(dummy);
- new JaCoCoReportReader(report).analyzeFiles(null, classFile);
- }
-
@Test
public void analyzing_a_deleted_file_should_fail() throws Exception {
File report = testFolder.newFile("jacoco.exec");
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
index 01b9ccb5..b2ff4e23 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
@@ -27,6 +27,7 @@
import java.nio.file.Paths;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
@@ -46,10 +47,11 @@ public class JaCoCoSensorTest {
@Rule public final TemporaryFolder tmpDir = new TemporaryFolder();
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
private MapSettings settings =
new MapSettings(new PropertyDefinitions(JaCoCoConfiguration.getPropertyDefinitions()));
- private InputFile inputFile;
- private JaCoCoConfiguration configuration;
private JaCoCoSensor sensor;
private void initWithJaCoCoVersion(String jacocoVersion) throws IOException {
@@ -69,14 +71,14 @@ private void initWithJaCoCoVersion(String jacocoVersion) throws IOException {
settings.setProperty(JaCoCoConfiguration.REPORT_PATH_PROPERTY, "jacoco-ut.exec");
DefaultFileSystem fileSystem = new DefaultFileSystem(outputDir);
- inputFile =
+ InputFile inputFile =
TestInputFileBuilder.create("", "example/Hello.groovy")
.setLanguage(Groovy.KEY)
.setType(Type.MAIN)
.setLines(50)
.build();
fileSystem.add(inputFile);
- configuration = new JaCoCoConfiguration(settings, fileSystem);
+ JaCoCoConfiguration configuration = new JaCoCoConfiguration(settings, fileSystem);
sensor =
new JaCoCoSensor(
@@ -110,9 +112,10 @@ public void test_read_execution_data_with_jacoco_0_7_4() throws IOException {
SensorContextTester context = SensorContextTester.create(Paths.get("."));
context.fileSystem().setWorkDir(tmpDir.newFolder().toPath());
- sensor.execute(context);
- verifyMeasures(context);
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage(JaCoCoReportReader.INCOMPATIBLE_JACOCO_ERROR);
+ sensor.execute(context);
}
@Test
diff --git a/sonar-groovy-plugin/src/test/resources/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTests/jacoco-it.exec b/sonar-groovy-plugin/src/test/resources/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTests/jacoco-it.exec
deleted file mode 100644
index 1b4c570f78a8959869d0ed57199874e4521c770f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 19056
zcmc&+cU)6f`#&K-*l=*+1T|Wmk?E|;Qcyu;s8}tAwveeYF*W~+Pb%B
zTdQ@nSnH^$FV?!M*1fH(uGjTi;rE<-GA`jJN`HU6`6!U+z4x4FexL9293;DU`?>ld
z-{hE1ox(#pWM_2^VZxNz2uYH^ow{x!{r)w^-{T9vO`DnOi9%T}N1+XSLARk
zTUewp8Z=r(qEe^KVblXOx>4k--XM?DGWm?o;3Yx0w8xLKohu?jQ4g`}IVM}ns0qlXY`5$oq@?=xEQ4>mr=)%4+A6!;RavD4NBXP(h7x;TPX|3KP&Q;g$!J5
zgga?CMv=v`28L6l6%{aXIpvh+x>YRK{et}k@y`ZGoGN_{Rdyf~eKD{_+JqUK8`#!QZ%CVs6z*r`Sxzuf_>QVl{1arVS%@1Hoi
zx?ja%)K=`df@=j1H)5jfs6tyQ3964K1mK%5uZOe<95@;Ui`{`=c{OvFhr^O{CU0vL
z_|b;GsHNCN0)v-_cZ~qGoHfpTURv05Hwq{J-=R@PEA>n=#};Z}i+#XZS+1y2#?qZq
z{Agr+_l+G&W9e3@9cdt%a5|+{k!93q;R1*+IXaeO)Y0_4)CHe9bgAXv6J#AxchRL<
zgOt^j2Pi)%637d-FO}i%TFngFTBcfB+xw6ZM-@iyBf$lEKmIXi!FCx65SnsdKIWzt
z=?zT2+kAZBny#DgepR`6WEQBkF9Uw0G%#x73)GTb0`afqFJ3iRw6!<2D2L+i!*USW
zqxsMZ7A3*EOZ06NE5eMZ8C_qVl7l}=eZGSHjV>}UgCT6OT-Tq+UkN~nli==yRjoXS
z9iJj@43=0G&u9x6ZjvPOln)8mmX{lD{9)pKwC{q~KMkMB#%kfyUy7XYH~W6*6jCvy
z2Z9aO%xwY-6^3LGgO*Y1_?T>SQ@4-s_BOH*|8pJk&6=w&nK*S02_S1XUTpGm-Gec;
zdafxciapmy8if7Rd#^vbdCyAJ+tFU~Lqc^52!OVxK
zp_t+H;gtEz14#7_USsi&SIXFyTc*a>$`WE(W0sb&C%gyOeB-D55wZq#btF7XMld;I
zwMgsig(nu}`TGvI*Z@V?N{tU2DNGLJU#>__tg#z1oPKn~(;GDL)Y24b(?eIvp}f9|*+F>&pU+U$&9ks!zh5!1l;mJA!2yLI>z
z6eMax8b+%gtbxqUa(?v?-o>rj+~j;>Jc_S{C}MJ9?J8Khn8ARTx00`Wc;IZEo8tLU
z5PB{7Vv$68G!S{Yy*T~igNIdBy@DTBp%-pAVE!xP(rF(&MZH8;59qJgt0cvp
zqzH|~iTzTQ;~&4+BaW&C(x86B%Y;Yerhwz#R)YUKNPF(tCq7+JV^QBp;K3VM_7cs6
z8|Odk=ueZLc-G?ah$ZWjY!q$Gh8;IV=!FEY>HA$t*p49$QJ|Rl@QWM50np=~NHV5?
zz5TTzZ*Y2M`j%2>^iT%x7sya9Ld6p|$#8h1UNm*bTS88WNr9)!HDA;|1~)=vy8FDIE1qT)Sb;{t61?9cf&&nsN5P<2-Lw
z{94vO6m@zl?Zaf*DC_Z`iI0_~P-MKJgd(cdw!)ne7UMOD7PAuK~>HzwU!7U%dBz
z`vXIkezg>Je7on9yT~K>7}w*6V|xqlo%>1LaI0fdTA_0CP`3npGwnuNryNyX;pL#@mM+b~7Hbf}ZUNR<(j
z%cw>%T%Cxnu6Wn%5k1TBr{9R@*a6BcM%!)fwxfKG#b0&k+{d_~{84SfG9MHLwn)nS
z-%+ekM@pnOSp+I;q
z#agdH<9>^HQ7m51@S2ZdAz(0Lt%X!0_ZJc=-Zb#MH23N6yJ`izgn+MR5q|aL-Pk8F
z$GX~q{H9cE)jCl*A7spMfP^;Hqw)XQ{x^frznl<~;Y%r7e!RZWd61(Zmqm$=R1@(5
zA)OE@EEj^1Gf^#Wo*y}E!}5%g|Bu91bGIJb+#|0?9vCeS;{}KrYPt{rhS8r~z~`q7
zYf2+zjrd@e4nd`HV-1W>4`_&jQL}iw<{|u3Y-ACR&Oa1%@8X8zL^a^s@9)e8#)tL92S?A$BZ}hj;-Bg2G8Qv~c6r
zXWHg=;-yI*raTEHTMksVsm1~ljT-wcL(aG$cgK(AowFt(KN7uYfg1&+8D|)R{J>F)
z=@M7080-DvhDui&i)`v(P!kk{dLUS|K(?h2_LYHroISgMwwGr(MOfe=I
z^RpO^eofXI^-YQC;3KmmI+j;l$aVz8LhC%ZD8sk_02Fl$nn&~|zlcGoJ#Qk;Sn55plX2v$
zC_BkayzJq#8HvjDwov_+FS~QLXy)>cc9vv~6@{G@CRZg1orkorkJ8c#=
zXYJ75=D=qG1J(ub`B5GZJSoFDIpM1-i;rEcxAHd>V0Czt#iuZ%jgb4jTo7LH%CNTA
z&i^zOFG%>1LnPyIvVjU9
zr3>Jh`s|p{CDT^iaO~FBeSsFqhN7TiV5}|}%7ZED>tEDn{h_e_i9;jgCH1nC
z?cf+wT(K;Gh9}#efNKQq+oI&mu8OqPj^tpff>H_l$)xZl5#NsJs@$yLBQ91huXF6r
z7N>gJS&h}31auW`X$epjRP{%aI<2_=`MDPk!k5L;qK%|$1kA<61MNQUHh+o|y<_Va
zdIfbSo=+SDxrc`K))&?}p#XgNaLkzJL2g|fXGx0)ZEVp`_AActI3H5ceb7`P3bF7F
z76;?2vv89?f$IM9e7Q2$qrShLaBCG7u(KSiQ7fY8cT=8ojl?J4DUEnM=e=~gWAThj
z;irj$Yjm+>q!TU=Y`Jc3Nxy%+ZDAQs3(N2nYr1afvSXyX3x4si_=mQuw@ji|V-H~D
z3$q%uDk-Ti^T9v#?9gNM?U)XzuV_@TNgyxi?VL%sXlS+F59vzqX+WdWllYeD&09Sx
zfp5KWv&z;pZp@dK(iU*F2qY4gfwGX`zNk$Oof8nrkFm!5{32^ibSuHL->c}C;io!@
zn%FwDB9_ssI86b`bHO)3EXDZh&_V309P}XKUPi$>rgR@VK1qH(EWcZ$J%d>^g#a^xd
z3chvLPHePIYZh-d<=4DGrfn>JyRID)ES6TDT)!{i~Z4e;;E
zK?%*jPWiSr03i&rjC$6mC6Q9^6K@2#!ni6=EV71HmpZuHvH71IPlJZna1CA8D
zVNU)>IbH9Eq}TyUR$&T|fjR24WSWPUg*v`@Yxv9K}%6b|}n&*&|^Lb#}r3Sr{O0C{DdT
zKeQ@y*bf=Pp$wXS^onRLs~Sa-5@khsZi~=@j^2Uz!
zttq>2o6+rfoX{1lelSF1$OU#Ecnd%ZN!!B@J`O&;N<4L&BPX9*NL+g@;YrvUTDE-P
zhZ_g%EFCtt`}&$a^Jo|^FgMqmNSYxp{C8eVVQR-OD`|6I+zC{I)_@3tGxgeBoN#OZ
zg0C}A@O9>ueDc+EX~nbC(@_gCzv44SAMh?-u+7VSor5HJbDz^*zyFeW1bJ7p@-|Uu
zw`3MU{moVbHRprAv5~AG_0`GC^yNOZ
z^dxUJHcT|2Q!Xy0^5t({mEw&$-a^D!D@s3k9|M`s|J>(x|4)nFs`4ZxE2Pv3pQVm3
z3z{;)PN{5Gwy<R
zcgZTd7hXCYy|A~{-D>>QThu`<|LyX;i7%b}FIRqYp=Z>iDtPs(eEq1$lL{De5WYIP
z6<-f*44+JEnIu8WGD^myplBz6v6h!J4n5v{al6lN-Vg`cyop%|4Qgwg&$A#r;ZEYM
z;4kNNHS>zqr^on&N@o+2(~G0iwkR#-$L!&1N9e}fE#zkh&AG+&VB9TP
zf(K0>Sa0NTu3gO%u|{5}5rB{0=YF^(FPlC*+EELD->iilp$RpeK>zPScvK<)MEv-|KAHZ`FQ2bQ?}}v;VfH69fF0-Hrwh9J
zw4K?cSB`US@M|=k3^c=7c!D1^g2H?^p{*x&ET|QnizF>1c6igLOJahCq2OwXPOeuL
z@whIHO(28vbS9gSm3nWCaL>@nmCrAHcMS!K$$%#rQqu@drPEYHS9&d8{6|6+1vWw&
z!>sre9u$~Dv9AA%84-*X(mRU3>$Ci(6ObWNs}^>?nnf%CS*t62A4owxN)
zt&7WAhiyE?DE;g}2J59Y$}01GV3ZSjRQ3A7-6{!AsCQW!IpglLH&&+*s!XRec-sy{
z1*ib8AF$}};iZRX*qNEMTp~Q!F@V+O2;8F~@3aGAPIjEM#eIXgI8;OhIdH_oVm?rs
z8JMw#x@e|5{(jZkONUn6KT5%#4W0m)#`n4Pgi#~MH^|8nLT%6p25{s``=`E>TYa4(
zK1#@&nQ4?Ts2+(g2Ua$Ilr^hQ65=QL#c?>l2r~dTQ*s?2&HQ>fptbl{tDPfwj;ccqL***^xZTjs!5@>3qjUOyd*3i|>*OgQk_K
zu7UGiO#>ubrMpYgTjF9#Ze;)p=v@y%y9-{$9`Kj^Fb0jC*qQubc`frOjZRPZn?Jd<
zv|swu^z?dZxU{s?^3U`Ke5PV?M%xuD%25!BPt`pSMn*wRG~mbyn<2SZ)~0(W_uuWn
zK2als`A9x4Ry#mMBJsSu6ElBrvu^}7G;!?-s08!Gd*GK|T5Ug-ZDf5{-l-INWoQqleN+@8XMF7AG|HDehlJ&umT5jgt-Il2_uNT`gQj~LuKvkWN@28Ryd=R2)zIRy+w3R=jlz!XIaTNIS1@m
zHHw>;`!6MTE7!|k&PL6t6IHJ-s3VyYUJglkmKWZ5yw9%bfApic}y#7%Bp?KBQdDm6d{
zF_)Zp1VRz|S^Pjap)J!mrB0vCa{2reN4fnH6%w=X6@>TPxpqvFyvfZ@wIfO?@cT5+
zR#INZ6H;TWuXdqFmph4XI6Y*^S2pQ_Hfec^0^HNL%^B7D6a7}0Cwr|`ySei8kRd$h
zkk6C%q~W_!K=tY-fq*uCnGGdgizN8xE*GBl{IX@dxU&muI_q&^c_>WBtJmCIcx_r@
z2k{FnKxuFy48OtPq4_YvUI+|Ei4tCzBbiG&ffTSVS1gjdrrT!
zgH>!iTS!saFe#894GmM@ZM*UIZbyZ+393NV3C(P1kTRSGCOAJ}I7t5$Ej}6&>-5Wd
zS`|5jI=rY0l!n~M-o6FI!0^_v)y;IU)
zH^27ZI0_u5od|reTKmOqB{nElf6{Hr_nA~9;``AXAv=)MM>LQmSVu>({(OhLvk#BA
zLM?2;1OH6w2Z;ld6F`#hmbhMSR(x9$fE$J99X+?*XRBiz!5^u!X_Yuj@r~kTr@Ak{
zJ6GKL?3it5IL32$O>CBSab}))K`YFu)&uu-0Gs2@fA-Icb$>_YAR}0^FyAi;14Aoc
zx0em~*Bz|YM7#-J^I6fxcHvn1rP(dM9QkeQDn~HeK-da6D@M|Td5kg38PA(m9`xt7
z+#!x(vzg_smK-gx*`*=wvAtz?ZOHQ@b~w@+fe}t(B*4KIB^=hb1~$;4d{qov*^TwC
zO%Ij~f38J8zb^}mQN7KSd?ZZxHF(wJRnyq8p>M4@GRc=~pYpmQ?X}bpN_X>FATc0BvSE##J3)m=F9z!dY_lbzF3V{=4jy
z5n?JL^_4~?P>>AIFkJFI(qsGGS`DeE=E9()o%LVHJ)|DlWJ+6cE<)h7mcxz2ll0Rh
zlBx+3v@H>-Czx_H-dQhhZ`t}Cr^LGqW{fLl%dwh5%8X=O)!c2-_0ackBxnSjiaZ34
zhBd&K-V0mNwQybSsCbKFZK!xMz3fHFqska@M79|2G*DR2Ym&6S}F&rK6C?w{&8JtwNP)Gpz?IsTd9lGG-
zcy;6~Jd%ba!6W^lXvPm7`ov5-8mz9B9z%JC{pTI&ZHCTR))oyCV{^?`lwS>)
z@j0y;#xuc9+B-A@Y>$^x%nUj3+k*T58YJxV!cBSFELyZRANzX5*w-|yP?
zbI*{TUP$!!S*Xm!o%vS+kcKdwDLO0Z5^i#n>ff#+cQ}^6VIT8d(9Gon-}s9~ge0f=
z#I8X0g!6gy!@Aec^9qWn=xwSs3zSPG&;cR~@CYV6=i-eI7hK(Q>wI2UG|Z9cEtN#g
z&Z@lTN4As95d0NAo;6L<3^N_U6p!P4);B3JRi!i`oF)ejL62U;~2nkAlI
zQH|guJpAKR?g=BWJWl$D5nLot?XL<9&qzD6R(uM9-wPZ;9Yu!g=_qoYD5)!+H+$aW
z;5~J}rR2W27R;a}7JktX|2s#BD!^4Nxj^sXjqsNwveeYF*W~+Pb%B
zTdQ@nSnH^$FV?!M*1fH(uGjTi;rE<-GA`jJN`HU6`6!U+z4x4FexL9293;DU`?>ld
z-{hE1ox(#pWM_2^VZxNz2uYH^ow{x!{r)w^-{T9vO`DnOi9%T}N1+XSLARk
zTUewp8Z=r(qEe^KVblXOx>4k--XM?DGWm?o;3Yx0w8xLKohu?jQ4g`}IVM}ns0qlXY`5$oq@?=xEQ4>mr=)%4+A6!;RavD4NBXP(h7x;TPX|3KP&Q;g$!J5
zgga?CMv=v`28L6l6%{aXIpvh+x>YRK{et}k@y`ZGoGN_{Rdyf~eKD{_+JqUK8`#!QZ%CVs6z*r`Sxzuf_>QVl{1arVS%@1Hoi
zx?ja%)K=`df@=j1H)5jfs6tyQ3964K1mK%5uZOe<95@;Ui`{`=c{OvFhr^O{CU0vL
z_|b;GsHNCN0)v-_cZ~qGoHfpTURv05Hwq{J-=R@PEA>n=#};Z}i+#XZS+1y2#?qZq
z{Agr+_l+G&W9e3@9cdt%a5|+{k!93q;R1*+IXaeO)Y0_4)CHe9bgAXv6J#AxchRL<
zgOt^j2Pi)%637d-FO}i%TFngFTBcfB+xw6ZM-@iyBf$lEKmIXi!FCx65SnsdKIWzt
z=?zT2+kAZBny#DgepR`6WEQBkF9Uw0G%#x73)GTb0`afqFJ3iRw6!<2D2L+i!*USW
zqxsMZ7A3*EOZ06NE5eMZ8C_qVl7l}=eZGSHjV>}UgCT6OT-Tq+UkN~nli==yRjoXS
z9iJj@43=0G&u9x6ZjvPOln)8mmX{lD{9)pKwC{q~KMkMB#%kfyUy7XYH~W6*6jCvy
z2Z9aO%xwY-6^3LGgO*Y1_?T>SQ@4-s_BOH*|8pJk&6=w&nK*S02_S1XUTpGm-Gec;
zdafxciapmy8if7Rd#^vbdCyAJ+tFU~Lqc^52!OVxK
zp_t+H;gtEz14#7_USsi&SIXFyTc*a>$`WE(W0sb&C%gyOeB-D55wZq#btF7XMld;I
zwMgsig(nu}`TGvI*Z@V?N{tU2DNGLJU#>__tg#z1oPKn~(;GDL)Y24b(?eIvp}f9|*+F>&pU+U$&9ks!zh5!1l;mJA!2yLI>z
z6eMax8b+%gtbxqUa(?v?-o>rj+~j;>Jc_S{C}MJ9?J8Khn8ARTx00`Wc;IZEo8tLU
z5PB{7Vv$68G!S{Yy*T~igNIdBy@DTBp%-pAVE!xP(rF(&MZH8;59qJgt0cvp
zqzH|~iTzTQ;~&4+BaW&C(x86B%Y;Yerhwz#R)YUKNPF(tCq7+JV^QBp;K3VM_7cs6
z8|Odk=ueZLc-G?ah$ZWjY!q$Gh8;IV=!FEY>HA$t*p49$QJ|Rl@QWM50np=~NHV5?
zz5TTzZ*Y2M`j%2>^iT%x7sya9Ld6p|$#8h1UNm*bTS88WNr9)!HDA;|1~)=vy8FDIE1qT)Sb;{t61?9cf&&nsN5P<2-Lw
z{94vO6m@zl?Zaf*DC_Z`iI0_~P-MKJgd(cdw!)ne7UMOD7PAuK~>HzwU!7U%dBz
z`vXIkezg>Je7on9yT~K>7}w*6V|xqlo%>1LaI0fdTA_0CP`3npGwnuNryNyX;pL#@mM+b~7Hbf}ZUNR<(j
z%cw>%T%Cxnu6Wn%5k1TBr{9R@*a6BcM%!)fwxfKG#b0&k+{d_~{84SfG9MHLwn)nS
z-%+ekM@pnOSp+I;q
z#agdH<9>^HQ7m51@S2ZdAz(0Lt%X!0_ZJc=-Zb#MH23N6yJ`izgn+MR5q|aL-Pk8F
z$GX~q{H9cE)jCl*A7spMfP^;Hqw)XQ{x^frznl<~;Y%r7e!RZWd61(Zmqm$=R1@(5
zA)OE@EEj^1Gf^#Wo*y}E!}5%g|Bu91bGIJb+#|0?9vCeS;{}KrYPt{rhS8r~z~`q7
zYf2+zjrd@e4nd`HV-1W>4`_&jQL}iw<{|u3Y-ACR&Oa1%@8X8zL^a^s@9)e8#)tL92S?A$BZ}hj;-Bg2G8Qv~c6r
zXWHg=;-yI*raTEHTMksVsm1~ljT-wcL(aG$cgK(AowFt(KN7uYfg1&+8D|)R{J>F)
z=@M7080-DvhDui&i)`v(P!kk{dLUS|K(?h2_LYHroISgMwwGr(MOfe=I
z^RpO^eofXI^-YQC;3KmmI+j;l$aVz8LhC%ZD8sk_02Fl$nn&~|zlcGoJ#Qk;Sn55plX2v$
zC_BkayzJq#8HvjDwov_+FS~QLXy)>cc9vv~6@{G@CRZg1orkorkJ8c#=
zXYJ75=D=qG1J(ub`B5GZJSoFDIpM1-i;rEcxAHd>V0Czt#iuZ%jgb4jTo7LH%CNTA
z&i^zOFG%>1LnPyIvVjU9
zr3>Jh`s|p{CDT^iaO~FBeSsFqhN7TiV5}|}%7ZED>tEDn{h_e_i9;jgCH1nC
z?cf+wT(K;Gh9}#efNKQq+oI&mu8OqPj^tpff>H_l$)xZl5#NsJs@$yLBQ91huXF6r
z7N>gJS&h}31auW`X$epjRP{%aI<2_=`MDPk!k5L;qK%|$1kA<61MNQUHh+o|y<_Va
zdIfbSo=+SDxrc`K))&?}p#XgNaLkzJL2g|fXGx0)ZEVp`_AActI3H5ceb7`P3bF7F
z76;?2vv89?f$IM9e7Q2$qrShLaBCG7u(KSiQ7fY8cT=8ojl?J4DUEnM=e=~gWAThj
z;irj$Yjm+>q!TU=Y`Jc3Nxy%+ZDAQs3(N2nYr1afvSXyX3x4si_=mQuw@ji|V-H~D
z3$q%uDk-Ti^T9v#?9gNM?U)XzuV_@TNgyxi?VL%sXlS+F59vzqX+WdWllYeD&09Sx
zfp5KWv&z;pZp@dK(iU*F2qY4gfwGX`zNk$Oof8nrkFm!5{32^ibSuHL->c}C;io!@
zn%FwDB9_ssI86b`bHO)3EXDZh&_V309P}XKUPi$>rgR@VK1qH(EWcZ$J%d>^g#a^xd
z3chvLPHePIYZh-d<=4DGrfn>JyRID)ES6TDT)!{i~Z4e;;E
zK?%*jPWiSr03i&rjC$6mC6Q9^6K@2#!ni6=EV71HmpZuHvH71IPlJZna1CA8D
zVNU)>IbH9Eq}TyUR$&T|fjR24WSWPUg*v`@Yxv9K}%6b|}n&*&|^Lb#}r3Sr{O0C{DdT
zKeQ@y*bf=Pp$wXS^onRLs~Sa-5@khsZi~=@j^2Uz!
zttq>2o6+rfoX{1lelSF1$OU#Ecnd%ZN!!B@J`O&;N<4L&BPX9*NL+g@;YrvUTDE-P
zhZ_g%EFCtt`}&$a^Jo|^FgMqmNSYxp{C8eVVQR-OD`|6I+zC{I)_@3tGxgeBoN#OZ
zg0C}A@O9>ueDc+EX~nbC(@_gCzv44SAMh?-u+7VSor5HJbDz^*zyFeW1bJ7p@-|Uu
zw`3MU{moVbHRprAv5~AG_0`GC^yNOZ
z^dxUJHcT|2Q!Xy0^5t({mEw&$-a^D!D@s3k9|M`s|J>(x|4)nFs`4ZxE2Pv3pQVm3
z3z{;)PN{5Gwy<R
zcgZTd7hXCYy|A~{-D>>QThu`<|LyX;i7%b}FIRqYp=Z>iDtPs(eEq1$lL{De5WYIP
z6<-f*44+JEnIu8WGD^myplBz6v6h!J4n5v{al6lN-Vg`cyop%|4Qgwg&$A#r;ZEYM
z;4kNNHS>zqr^on&N@o+2(~G0iwkR#-$L!&1N9e}fE#zkh&AG+&VB9TP
zf(K0>Sa0NTu3gO%u|{5}5rB{0=YF^(FPlC*+EELD->iilp$RpeK>zPScvK<)MEv-|KAHZ`FQ2bQ?}}v;VfH69fF0-Hrwh9J
zw4K?cSB`US@M|=k3^c=7c!D1^g2H?^p{*x&ET|QnizF>1c6igLOJahCq2OwXPOeuL
z@whIHO(28vbS9gSm3nWCaL>@nmCrAHcMS!K$$%#rQqu@drPEYHS9&d8{6|6+1vWw&
z!>sre9u$~Dv9AA%84-*X(mRU3>$Ci(6ObWNs}^>?nnf%CS*t62A4owxN)
zt&7WAhiyE?DE;g}2J59Y$}01GV3ZSjRQ3A7-6{!AsCQW!IpglLH&&+*s!XRec-sy{
z1*ib8AF$}};iZRX*qNEMTp~Q!F@V+O2;8F~@3aGAPIjEM#eIXgI8;OhIdH_oVm?rs
z8JMw#x@e|5{(jZkONUn6KT5%#4W0m)#`n4Pgi#~MH^|8nLT%6p25{s``=`E>TYa4(
zK1#@&nQ4?Ts2+(g2Ua$Ilr^hQ65=QL#c?>l2r~dTQ*s?2&HQ>fptbl{tDPfwj;ccqL***^xZTjs!5@>3qjUOyd*3i|>*OgQk_K
zu7UGiO#>ubrMpYgTjF9#Ze;)p=v@y%y9-{$9`Kj^Fb0jC*qQubc`frOjZRPZn?Jd<
zv|swu^z?dZxU{s?^3U`Ke5PV?M%xuD%25!BPt`pSMn*wRG~mbyn<2SZ)~0(W_uuWn
zK2als`A9x4Ry#mMBJsSu6ElBrvu^}7G;!?-s08!Gd*GK|T5Ug-ZDf5{-l-INWoQqleN+@8XMF7AG|HDehlJ&umT5jgt-Il2_uNT`gQj~LuKvkWN@28Ryd=R2)zIRy+w3R=jlz!XIaTNIS1@m
zHHw>;`!6MTE7!|k&PL6t6IHJ-s3VyYUJglkmKWZ5yw9%bfApic}y#7%Bp?KBQdDm6d{
zF_)Zp1VRz|S^Pjap)J!mrB0vCa{2reN4fnH6%w=X6@>TPxpqvFyvfZ@wIfO?@cT5+
zR#INZ6H;TWuXdqFmph4XI6Y*^S2pQ_Hfec^0^HNL%^B7D6a7}0Cwr|`ySei8kRd$h
zkk6C%q~W_!K=tY-fq*uCnGGdgizN8xE*GBl{IX@dxU&muI_q&^c_>WBtJmCIcx_r@
z2k{FnKxuFy48OtPq4_YvUI+|Ei4tCzBbiG&ffTSVS1gjdrrT!
zgH>!iTS!saFe#894GmM@ZM*UIZbyZ+393NV3C(P1kTRSGCOAJ}I7t5$Ej}6&>-5Wd
zS`|5jI=rY0l!n~M-o6FI!0^_v)y;IU)
zH^27ZI0_u5od|reTKmOqB{nElf6{Hr_nA~9;``AXAv=)MM>LQmSVu>({(OhLvk#BA
zLM?2;1OH6w2Z;ld6F`#hmbhMSR(x9$fE$J99X+?*XRBiz!5^u!X_Yuj@r~kTr@Ak{
zJ6GKL?3it5IL32$O>CBSab}))K`YFu)&uu-0Gs2@fA-Icb$>_YAR}0^FyAi;14Aoc
zx0em~*Bz|YM7#-J^I6fxcHvn1rP(dM9QkeQDn~HeK-da6D@M|Td5kg38PA(m9`xt7
z+#!x(vzg_smK-gx*`*=wvAtz?ZOHQ@b~w@+fe}t(B*4KIB^=hb1~$;4d{qov*^TwC
zO%Ij~f38J8zb^}mQN7KSd?ZZxHF(wJRnyq8p>M4@GRc=~pYpmQ?X}bpN_X>FATc0BvSE##J3)m=F9z!dY_lbzF3V{=4jy
z5n?JL^_4~?P>>AIFkJFI(qsGGS`DeE=E9()o%LVHJ)|DlWJ+6cE<)h7mcxz2ll0Rh
zlBx+3v@H>-Czx_H-dQhhZ`t}Cr^LGqW{fLl%dwh5%8X=O)!c2-_0ackBxnSjiaZ34
zhBd&K-V0mNwQybSsCbKFZK!xMz3fHFqska@M79|2G*DR2Ym&6S}F&rK6C?w{&8JtwNP)Gpz?IsTd9lGG-
zcy;6~Jd%ba!6W^lXvPm7`ov5-8mz9B9z%JC{pTI&ZHCTR))oyCV{^?`lwS>)
z@j0y;#xuc9+B-A@Y>$^x%nUj3+k*T58YJxV!cBSFELyZRANzX5*w-|yP?
zbI*{TUP$!!S*Xm!o%vS+kcKdwDLO0Z5^i#n>ff#+cQ}^6VIT8d(9Gon-}s9~ge0f=
z#I8X0g!6gy!@Aec^9qWn=xwSs3zSPG&;cR~@CYV6=i-eI7hK(Q>wI2UG|Z9cEtN#g
z&Z@lTN4As95d0NAo;6L<3^N_U6p!P4);B3JRi!i`oF)ejL62U;~2nkAlI
zQH|guJpAKR?g=BWJWl$D5nLot?XL<9&qzD6R(uM9-wPZ;9Yu!g=_qoYD5)!+H+$aW
z;5~J}rR2W27R;a}7JktX|2s#BD!^4Nxj^sXjqsN8ZKn0m9R;wXgAQ%$7Nl;n`w61F1wrbs5(Y99W
zXtCB&QH!;%sMcs;jOd@V)1ro8%I1qV#*7f1Zj-?7jD#cl_SpI}Vb)d%bFTA-L6D*E@j_we`l((hAeB)Ot4S~gRz)TT383WH9b$!fKE
z`Er9^rIyDkG>S|ny}wE`lKj-^WszzohtcTWBnTJv`q6Rss=zL&m)P|zlc8pmdX-iq
z*Xh%hYK2b6=;SdPJ(J0>;RSko~G668CIU0pUXsQ$ZFFED%1w1MHGS;9{tn0ru~*39)Nx6-s@$
zR--hqEbJmykt<7LGRcMlJ?%%-D}WmftG6O?W$fi%sI}D_B{CTdT&`ruS{$0-zA2GA
z=QK!Ik0Qk`VGSC+DuSGzb0{&!a(;Xx6
z;^d|G@*k#!q7GtrROs|_PIhr11sQB&KnBr`&P8H}M_z64^X(G1r6`bGX;YF(dIhUD
z(90D>t9Dbn={3sD^*OkL8H>kK_nVbrADh)WvG(b+FDVYIzCu?ER-W|bchHDqpUl8ZC0?Eam%UzMA
z(qyWceoTI}LYGAhFH)mt^X;TKzxlEW;gh1LieD=bc9KEEZMVNxkq$!gvv(XxQ-
zVH~uAMM?19LS0+=Dt`lNM%S0EVBtT7E=NxOgyrj*fdE@tw)@ZHu6ZNGN^sAC%2uvJ
zPEHm#1`}3AGwNK1ohS)9<3Rx1^m4+DKaPEf4qS5kukaafr~;q0rN|C{bKr;0ex-wY
zA=qH`*e0-0AtZws)Qm#IVY0KV0J47b!OhZq-)X@Y&v)l2wSgWbg|lWgPP$z$uSh8
z+D_djPYM4GwG`SPF(2;n{TWTBK8wFRAMEvuNe@=MYtRjbb1fkx>YYg61rif^{ZAx^FEFnT`NK-S`g!kx%XY}Mh{nnxGwuEPj2)rX!
zL0Wq^JRv{3wrBs#4N#z^)Hv8kWHKTCviUM1NA8<&h=wGd(m?1IX@?K2+&8Zix<3x}
z5M78Fhy-kjqEJ$3EO$?tAK=h~>8Ee!U)JA65ud=Nf&~T7@;Lu`AT)vESfJ`)y&f
zo<
z;1!Gvns&W)+fdU*PczYjr_wX$vTT}95D<6PRMhURfa$Gy@vo;~IG4)aVx2%9ZjEZCU
z50byjcS{NarT%CHj_sSI829wmK5_0YkOuWmP9_}p=V8scodo}zpuX_pbB}JQv8ac}
za1;^zXPIjJt&3lDs!ccYkBM85m=|WqfE_nP=#>Poi~6q6f7hUf$Vbdbxy21)
zflji|B&n0Zs{h`UJuqc>%C;hV^w<$TFLXp%2o+4&;)r9Uu5Erb^f*Cn$;M(Lm<)wM
ztvC8#xI(Qos1@J`^?z#PggadK3mfj%S}&e02;?Wwx6BWS0t$&;ziIZtQkpE-(zs~O
zWbcB;RmqA&OBSxFN=%M}QhPMnF$G>kb$
z-A9$4c>lu=hXyTQyc~6Ux95|)$O1Ve?e)Wn{do^A{3LF;Rhci%g8>1YV(_)E_it1W
z{NOa|M;~c7ak1Fz9m)`fx?A9&%Y3Fp|*_q9GlKXTivl^bjg?+zV^t
z{+Y
zNiGwf#VAKIY@NXFweX%R&&7
zKjK;ViSAYs3qGKmwN6ydfsB!K5NK0A8TZf5H@6V_#10`xd?j()k2e?DC)fhHG+Itc
z;>#-l>7-nvW&IGcC#uEGbApC!TA4cH{}EoR@7869bI{G8L!-o#1pzOI%+U|%XV~YL
z@WshPn!Y9467Cy0M$c$;z_}>pHHyb=9>PCG1oT?B;Oyt`AP+Nh9>gkgfkd~g7zgHq
zD;^#(MBuTTtf)ye&{Ae9F!VN@A>!OCuZylkr@k)^T2+yU*s&}c@B$PB>6zo;yv^HR
zsGD2COWs=eI0=biCgjgahFpS1jlEVNdz_oK>&KF=X%mqbK`)v{heBzN)ek~mb`n%T
zm$+)x8267iRn($bWRY!ynjr1eK^aF4CA~zFUvSh+p;o1HL8$}s#m>W1j<=o{_TGOa
zsuuYd$%8y27wKPi+uaGZ62tmDa05f8N+Zt;l=oHSDFUZSCiIN(f*jTSvcr2%CobOS
zcfK*@ICNihJJqUDq@+gDYbQ^vEG{|cb811icUD-EHbV~zgS2SFy~XRa=tb|EL>WJ4
z07T^{jVCX;8gCbqzLD!U+4n8(3uv1Ctr3_m{tV^9ommTrp6qoA-XRgPfIzq^gf`ACIv6CI@
z(FDxsPT$ITZ7cH8NJ(jwU=xi8K7HTEpSqMo%tG!&vBhXE63yFBiihJktXRPdG
zWl3g0$?GcT{h5##j`tG#?h19dlojXSYrCkq)=C9lGISf*bey!)S~;#muaTcmadhEKBtSr@2?JX<+;$-o{7
zPsBNO1vb~FFZ*P)JL%Htl(_bIBdREI{mUhF>k
z(<2Xdi?dVlKu_zkQYl_};^udWt|9wuq(hc9-456GcoHADyQ@diq&81RTZvj`-HO!j
zWDtSI$g!Eg|x7)i19*|vkh0lLM>
zC|S%fjHYF(?Ff<&Qtp>oe2&wmXhuWKkJE;08CJFm{q6Vq=lsLA@f!1^Z)4wMzv%ZRr^c6eMdEr7z4WqYDlAdYHLcy3Q=@>*MR
z;8Ud}Qix>|xx9(%jC5CQm2-%T6)WqU_^ZX4-d0v)_9j8)jCR)q)C*GoV{x5V-Td;x
zD;w}-va~P*X<$KlW5S{KpY@nOS%KcO^b4Jwx)WF091XFDB5UhQ8(dH~eDrAe=$F1u
z-E4La-dpC399SXme`yovfE>x(LI)Z`2-8s)dh45Dh
zZdTEH`mOoWBHFR8f>I*T4YdymKFKZ%UNnFD6mcp|9v7<7X!WGCM0(71f!X0T-(R`Q
zF06P&t90V~EI%T!wRgx*|W@
zN4-a!0T_Y48i#<5{(CFv+i4f$JyBaB$0Q)h<iyY6c
zsTz4H%u!_F-Ni|QXMIrGH`Pmd8a1&52zdmfQ?jaD5;xo21`!tE>w^=tWxZO>L*b%!
zC(a#70g~g7)zj&`Oi9m&ji+rEM;VLWn~d8s^#RV73Gr*4V}HbXaH)7Hgtc@8F3)pu
zMR;uH&ReY>*Vm&4)pni8=%7^T<
z?6_r`-Z5~&9&sXO)P9U6PYV?+y1hkE263W3!vFL_cJK{X*&yH4f`cfsyv=lp#>
zqTEB=q$$*y1d#$`F}gM@kOa-a6PLQR{=3bc^H#9dGEAC0pO4qsKB#^)DsVVGthNNz
zMR@YZg>&2AYg=Yx@}vsA#ydSExHv9#!rg8j34LhA~2D$)FM^
z3nzcv;#XDo-_thSq?Rwf6pO5tV?L&t2Z$%}f48{v$AR(#w(yqU4y8>nRwcw+dj~A}
zYI&XR2FC}erDY_|=ek)nEq-&^IoEEc|1m4=A|b3$
zR%wAM^&brj#-EpJQh!Ydeh(#z?bHY=ITi$hz?89#Cj&SRgK+`sLBf9lgYNx(oAWQ(
zNZ0Byxf*Sxmkhq4SwNZ;(o#MQb*|W8!uO9DdpcBByAL&L~zc
znh_)|mzWT_nyGMKc;Uw0yNia*>AA7`00I%dQ5j7n&5#>@lO3Ly)ak1VIw>LUc1l49
zM1+I#Eky@A9NpA#V{WI?L1H0}lRi}UuBSR~xqS6mDwVxO63o)diH^?d@pTk%>{-rr
zYGn_NX+#OOrR>dh%&uG=vn!|M(`7HEr7zA-LoLM2m5Wh*z&$y^HZS(H_m$wSea^c5
z@k{J6bajAUIclT{V9-n}Z0{hOpcSFT6M2eP-w@*3C+A5c)fB4wiE-kP7=B
z@;f}_TI?v>T*Q=*#cMOQWZBfYNp>A^5Vehm1+}!t&vi)ymHV#vq4w5ECB2X<&xCSQ
zux`+;+)~#~mv-U);Oe%_iHA0+1HnD7&))p>%+qx@C^%Z!l_~c#adbZYb9BJ^d4AKQ
z92%BdnFruyWig7%S&c=(9k??anOO1qcee`hek5lhVs$rKKyyC>HIW#ARMdw4_O=DkXSOJ}VpUK5m$m`(rKU60{<m#j)5{)rIoW(^`!8?b
z5~uc@iJ3|=)Ye#!7ruD>z1TZ#zM9?Ln4eW0#p41h9l?lCDF{p19-mULs0g>NGx(cc
zvxcVI;#0<^C^v{{j4k|wagTTjPM9{J-iV=W`|1g7wYW|ZfJ5&KKU|R&Pa7I$tBJvF
z)>Pl20X2mr8{dQQC}P^zenn;H<#ZJ#BYfv^4`uq;$*c|OB}4uxoH}ks#E&l>aMa!V
z<;%6`eX(dFjQ*rZVZ}MPA&TxE?PfFy&a|%yV-BNZmPX>_!@6WQ$I8DJLoKNuh>b{nhpDBCUHTq**TY9=x>sy^ttOOwoP~xUtqSV?n7}O$q
zNMiIZp;D}GRMz7Q|5JayJ!K~saW^4@g9A!hCC)t2ZXBidV%z5CK*%-nfA9GG?4E&-
zs62hPZXR$|T)A%v0E8BDogC=kOfBwbUw;$pZl!)>-gng+vU^fpT-@4!^BG3rWhMBV
zFRhl68OJ6=pQ0y~<&W-HN^nfQtJ0w9_g}mVtAoF5cLG$(x}?N2gmE
zB{f|lJnzz9tH~4?dPC0r`iGzHG;y2rCUJ2ni3&2|9xY8C@dw#YyPC7qP{85Q&Q?B
z(?8QU_+07I)OM>@l^|b&PgOk+CTT%U6mVpu5+Zp}+_qE_
z8Ruo6n(;^51H-7HiEB?#hA&~_(1$Heu_UI{AXS)T_a&bJnw>k~Zf>943s
zl}tw#L%e~rX<3F=OX?eQ?(aQ!FXO_|8U>j^K+n0CLtf9Daj&KArRt$JpGA&7!5D%(
zDGOSqB;n>}z~P&^zR8|66IL6z!VubLEaE
zz`!_ADeZkrx_hwu-nXI?ClD?ynBIkxV-JR0@SLqpqkELs>HHaLX4_WZuiR1jBnpjj
z!jkEWcZN5cd=}LcCPTbg0Q-^P550yysb6~MwPimija6vioS%*;rs?u!9f!oLb5MQZ
zUCf&gmpHhWj6$fF6w3!4eRMkXYbWuhzR@nlW;w3c=3TQuKte6N^?&-Ypz2YW|LL>e
z`Y=2E%InR4@!v$!Wq#n-GuwYW(k^6J7xB`9Q9~xWM6}GAB1yC1a_zM_
zDec`3W{5i}_gGSWsxqD_^Ybbz!?^EnVTWBZZocD#jXaIZe`Ujyr%m<5+Xk{<47)#K
z3mvet5?^WKHxf>%63%37{ky_|XmH=29%!&*dn2@#nEhorKf!2(>w5Y-{Sgx`H?&;a~oO0u-zN?IL
z*XCk_F=2LbM0oZQk7pl91NI_sYcaW@v>B8kf9`haMena#MvFVUFcmc)8JBf|vkU3#
zZZEnqHMXPpg(g-wFcwA=VJy^mRAit8H+3C#=zSM&nJ|YpCElju8l8>jlR$fST%MOw
z=ls62udNU>3(r;v#{Mh{KoAl24U^t)xB2c~TlD~*mqD@&69UjlW>^)>*M7vXz(z`2
zd^#w??w5@;1+>ZQIE%jcRlJ(1v&4g0kLwKa!p
zbO3@+PPi~@;SBJ*4zA2<@zscLTUXjjQuL%n2?r2KyfF@>rrG0pQ%ijR+L1NLHY+z)
zyQ@T7Qv%`85ck^IvZvbb2XA8F922lt!MGjhP_`yqThT-7UX$)O8RK1#
ze*VzWKV11Pha!StRdiC
zN>)6)t*cj!D%Ye2Vnz4my^2Pi{sqd1{HeXFjK%m{Bp`wL`il}IYbOVEy3
zls=vh`*?S~$o<6|cbyUMwisbq%$6fmd9<#SdR=wDMfW4$zqPz2s7T5D;3QxJeB}fG
zRo(M8)T||8QmjQwf*jWH=Hf)YS8Q*72;nNUi{NIb%#4i7gb#Ptxb&=*k<`1qmSSemq2Cui{3Jox5(n$$>XKoiQw$O1
z!_Mz{n78{k5By>Gc3-;s^>#y|zeh!Btc)6e6$R;?(}Az^l5V}glYGq+Uc6u3ck={_
zvgrWxo$rj51K#=zZG=^1<4JLWdPq_2$qyUKUuNg#Q|(w}h$i}&MA!vQxp)rg;EwY*
z_FMb1GdgCa{?DVBDSL_6W?M9&`-CQN`zOZ600C$CbCB~6p3
zXPje3TzeY#9|ML6E*`A(2}n&owqCrd%IyUXIFBT!GU%jfolt2lJa5*#r)~Dt{g!rO
z#I<1LND=VMvbf)yLsS87X9_(!7k7len!a+6=gj>JZ66>^;^tP#;3;vj&~!Mu%&-SU
z=Qh9|3zpriT2QmcnN!Y=JJ;;%ac`9}8Acl3YHi-oXCL}oDchLAn)gKWA#x7$MkapN
U
Date: Sun, 15 Dec 2019 22:02:11 +0100
Subject: [PATCH 81/89] Travis: Test against SonarQube 8.0
---
.github/travis-build.sh | 4 ++++
.travis.yml | 2 +-
README.md | 2 +-
codenarc-converter/pom.xml | 23 ++++-------------------
pom.xml | 16 ++++++++++++++++
5 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/.github/travis-build.sh b/.github/travis-build.sh
index 9cd8b991..3fac0d1c 100755
--- a/.github/travis-build.sh
+++ b/.github/travis-build.sh
@@ -6,6 +6,10 @@ if [ "$SONAR_VERSION" ]
then
add="$add -Dsonar.version=$SONAR_VERSION"
+ case $SONAR_VERSION in
+ 8*) add="$add -PtestModernSonarQube" ;;
+ esac
+
# Workaround until https://jira.sonarsource.com/browse/TRAVIS-19 is fixed
# See also https://community.sonarsource.com/t/travis-plugin-is-failing-on-external-pull-request/807/7
elif [ -n "$SONAR_SCANNER_HOME" ]
diff --git a/.travis.yml b/.travis.yml
index 9e1c7632..e403bb86 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ jdk:
env:
- SONAR_VERSION=
- SONAR_VERSION=7.9
-#- SONAR_VERSION=8.0 - not compatible yet
+- SONAR_VERSION=8.0
# Install step is redundant
install: true
diff --git a/README.md b/README.md
index 4b32a052..0ac68e6a 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Plugin | 1.4/1.5 | 1.6 | 1.7
----------|---------|---------|-----
CodeNarc | 0.25.2 | 1.4 | 1.4
GMetrics | 0.7 | 1.0 | 1.0
-SonarQube | 5.6-6.7 | 6.7-7.9 | 7.8-7.9
+SonarQube | 5.6-6.7 | 6.7-7.9 | 7.8-8.0
## Steps to Analyze a Groovy Project
1. Install SonarQube Server
diff --git a/codenarc-converter/pom.xml b/codenarc-converter/pom.xml
index 374e13ce..bf75ff5b 100644
--- a/codenarc-converter/pom.xml
+++ b/codenarc-converter/pom.xml
@@ -54,6 +54,10 @@
commons-langcommons-lang
+
+ junit
+ junit
+ org.assertjassertj-core
@@ -73,25 +77,6 @@
-
- m2eHack
-
-
- m2e.version
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.6
-
-
-
-
- run-converter
diff --git a/pom.xml b/pom.xml
index 7b7f3be9..9a81b2d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -170,4 +170,20 @@
+
+
+
+
+ testModernSonarQube
+
+
+
+ org.sonarsource.sonarqube
+ sonar-plugin-api-impl
+ ${sonar.version}
+ test
+
+
+
+
From 6644a0fb61f741d5b4abd524b8ada5942b45cdf6 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sun, 15 Dec 2019 22:36:55 +0100
Subject: [PATCH 82/89] Tell Maven to not alter paths for sub-projects
This needs a pretty recent Maven (at least 3.6.1,
see MNG-6059 for details)
---
pom.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pom.xml b/pom.xml
index 9a81b2d9..97b711c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,5 +1,5 @@
-
+4.0.0
@@ -52,11 +52,11 @@
codenarc-converter
-
+ scm:git:git@github.com:Inform-Software/sonar-groovy.gitscm:git:git@github.com:Inform-Software/sonar-groovy.git
- https://github.com/Inform-Software/sonar-groovy
+ https://github.com/Inform-Software/sonar-groovy/tree/masterHEAD
From df9762ecbe9c96473bd63b8ebb35b4662ebca10c Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Sun, 15 Dec 2019 22:40:28 +0100
Subject: [PATCH 83/89] AppVeyor: Update build image for recent Maven
---
.appveyor.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.appveyor.yml b/.appveyor.yml
index 75341945..696bcb3d 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,4 +1,5 @@
version: '{build}'
+image: Visual Studio 2019
cache:
- C:\Users\appveyor\.m2
From 4c1b566868ab140f8a47d788a5c083cb6b6ec899 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Mon, 11 May 2020 11:03:16 +0200
Subject: [PATCH 84/89] Test against SonarQube 8.3
---
.travis.yml | 1 +
README.md | 2 +-
.../org/sonar/plugins/groovy/TestUtils.java | 20 +++++++++++++++++++
.../jacoco/JaCoCoConfigurationTest.java | 9 +++------
.../groovy/jacoco/JaCoCoItSensorTest.java | 4 +---
.../groovy/jacoco/JaCoCoSensorTest.java | 4 +---
6 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index e403bb86..2dd9811c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,7 @@ env:
- SONAR_VERSION=
- SONAR_VERSION=7.9
- SONAR_VERSION=8.0
+- SONAR_VERSION=8.3.0.34182
# Install step is redundant
install: true
diff --git a/README.md b/README.md
index 0ac68e6a..723d36c1 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Plugin | 1.4/1.5 | 1.6 | 1.7
----------|---------|---------|-----
CodeNarc | 0.25.2 | 1.4 | 1.4
GMetrics | 0.7 | 1.0 | 1.0
-SonarQube | 5.6-6.7 | 6.7-7.9 | 7.8-8.0
+SonarQube | 5.6-6.7 | 6.7-7.9 | 7.8-8.3
## Steps to Analyze a Groovy Project
1. Install SonarQube Server
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/TestUtils.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/TestUtils.java
index 5baa01f6..9832a8e8 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/TestUtils.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/TestUtils.java
@@ -20,10 +20,16 @@
package org.sonar.plugins.groovy;
import java.io.File;
+import java.lang.reflect.Constructor;
import java.net.URL;
import java.nio.file.Path;
+import java.util.Collection;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.utils.System2;
+import org.sonar.plugins.groovy.jacoco.JaCoCoConfiguration;
public final class TestUtils {
@@ -63,4 +69,18 @@ public static Path getResource(Class> baseClass, String path) {
resourcePath += path;
return getResource(resourcePath).toPath();
}
+
+ public static MapSettings jacocoDefaultSettings() {
+ PropertyDefinitions prop = null;
+ try {
+ // Legacy declaration, doesn't compile on modern SonarQube
+ Constructor c =
+ PropertyDefinitions.class.getConstructor(Collection.class);
+ prop = c.newInstance(JaCoCoConfiguration.getPropertyDefinitions());
+ } catch (ReflectiveOperationException | IllegalArgumentException e) {
+ prop =
+ new PropertyDefinitions(System2.INSTANCE, JaCoCoConfiguration.getPropertyDefinitions());
+ }
+ return new MapSettings(prop);
+ }
}
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoConfigurationTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoConfigurationTest.java
index 4e4391f2..381abb10 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoConfigurationTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoConfigurationTest.java
@@ -26,27 +26,24 @@
import org.junit.Test;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
-import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.plugins.groovy.TestUtils;
import org.sonar.plugins.groovy.foundation.Groovy;
public class JaCoCoConfigurationTest {
- private MapSettings settings;
+ private MapSettings settings = TestUtils.jacocoDefaultSettings();
private JaCoCoConfiguration jacocoSettings;
private DefaultFileSystem fileSystem;
@Before
public void setUp() {
- settings =
- new MapSettings(
- new PropertyDefinitions().addComponents(JaCoCoConfiguration.getPropertyDefinitions()));
fileSystem = new DefaultFileSystem(Paths.get("."));
jacocoSettings = new JaCoCoConfiguration(settings, fileSystem);
}
@Test
- public void shouldExecuteOnProject() throws Exception {
+ public void shouldExecuteOnProject() {
// no files
assertThat(jacocoSettings.shouldExecuteOnProject(true)).isFalse();
assertThat(jacocoSettings.shouldExecuteOnProject(false)).isFalse();
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
index 8e28c7c1..58ac15ac 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
@@ -32,7 +32,6 @@
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
-import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.plugins.groovy.GroovyPlugin;
@@ -44,8 +43,7 @@ public class JaCoCoItSensorTest {
@Rule public final TemporaryFolder tmpDir = new TemporaryFolder();
- private MapSettings settings =
- new MapSettings(new PropertyDefinitions(JaCoCoConfiguration.getPropertyDefinitions()));
+ private MapSettings settings = TestUtils.jacocoDefaultSettings();
private JaCoCoSensor sensor;
@Before
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
index b2ff4e23..daf7c326 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
@@ -35,7 +35,6 @@
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.batch.sensor.internal.SensorContextTester;
-import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.plugins.groovy.GroovyPlugin;
@@ -50,8 +49,7 @@ public class JaCoCoSensorTest {
@Rule
public ExpectedException exception = ExpectedException.none();
- private MapSettings settings =
- new MapSettings(new PropertyDefinitions(JaCoCoConfiguration.getPropertyDefinitions()));
+ private MapSettings settings = TestUtils.jacocoDefaultSettings();
private JaCoCoSensor sensor;
private void initWithJaCoCoVersion(String jacocoVersion) throws IOException {
From 29fb93d90676cfb830a64da1ac86ff0ecd2b0823 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Mon, 11 May 2020 11:04:44 +0200
Subject: [PATCH 85/89] Disable JaCoCo sensor if JaCoCo XML exists
---
CHANGELOG.md | 2 +
README.md | 10 ++-
.../plugins/groovy/jacoco/JaCoCoSensor.java | 71 +++++++++++++++++--
.../groovy/jacoco/JaCoCoItSensorTest.java | 21 +++---
.../jacoco/JaCoCoOverallSensorTest.java | 66 +++++++++++++----
.../groovy/jacoco/JaCoCoSensorTest.java | 44 ++++++------
6 files changed, 155 insertions(+), 59 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3f9aedc..2a21a89e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Remove backwards compatibility hacks (drop support for everything older then
SonarQube 7.8)
- Minor dependency updates
+- Deprecates support for JaCoCo binary format (use the SonarQube JaCoCo plugin
+ instead)
### Removed
- Compatibility with JaCoCo older the 0.7.5 (released in mid-2015)
diff --git a/README.md b/README.md
index 723d36c1..fccc5395 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,13 @@ Get test builds from [AppVeyor](https://ci.appveyor.com/project/TobiX/sonar-groo
This plugin enables analysis of Groovy within SonarQube.
It leverages [CodeNarc](http://codenarc.sourceforge.net/) to raise issues
-against coding rules, [GMetrics](http://gmetrics.sourceforge.net/) for
-cyclomatic complexity and [Cobertura](http://cobertura.sourceforge.net/) or
-[JaCoCo](http://www.eclemma.org/jacoco/) for code coverage.
+against coding rules and [GMetrics](http://gmetrics.sourceforge.net/) for
+cyclomatic complexity.
+
+For code coverage, the SonarQube [JaCoCo](http://www.eclemma.org/jacoco/)
+plugin should be used. Additionally, this plugin still supports importing
+binary JaCoCo reports (deprecated, will be removed in the future) and
+[Cobertura](http://cobertura.sourceforge.net/).
Plugin | 1.4/1.5 | 1.6 | 1.7
----------|---------|---------|-----
diff --git a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensor.java b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensor.java
index 569dd790..450d26e6 100644
--- a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensor.java
+++ b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensor.java
@@ -20,33 +20,47 @@
package org.sonar.plugins.groovy.jacoco;
import java.io.File;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Arrays;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.config.Settings;
+import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.plugins.groovy.foundation.Groovy;
import org.sonar.plugins.groovy.foundation.GroovyFileSystem;
public class JaCoCoSensor implements Sensor {
+ private static final Logger LOG = Loggers.get(JaCoCoSensor.class.getName());
+
public static final String JACOCO_OVERALL = "jacoco-overall.exec";
private final JaCoCoConfiguration configuration;
private final GroovyFileSystem fileSystem;
private final PathResolver pathResolver;
private final Settings settings;
+ private final AnalysisWarnings analysisWarnings;
+ static final String JACOCO_XML_PROPERTY = "sonar.coverage.jacoco.xmlReportPaths";
+ private static final String[] JACOCO_XML_DEFAULT_PATHS = {
+ "target/site/jacoco/jacoco.xml", "build/reports/jacoco/test/jacocoTestReport.xml"
+ };
public JaCoCoSensor(
JaCoCoConfiguration configuration,
GroovyFileSystem fileSystem,
PathResolver pathResolver,
- Settings settings) {
+ Settings settings,
+ AnalysisWarnings analysisWarnings) {
this.configuration = configuration;
this.fileSystem = fileSystem;
this.pathResolver = pathResolver;
this.settings = settings;
+ this.analysisWarnings = analysisWarnings;
}
@Override
@@ -56,22 +70,65 @@ public void describe(SensorDescriptor descriptor) {
@Override
public void execute(SensorContext context) {
+ boolean hasXmlReport = hasXmlReport(context);
File baseDir = fileSystem.baseDir();
File reportUTs = pathResolver.relativeFile(baseDir, configuration.getReportPath());
File reportITs = pathResolver.relativeFile(baseDir, configuration.getItReportPath());
- if (shouldExecuteOnProject()) {
+
+ if (reportUTs.isFile()) {
+ warnAboutDeprecatedProperty(hasXmlReport, JaCoCoConfiguration.REPORT_PATH_PROPERTY);
+ }
+ if (reportITs.isFile()) {
+ warnAboutDeprecatedProperty(hasXmlReport, JaCoCoConfiguration.IT_REPORT_PATH_PROPERTY);
+ }
+ if (hasXmlReport) {
+ LOG.debug(
+ "JaCoCo XML report found, skipping processing of binary JaCoCo exec report.",
+ JACOCO_XML_PROPERTY);
+ return;
+ }
+
+ if (shouldExecuteOnProject(reportUTs.isFile(), reportITs.isFile())) {
Path reportOverall = context.fileSystem().workDir().toPath().resolve(JACOCO_OVERALL);
JaCoCoReportMerger.mergeReports(reportOverall, reportUTs, reportITs);
new JaCoCoAnalyzer(fileSystem, settings, reportOverall).analyse(context);
}
}
+ private void warnAboutDeprecatedProperty(boolean hasXmlReport, String deprecatedProperty) {
+ if (!hasXmlReport) {
+ addAnalysisWarning(
+ "Property '%s' is deprecated (JaCoCo binary format). '%s' should be used instead (JaCoCo XML format)."
+ + " Please check that the JaCoCo plugin is installed on your SonarQube Instance.",
+ deprecatedProperty, JACOCO_XML_PROPERTY);
+ } else if (settings.hasKey(deprecatedProperty)) {
+ // only log for those properties which were set explicitly
+ LOG.info(
+ "Both '{}' and '{}' were set. '{}' is deprecated therefore, only '{}' will be taken into account."
+ + " Please check that the JaCoCo plugin is installed on your SonarQube Instance.",
+ deprecatedProperty,
+ JACOCO_XML_PROPERTY,
+ deprecatedProperty,
+ JACOCO_XML_PROPERTY);
+ }
+ }
+
+ private static boolean hasXmlReport(SensorContext context) {
+ return context.config().hasKey(JACOCO_XML_PROPERTY)
+ || Arrays.stream(JACOCO_XML_DEFAULT_PATHS)
+ .map(path -> context.fileSystem().baseDir().toPath().resolve(path))
+ .anyMatch(Files::isRegularFile);
+ }
+
+ private void addAnalysisWarning(String format, Object... args) {
+ String msg = String.format(format, args);
+ LOG.warn(msg);
+ analysisWarnings.addUnique(msg);
+ }
+
// VisibleForTesting
- boolean shouldExecuteOnProject() {
- File baseDir = fileSystem.baseDir();
- File reportUTs = pathResolver.relativeFile(baseDir, configuration.getReportPath());
- File reportITs = pathResolver.relativeFile(baseDir, configuration.getItReportPath());
- boolean foundOneReport = reportUTs.isFile() || reportITs.isFile();
+ boolean shouldExecuteOnProject(boolean hasUT, boolean hasIT) {
+ boolean foundOneReport = hasUT || hasIT;
boolean shouldExecute = configuration.shouldExecuteOnProject(foundOneReport);
if (!foundOneReport && shouldExecute) {
JaCoCoExtensions.logger().info("JaCoCoSensor: No JaCoCo report found.");
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
index 58ac15ac..eec97405 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoItSensorTest.java
@@ -20,6 +20,8 @@
package org.sonar.plugins.groovy.jacoco;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -33,6 +35,7 @@
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.plugins.groovy.GroovyPlugin;
import org.sonar.plugins.groovy.TestUtils;
@@ -74,7 +77,11 @@ public void setUp() throws IOException {
sensor =
new JaCoCoSensor(
- configuration, new GroovyFileSystem(fileSystem), new PathResolver(), settings);
+ configuration,
+ new GroovyFileSystem(fileSystem),
+ new PathResolver(),
+ settings,
+ mock(AnalysisWarnings.class));
}
@Test
@@ -83,16 +90,4 @@ public void testDescription() {
sensor.describe(defaultSensorDescriptor);
assertThat(defaultSensorDescriptor.languages()).containsOnly(Groovy.KEY);
}
-
- @Test
- public void should_Execute_On_Project_only_if_exec_exists() {
- assertThat(sensor.shouldExecuteOnProject()).isTrue();
-
- settings.setProperty(JaCoCoConfiguration.IT_REPORT_PATH_PROPERTY, ".");
- assertThat(sensor.shouldExecuteOnProject()).isFalse();
-
- settings.setProperty(JaCoCoConfiguration.IT_REPORT_PATH_PROPERTY, "it.not.found.exec");
- assertThat(sensor.shouldExecuteOnProject()).isFalse();
- }
-
}
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java
index 9e5c40b2..cf8c4119 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoOverallSensorTest.java
@@ -20,6 +20,13 @@
package org.sonar.plugins.groovy.jacoco;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.ArgumentMatchers.anyString;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -27,12 +34,17 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.batch.sensor.internal.SensorContextTester;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.plugins.groovy.GroovyPlugin;
import org.sonar.plugins.groovy.TestUtils;
@@ -42,9 +54,15 @@
public class JaCoCoOverallSensorTest {
@Rule public final TemporaryFolder tmpDir = new TemporaryFolder();
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
private JaCoCoSensor sensor;
+ private InputFile inputFile;
private MapSettings settings = new MapSettings();
+ private SensorContextTester context;
+ @Mock
+ private AnalysisWarnings analysisWarnings;
@Before
public void before() throws IOException {
@@ -65,10 +83,11 @@ public void before() throws IOException {
settings.setProperty(GroovyPlugin.SONAR_GROOVY_BINARIES, ".");
- SensorContextTester context = SensorContextTester.create(outputDir);
+ context = SensorContextTester.create(outputDir);
context.fileSystem().setWorkDir(tmpDir.newFolder().toPath());
+ context.setSettings(settings);
- InputFile inputFile =
+ inputFile =
TestInputFileBuilder.create("", "example/Hello.groovy")
.setLanguage(Groovy.KEY)
.setType(Type.MAIN)
@@ -82,29 +101,52 @@ public void before() throws IOException {
configuration,
new GroovyFileSystem(context.fileSystem()),
new PathResolver(),
- settings);
+ settings,
+ analysisWarnings);
}
@Test
- public void test_description() {
+ public void testDescription() {
DefaultSensorDescriptor defaultSensorDescriptor = new DefaultSensorDescriptor();
sensor.describe(defaultSensorDescriptor);
assertThat(defaultSensorDescriptor.languages()).containsOnly(Groovy.KEY);
}
+
@Test
- public void should_Execute_On_Project_only_if_at_least_one_exec_exists() {
- settings.setProperty(JaCoCoConfiguration.IT_REPORT_PATH_PROPERTY, "jacoco-it.exec");
- settings.setProperty(JaCoCoConfiguration.REPORT_PATH_PROPERTY, "notexist.exec");
+ public void shouldExecuteOnProjectWithItExisting() {
configReports(false, true);
- assertThat(sensor.shouldExecuteOnProject()).isTrue();
+ sensor.execute(context);
+ assertThat(context.coveredConditions(inputFile.key(), 14), is(equalTo(2)));
+ verify(analysisWarnings).addUnique(anyString());
+ }
+
+ @Test
+ public void shouldExecuteOnProjectWithUtExisting() {
configReports(true, false);
- assertThat(sensor.shouldExecuteOnProject()).isTrue();
+ sensor.execute(context);
+ assertThat(context.coveredConditions(inputFile.key(), 14), is(equalTo(2)));
+ verify(analysisWarnings).addUnique(anyString());
+ }
+
+ @Test
+ public void shouldNotExecuteOnProjectWithoutExecutionData() {
+ configReports(false, false);
+ sensor.execute(context);
+ assertNull(context.coveredConditions(inputFile.key(), 14));
+ verify(analysisWarnings, never()).addUnique(anyString());
+ }
+
+
+ @Test
+ public void shouldNotExecuteIfJaCoCoXmlConfigured() {
+ settings.setProperty(JaCoCoSensor.JACOCO_XML_PROPERTY, "report.xml");
- settings.setProperty(JaCoCoConfiguration.IT_REPORT_PATH_PROPERTY, "notexist.exec");
- settings.setProperty(JaCoCoConfiguration.REPORT_PATH_PROPERTY, "notexist.exec");
- assertThat(sensor.shouldExecuteOnProject()).isFalse();
+ configReports(true, true);
+ sensor.execute(context);
+ assertNull(context.coveredConditions(inputFile.key(), 14));
+ verify(analysisWarnings, never()).addUnique(anyString());
}
private void configReports(boolean utReport, boolean itReport) {
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
index daf7c326..fe67bbf3 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/jacoco/JaCoCoSensorTest.java
@@ -20,11 +20,11 @@
package org.sonar.plugins.groovy.jacoco;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -36,6 +36,7 @@
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.batch.sensor.internal.SensorContextTester;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.plugins.groovy.GroovyPlugin;
import org.sonar.plugins.groovy.TestUtils;
@@ -46,8 +47,7 @@ public class JaCoCoSensorTest {
@Rule public final TemporaryFolder tmpDir = new TemporaryFolder();
- @Rule
- public ExpectedException exception = ExpectedException.none();
+ @Rule public ExpectedException exception = ExpectedException.none();
private MapSettings settings = TestUtils.jacocoDefaultSettings();
private JaCoCoSensor sensor;
@@ -80,11 +80,15 @@ private void initWithJaCoCoVersion(String jacocoVersion) throws IOException {
sensor =
new JaCoCoSensor(
- configuration, new GroovyFileSystem(fileSystem), new PathResolver(), settings);
+ configuration,
+ new GroovyFileSystem(fileSystem),
+ new PathResolver(),
+ settings,
+ mock(AnalysisWarnings.class));
}
@Test
- public void test_description() throws IOException {
+ public void testDescription() throws IOException {
initWithJaCoCoVersion("JaCoCoSensor_0_7_5");
DefaultSensorDescriptor defaultSensorDescriptor = new DefaultSensorDescriptor();
sensor.describe(defaultSensorDescriptor);
@@ -92,24 +96,13 @@ public void test_description() throws IOException {
}
@Test
- public void should_Execute_On_Project_only_if_exec_exists() throws IOException {
- initWithJaCoCoVersion("JaCoCoSensor_0_7_5");
-
- assertThat(sensor.shouldExecuteOnProject()).isTrue();
-
- settings.setProperty(JaCoCoConfiguration.REPORT_PATH_PROPERTY, ".");
- assertThat(sensor.shouldExecuteOnProject()).isFalse();
-
- settings.setProperty(JaCoCoConfiguration.REPORT_PATH_PROPERTY, "ut.not.found.exec");
- assertThat(sensor.shouldExecuteOnProject()).isFalse();
- }
-
- @Test
- public void test_read_execution_data_with_jacoco_0_7_4() throws IOException {
+ public void testReadExecutionDataWithJacoco074() throws IOException {
initWithJaCoCoVersion("JaCoCoSensor_0_7_4");
- SensorContextTester context = SensorContextTester.create(Paths.get("."));
- context.fileSystem().setWorkDir(tmpDir.newFolder().toPath());
+ Path workDir = tmpDir.newFolder().toPath();
+ SensorContextTester context = SensorContextTester.create(workDir);
+ context.setSettings(settings);
+ context.fileSystem().setWorkDir(workDir);
exception.expect(IllegalArgumentException.class);
exception.expectMessage(JaCoCoReportReader.INCOMPATIBLE_JACOCO_ERROR);
@@ -117,11 +110,14 @@ public void test_read_execution_data_with_jacoco_0_7_4() throws IOException {
}
@Test
- public void test_read_execution_data_with_jacoco_0_7_5() throws IOException {
+ public void testReadExecutionDataWithJacoco075() throws IOException {
initWithJaCoCoVersion("JaCoCoSensor_0_7_5");
- SensorContextTester context = SensorContextTester.create(Paths.get("."));
- context.fileSystem().setWorkDir(tmpDir.newFolder().toPath());
+ Path workDir = tmpDir.newFolder().toPath();
+ SensorContextTester context = SensorContextTester.create(workDir);
+ context.setSettings(settings);
+ context.fileSystem().setWorkDir(workDir);
+
sensor.execute(context);
verifyMeasures(context);
From f043bdf30556caf1541ab8673f7119dc0d54b248 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Mon, 11 May 2020 18:03:10 +0200
Subject: [PATCH 86/89] Remove 'test_success_density' metric (fixes #25)
---
.../groovy/surefire/GroovySurefireParser.java | 10 ----
.../surefire/GroovySurefireParserTest.java | 59 ++++++++++---------
.../surefire/GroovySurefireSensorTest.java | 24 +++-----
3 files changed, 38 insertions(+), 55 deletions(-)
diff --git a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/surefire/GroovySurefireParser.java b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/surefire/GroovySurefireParser.java
index 7e951256..8a8eef14 100644
--- a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/surefire/GroovySurefireParser.java
+++ b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/surefire/GroovySurefireParser.java
@@ -35,7 +35,6 @@
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.utils.MessageException;
-import org.sonar.api.utils.ParsingUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.plugins.groovy.foundation.Groovy;
@@ -139,15 +138,6 @@ private void save(UnitTestClassReport report, InputFile inputFile, SensorContext
saveMeasure(context, inputFile, CoreMetrics.TEST_FAILURES, report.getFailures());
saveMeasure(
context, inputFile, CoreMetrics.TEST_EXECUTION_TIME, report.getDurationMilliseconds());
- int passedTests = testsCount - report.getErrors() - report.getFailures();
- if (testsCount > 0) {
- double percentage = (passedTests * 100D) / testsCount;
- saveMeasure(
- context,
- inputFile,
- CoreMetrics.TEST_SUCCESS_DENSITY,
- ParsingUtils.scaleValue(percentage));
- }
}
protected InputFile getUnitTestInputFile(String classKey) {
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireParserTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireParserTest.java
index ba8ec03d..e411320b 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireParserTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireParserTest.java
@@ -27,7 +27,6 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import java.net.URISyntaxException;
import java.nio.file.Paths;
import org.junit.Before;
import org.junit.Test;
@@ -45,15 +44,12 @@
public class GroovySurefireParserTest {
- private FileSystem fs;
private GroovySurefireParser parser;
private Groovy groovy;
- private SensorContext context;
@Before
public void before() {
- context = mock(SensorContext.class);
- fs = new DefaultFileSystem(Paths.get("."));
+ FileSystem fs = new DefaultFileSystem(Paths.get("."));
MapSettings settings = new MapSettings();
settings.setProperty(GroovyPlugin.FILE_SUFFIXES_KEY, ".groovy,grvy");
@@ -69,58 +65,63 @@ public void before() {
}
@Test
- public void should_store_zero_tests_when_directory_is_null_or_non_existing_or_a_file()
- throws Exception {
+ public void shouldStoreZeroTestsWhenDirectoryIsNull() {
+ SensorContext context = mock(SensorContext.class);
parser.collect(context, null);
verify(context, never()).newMeasure();
+ }
- context = mock(SensorContext.class);
+ @Test
+ public void shouldStoreZeroTestsWhenDirectoryIsNonExisting() {
+ SensorContext context = mock(SensorContext.class);
parser.collect(context, getDir("nonExistingReportsDirectory"));
verify(context, never()).newMeasure();
+ }
- context = mock(SensorContext.class);
+ @Test
+ public void shouldStoreZeroTestsWhenDirectoryIsAFile() {
+ SensorContext context = mock(SensorContext.class);
parser.collect(context, getDir("file.txt"));
verify(context, never()).newMeasure();
}
@Test
- public void shouldAggregateReports() throws URISyntaxException {
+ public void shouldAggregateReports() {
SensorContextTester context = SensorContextTester.create(Paths.get("."));
parser.collect(context, getDir("multipleReports"));
- // Only 6 tests measures should be stored, no more: the TESTS-AllTests.xml must not be read as
- // there's 1 file result per unit test
- // (SONAR-2841).
- assertThat(context.measures(":ch.hortis.sonar.mvn.mc.MetricsCollectorRegistryTest")).hasSize(6);
- assertThat(context.measures(":ch.hortis.sonar.mvn.mc.CloverCollectorTest")).hasSize(6);
- assertThat(context.measures(":ch.hortis.sonar.mvn.mc.CheckstyleCollectorTest")).hasSize(6);
- assertThat(context.measures(":ch.hortis.sonar.mvn.SonarMojoTest")).hasSize(6);
- assertThat(context.measures(":ch.hortis.sonar.mvn.mc.JDependsCollectorTest")).hasSize(6);
- assertThat(context.measures(":ch.hortis.sonar.mvn.mc.JavaNCSSCollectorTest")).hasSize(6);
+ // Only 5 tests measures should be stored, no more: the TESTS-AllTests.xml must not be read as
+ // there's 1 file result per unit test (SONAR-2841).
+ assertThat(context.measures(":ch.hortis.sonar.mvn.mc.MetricsCollectorRegistryTest")).hasSize(5);
+ assertThat(context.measures(":ch.hortis.sonar.mvn.mc.CloverCollectorTest")).hasSize(5);
+ assertThat(context.measures(":ch.hortis.sonar.mvn.mc.CheckstyleCollectorTest")).hasSize(5);
+ assertThat(context.measures(":ch.hortis.sonar.mvn.SonarMojoTest")).hasSize(5);
+ assertThat(context.measures(":ch.hortis.sonar.mvn.mc.JDependsCollectorTest")).hasSize(5);
+ assertThat(context.measures(":ch.hortis.sonar.mvn.mc.JavaNCSSCollectorTest")).hasSize(5);
}
// SONAR-2841: if there's only a test suite report, then it should be read.
@Test
- public void shouldUseTestSuiteReportIfAlone() throws URISyntaxException {
+ public void shouldUseTestSuiteReportIfAlone() {
SensorContextTester context = SensorContextTester.create(Paths.get("."));
parser.collect(context, getDir("onlyTestSuiteReport"));
- assertThat(context.measures(":org.sonar.SecondTest")).hasSize(6);
- assertThat(context.measures(":org.sonar.JavaNCSSCollectorTest")).hasSize(6);
+ assertThat(context.measures(":org.sonar.SecondTest")).hasSize(5);
+ assertThat(context.measures(":org.sonar.JavaNCSSCollectorTest")).hasSize(5);
}
/** See http://jira.codehaus.org/browse/SONAR-2371 */
@Test
- public void shouldInsertZeroWhenNoReports() throws URISyntaxException {
+ public void shouldInsertZeroWhenNoReports() {
SensorContext context = mock(SensorContext.class);
parser.collect(context, getDir("noReports"));
verify(context, never()).newMeasure();
}
@Test
- public void shouldNotInsertZeroOnFiles() throws URISyntaxException {
+ public void shouldNotInsertZeroOnFiles() {
SensorContext context = mock(SensorContext.class);
parser.collect(context, getDir("noTests"));
@@ -128,7 +129,7 @@ public void shouldNotInsertZeroOnFiles() throws URISyntaxException {
}
@Test
- public void shouldMergeInnerClasses() throws URISyntaxException {
+ public void shouldMergeInnerClasses() {
SensorContextTester context = SensorContextTester.create(Paths.get("."));
parser.collect(context, getDir("innerClasses"));
@@ -153,7 +154,7 @@ public void shouldMergeInnerClasses() throws URISyntaxException {
}
@Test
- public void shouldMergeNestedInnerClasses() throws URISyntaxException {
+ public void shouldMergeNestedInnerClasses() {
SensorContextTester context = SensorContextTester.create(Paths.get("."));
parser.collect(context, getDir("nestedInnerClasses"));
@@ -165,7 +166,7 @@ public void shouldMergeNestedInnerClasses() throws URISyntaxException {
}
@Test
- public void should_not_count_negative_tests() throws URISyntaxException {
+ public void shouldNotCountNegativeTests() {
SensorContextTester context = SensorContextTester.create(Paths.get("."));
parser.collect(context, getDir("negativeTestTime"));
// Test times : -1.120, 0.644, 0.015 -> computed time : 0.659, ignore negative time.
@@ -178,13 +179,13 @@ public void should_not_count_negative_tests() throws URISyntaxException {
.isEqualTo(659);
}
- private java.io.File getDir(String dirname) throws URISyntaxException {
+ private java.io.File getDir(String dirname) {
return new java.io.File(
"src/test/resources/org/sonar/plugins/groovy/surefire/SurefireParserTest/" + dirname);
}
@Test
- public void should_generate_correct_predicate() throws URISyntaxException {
+ public void shouldGenerateCorrectPredicate() {
DefaultFileSystem fs = new DefaultFileSystem(Paths.get("."));
InputFile inputFile =
TestInputFileBuilder.create("", "src/test/org/sonar/JavaNCSSCollectorTest.groovy")
diff --git a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireSensorTest.java b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireSensorTest.java
index 7dfc77d5..3baf303a 100644
--- a/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireSensorTest.java
+++ b/sonar-groovy-plugin/src/test/java/org/sonar/plugins/groovy/surefire/GroovySurefireSensorTest.java
@@ -72,10 +72,7 @@ public void before() {
}
@Test
- public void test_description() {
- surefireSensor =
- new GroovySurefireSensor(
- new GroovySurefireParser(groovy, fs), new MapSettings(), fs, pathResolver);
+ public void testDescription() {
DefaultSensorDescriptor defaultSensorDescriptor = new DefaultSensorDescriptor();
surefireSensor.describe(defaultSensorDescriptor);
assertThat(defaultSensorDescriptor.languages()).containsOnly(Groovy.KEY);
@@ -86,9 +83,9 @@ public void shouldNotFailIfReportsNotFound() {
MapSettings settings = new MapSettings();
settings.setProperty(SurefireUtils.SUREFIRE_REPORTS_PATH_PROPERTY, "unknown");
- GroovySurefireSensor surefireSensor =
+ GroovySurefireSensor localSensor =
new GroovySurefireSensor(mock(GroovySurefireParser.class), settings, fs, pathResolver);
- surefireSensor.execute(mock(SensorContext.class));
+ localSensor.execute(mock(SensorContext.class));
}
@Test
@@ -107,10 +104,10 @@ public void shouldHandleTestSuiteDetails() throws URISyntaxException {
"/org/sonar/plugins/groovy/surefire/SurefireSensorTest/shouldHandleTestSuiteDetails/")
.toURI()));
- // 3 classes, 6 measures by class
- assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest")).hasSize(6);
- assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest2")).hasSize(6);
- assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest3")).hasSize(6);
+ // 3 classes, 5 measures by class
+ assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest")).hasSize(5);
+ assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest2")).hasSize(5);
+ assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest3")).hasSize(5);
assertThat(context.measure(":org.sonar.core.ExtensionsFinderTest", CoreMetrics.TESTS).value())
.isEqualTo(4);
@@ -212,7 +209,7 @@ public void shouldSaveErrorsAndFailuresInXML() throws URISyntaxException {
.isEqualTo(1);
assertThat(context.measure(":org.sonar.core.ExtensionsFinderTest", CoreMetrics.TESTS).value())
.isEqualTo(7);
- assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest")).hasSize(6);
+ assertThat(context.measures(":org.sonar.core.ExtensionsFinderTest")).hasSize(5);
}
@Test
@@ -247,8 +244,6 @@ public void successRatioIsZeroWhenAllTestsFail() throws URISyntaxException {
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TESTS).value()).isEqualTo(2);
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_FAILURES).value()).isEqualTo(1);
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_ERRORS).value()).isEqualTo(1);
- assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_SUCCESS_DENSITY).value())
- .isEqualTo(0);
}
@Test
@@ -268,8 +263,6 @@ public void measuresShouldNotIncludeSkippedTests() throws URISyntaxException {
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_FAILURES).value()).isEqualTo(1);
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_ERRORS).value()).isEqualTo(0);
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.SKIPPED_TESTS).value()).isEqualTo(1);
- assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_SUCCESS_DENSITY).value())
- .isEqualTo(50);
}
@Test
@@ -289,7 +282,6 @@ public void noSuccessRatioIfNoTests() throws URISyntaxException {
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_FAILURES).value()).isEqualTo(0);
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_ERRORS).value()).isEqualTo(0);
assertThat(context.measure(":org.sonar.Foo", CoreMetrics.SKIPPED_TESTS).value()).isEqualTo(2);
- assertThat(context.measure(":org.sonar.Foo", CoreMetrics.TEST_SUCCESS_DENSITY)).isNull();
}
@Test
From 03fb03e5540724cd16ecb940c4864fbe7f4b7278 Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Tue, 12 May 2020 09:39:36 +0200
Subject: [PATCH 87/89] Update documentation for coverage
---
README.md | 22 +++++-----------------
1 file changed, 5 insertions(+), 17 deletions(-)
diff --git a/README.md b/README.md
index fccc5395..1a02ac7c 100644
--- a/README.md
+++ b/README.md
@@ -54,8 +54,11 @@ folders). For Maven and gradle projects, the property is automatically set.
## Coverage Results Import
-The Groovy Plugin does not generate its own test coverage report, but re-uses
-the ones generated by Cobertura or JaCoCo.
+For coverage, it is recommended to use the generic [SonarQube JaCoCo
+plugin](https://community.sonarsource.com/t/coverage-test-data-importing-jacoco-coverage-report-in-xml-format/12151)
+instead of relying on this plugin to import coverage into SonarQube.
+Nevertheless, we support importing coverage from Cobertura (but this code path
+isn't used by the author of the plugin).
### Code Coverage with Cobertura
@@ -68,21 +71,6 @@ To display code coverage data:
XML report. The path may be absolute or relative to the project base
directory.
-### Code Coverage with JaCoCo
-
-To display code coverage data:
-
-1. Prior to the SonarQube analysis, execute your tests and generate the JaCoCo
- exec file(s).
-1. In order to be able to read the exec report file, and as JaCoCo bases its
- analysis on binaries, set the `sonar.groovy.binaries` property.
-1. Set the `sonar.groovy.jacoco.reportPath` property to the path to the JaCoCo
- exec file related to your unit tests.
-1. (Optional) If you are running integration tests on top of your unit tests,
- you may want to set the `sonar.groovy.jacoco.itReportPath` to the path to
- JaCoCo exec file related to the integration tests.
-1. Run the SonarQube analysis.
-
## Contributions
Contributions via GitHub [issues] and pull requests are very welcome. This
From 2715416fc088abe3c7e519f627e784679571c8dc Mon Sep 17 00:00:00 2001
From: Tobias Gruetzmacher
Date: Tue, 12 May 2020 09:45:09 +0200
Subject: [PATCH 88/89] Add distributionManagement for BinTray (see #18)
---
pom.xml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/pom.xml b/pom.xml
index 97b711c5..bbe8fdab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,13 @@
travis-cihttps://travis-ci.com/Inform-Software/sonar-groovy
+
+
+ bintray-tobix-sonar-groovy
+ TobiX-sonar-groovy
+ https://api.bintray.com/maven/tobix/sonar-groovy/sonar-groovy/;publish=1
+
+ 7.8
From db7308fbf0bea6e4d8b9805e07e0f4629a518d9a Mon Sep 17 00:00:00 2001
From: Pascal Porta
Date: Fri, 4 Sep 2020 12:12:32 +0200
Subject: [PATCH 89/89] JaCoCoAnalyzer: log missing file only if extension is
groovy
---
codenarc-converter/pom.xml | 2 +-
groovy-jacoco-previous/pom.xml | 2 +-
pom.xml | 2 +-
sonar-groovy-plugin/pom.xml | 2 +-
.../java/org/sonar/plugins/groovy/jacoco/JaCoCoAnalyzer.java | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/codenarc-converter/pom.xml b/codenarc-converter/pom.xml
index be426258..d6cc9d3a 100644
--- a/codenarc-converter/pom.xml
+++ b/codenarc-converter/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.7-SNAPSHOT
+ 1.7-CIT-MVN-162-SNAPSHOTsonar-codenarc-converter
diff --git a/groovy-jacoco-previous/pom.xml b/groovy-jacoco-previous/pom.xml
index 4c727bfb..dc9678f8 100644
--- a/groovy-jacoco-previous/pom.xml
+++ b/groovy-jacoco-previous/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.7-SNAPSHOT
+ 1.7-CIT-MVN-162-SNAPSHOTgroovy-jacoco-previous
diff --git a/pom.xml b/pom.xml
index 6025848d..7ab00723 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
org.sonarsource.groovygroovy
- 1.7-SNAPSHOT
+ 1.7-CIT-MVN-162-SNAPSHOTpomSonar Groovy
diff --git a/sonar-groovy-plugin/pom.xml b/sonar-groovy-plugin/pom.xml
index 6e123bb9..3fcb24dd 100644
--- a/sonar-groovy-plugin/pom.xml
+++ b/sonar-groovy-plugin/pom.xml
@@ -5,7 +5,7 @@
org.sonarsource.groovygroovy
- 1.7-SNAPSHOT
+ 1.7-CIT-MVN-162-SNAPSHOTsonar-groovy-plugin
diff --git a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoAnalyzer.java b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoAnalyzer.java
index 0d1eb4b7..6fc3d45f 100644
--- a/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoAnalyzer.java
+++ b/sonar-groovy-plugin/src/main/java/org/sonar/plugins/groovy/jacoco/JaCoCoAnalyzer.java
@@ -81,7 +81,7 @@ private InputFile getInputFile(ISourceFileCoverage coverage) {
String path = getFileRelativePath(coverage);
InputFile sourceInputFileFromRelativePath =
groovyFileSystem.sourceInputFileFromRelativePath(path);
- if (sourceInputFileFromRelativePath == null) {
+ if (sourceInputFileFromRelativePath == null && path.endsWith(".groovy")) {
JaCoCoExtensions.logger().warn("File not found: " + path);
}
return sourceInputFileFromRelativePath;