Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.
A method's cognitive complexity is based on a few simple rules:
Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
Code is considered more complex for each "break in the linear flow of the code"
Code is considered more complex when "flow breaking structures are nested"
Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.
A method's cognitive complexity is based on a few simple rules:
Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
Code is considered more complex for each "break in the linear flow of the code"
Code is considered more complex when "flow breaking structures are nested"
Checks that the groups of import declarations appear in the order specifiedby the user. If there is an import but its group is not specified in theconfiguration such an import should be placed at the end of the import list.
Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents
calling methods from handling true, system-generated exceptions differently than application-generated errors.
Noncompliant Code Example
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
Compliant Solution
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because overriding method has to follow signature of the throw declaration
in the superclass. The issue will be raised on superclass declaration of the method (or won't be raised at all if superclass is not part of the
analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod throws Exception {
doTheThing(); // this method throws Exception
}
See
MITRE, CWE-397 - Declaration of Throws for Generic Exception
CERT, ERR07-J. - Do not throw RuntimeException, Exception, or Throwable
The underlying implementation of String::replaceAll calls the java.util.regex.Pattern.compile() method each time it is
called even if the first argument is not a regular expression. This has a significant performance cost and therefore should be used with care.
When String::replaceAll is used, the first argument should be a real regular expression. If it’s not the case,
String::replace does exactly the same thing as String::replaceAll without the performance drawback of the regex.
This rule raises an issue for each String::replaceAll used with a String as first parameter which doesn’t contains
special regex character or pattern.
Noncompliant Code Example
String init = "Bob is a Bird... Bob is a Plane... Bob is Superman!";
String changed = init.replaceAll("Bob is", "It's"); // Noncompliant
changed = changed.replaceAll("\\.\\.\\.", ";"); // Noncompliant
Compliant Solution
String init = "Bob is a Bird... Bob is a Plane... Bob is Superman!";
String changed = init.replace("Bob is", "It's");
changed = changed.replace("...", ";");
Or, with a regex:
String init = "Bob is a Bird... Bob is a Plane... Bob is Superman!";
String changed = init.replaceAll("\\w*\\sis", "It's");
changed = changed.replaceAll("\\.{3}", ";");
See
{rule:java:S4248} - Regex patterns should not be created needlessly
The Java regex engine uses recursive method calls to implement backtracking. Therefore when a repetition inside a regular expression contains
multiple paths (i.e. the body of the repetition contains an alternation (|), an optional element or another repetition), trying to match
the regular expression can cause a stack overflow on large inputs. This does not happen when using a possessive quantifier (such as *+
instead of *) or when using a character class inside a repetition (e.g. [ab]* instead of (a|b)*).
The size of the input required to overflow the stack depends on various factors, including of course the stack size of the JVM. One thing that
significantly increases the size of the input that can be processed is if each iteration of the repetition goes through a chain of multiple constant
characters because such consecutive characters will be matched by the regex engine without invoking any recursion.
For example, on a JVM with a stack size of 1MB, the regex (?:a|b)* will overflow the stack after matching around 6000 characters
(actual numbers may differ between JVM versions and even across multiple runs on the same JVM) whereas (?:abc|def)* can handle around
15000 characters.
Since often times stack growth can't easily be avoided, this rule will only report issues on regular expressions if they can cause a stack overflow
on realistically sized inputs. You can adjust the maxStackConsumptionFactor parameter to adjust this.
Pattern.compile("[ab]*"); // Character classes don't cause recursion the way that '|' does
Pattern.compile("(?s).*"); // Enabling the (?s) flag makes '.' match line breaks, so '|\n' isn't necessary
Pattern.compile("(ab?)*+"); // Possessive quantifiers don't cause recursion because they disable backtracking
Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents
calling methods from handling true, system-generated exceptions differently than application-generated errors.
Noncompliant Code Example
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
Compliant Solution
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because overriding method has to follow signature of the throw declaration
in the superclass. The issue will be raised on superclass declaration of the method (or won't be raised at all if superclass is not part of the
analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod throws Exception {
doTheThing(); // this method throws Exception
}
See
MITRE, CWE-397 - Declaration of Throws for Generic Exception
CERT, ERR07-J. - Do not throw RuntimeException, Exception, or Throwable
Abstract classes should not have public constructors. Constructors of abstract classes can only be called in constructors of their subclasses. So
there is no point in making them public. The protected modifier should be enough.
Noncompliant Code Example
public abstract class AbstractClass1 {
public AbstractClass1 () { // Noncompliant, has public modifier
// do something here
}
}
Compliant Solution
public abstract class AbstractClass2 {
protected AbstractClass2 () {
// do something here
}
}
Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents
calling methods from handling true, system-generated exceptions differently than application-generated errors.
Noncompliant Code Example
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
Compliant Solution
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because overriding method has to follow signature of the throw declaration
in the superclass. The issue will be raised on superclass declaration of the method (or won't be raised at all if superclass is not part of the
analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod throws Exception {
doTheThing(); // this method throws Exception
}
See
MITRE, CWE-397 - Declaration of Throws for Generic Exception
CERT, ERR07-J. - Do not throw RuntimeException, Exception, or Throwable
Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents
calling methods from handling true, system-generated exceptions differently than application-generated errors.
Noncompliant Code Example
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
Compliant Solution
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because overriding method has to follow signature of the throw declaration
in the superclass. The issue will be raised on superclass declaration of the method (or won't be raised at all if superclass is not part of the
analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod throws Exception {
doTheThing(); // this method throws Exception
}
See
MITRE, CWE-397 - Declaration of Throws for Generic Exception
CERT, ERR07-J. - Do not throw RuntimeException, Exception, or Throwable
Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents
calling methods from handling true, system-generated exceptions differently than application-generated errors.
Noncompliant Code Example
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
Compliant Solution
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because overriding method has to follow signature of the throw declaration
in the superclass. The issue will be raised on superclass declaration of the method (or won't be raised at all if superclass is not part of the
analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod throws Exception {
doTheThing(); // this method throws Exception
}
See
MITRE, CWE-397 - Declaration of Throws for Generic Exception
CERT, ERR07-J. - Do not throw RuntimeException, Exception, or Throwable
Using such generic exceptions as Error, RuntimeException, Throwable, and Exception prevents
calling methods from handling true, system-generated exceptions differently than application-generated errors.
Noncompliant Code Example
public void foo(String bar) throws Throwable { // Noncompliant
throw new RuntimeException("My Message"); // Noncompliant
}
Compliant Solution
public void foo(String bar) {
throw new MyOwnRuntimeException("My Message");
}
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because overriding method has to follow signature of the throw declaration
in the superclass. The issue will be raised on superclass declaration of the method (or won't be raised at all if superclass is not part of the
analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod throws Exception {
doTheThing(); // this method throws Exception
}
See
MITRE, CWE-397 - Declaration of Throws for Generic Exception
CERT, ERR07-J. - Do not throw RuntimeException, Exception, or Throwable
Abstract classes should not have public constructors. Constructors of abstract classes can only be called in constructors of their subclasses. So
there is no point in making them public. The protected modifier should be enough.
Noncompliant Code Example
public abstract class AbstractClass1 {
public AbstractClass1 () { // Noncompliant, has public modifier
// do something here
}
}
Compliant Solution
public abstract class AbstractClass2 {
protected AbstractClass2 () {
// do something here
}
}