diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S106.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S106.html index 6a3e8f1db39..9db35e9790d 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S106.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S106.html @@ -1,30 +1,35 @@
When logging a message, the following requirements should be fulfilled:
+In software development, logs serve as a record of events within an application, providing crucial insights for debugging. When logging, it is +essential to ensure that the logs are:
Simply printing messages to System.out
or System.err
does not fulfill these needs. A dedicated logger should be used
-instead.
Those requirements are not met if a program directly writes to the standard outputs (e.g., System.out, System.err). That is why defining and using +a dedicated logger is highly recommended.
+The following noncompliant code:
-class PrintMessage { - public void print() { +class MyClass { + public void doSomething() { System.out.println("My Message"); // Noncompliant, output directly to System.out without a logger } }-
Could be replaced by:
import java.util.logging.Logger; -class PrintMessage { +class MyClass { Logger logger = Logger.getLogger(getClass().getName()); - public void print() { + public void doSomething() { + // ... logger.info("My Message"); // Compliant, output via logger + // ... } }diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.html index 66cbe52247b..ae2343b2064 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.html @@ -1,16 +1,36 @@
Merging collapsible if
statements increases the code’s readability.
Nested code - blocks of code inside blocks of code - is eventually necessary, but increases complexity. This is why keeping the code as flat as +possible, by avoiding unnecessary nesting, is considered a good practice.
+Merging if
statements when possible will decrease the nesting of the code and improve its readability.
Code like
++if (condition1) { + if (condition2) { // Noncompliant + /* ... */ + } +} ++
Will be more readable as
++if (condition1 && condition2) { // Compliant + /* ... */ +} ++
If merging the conditions seems to result in a more complex code, extracting the condition or part of it in a named function or variable is a +better approach to fix readability.
+if (file != null) { - if (file.isFile() || file.isDirectory()) { + if (file.isFile() || file.isDirectory()) { // Noncompliant /* ... */ } }-
-if (file != null && isFileOrDirectory(file)) { +if (file != null && isFileOrDirectory(file)) { // Compliant /* ... */ } diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.json b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.json index c3c1ca9b08c..b7f8fc91b8c 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.json +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1066.json @@ -1,5 +1,5 @@ { - "title": "Collapsible \"if\" statements should be merged", + "title": "Mergeable \"if\" statements should be combined", "type": "CODE_SMELL", "code": { "impacts": { diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1075.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1075.html index 1f07840f0fe..bfa52b4f018 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1075.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1075.html @@ -1,12 +1,19 @@Why is this an issue?
-Hard coding a URI makes it difficult to test a program: path literals are not always portable across operating systems, a given absolute path may -not exist on a specific test environment, a specified Internet URL may not be available when executing the tests, production environment filesystems -usually differ from the development environment, …etc. For all those reasons, a URI should never be hard coded. Instead, it should be replaced by -customizable parameter.
-Further even if the elements of a URI are obtained dynamically, portability can still be limited if the path-delimiters are hard-coded.
-This rule raises an issue when URI’s or path delimiters are hard coded.
-Noncompliant code example
-+Hard-coding a URI makes it difficult to test a program for a variety of reasons:
+
In addition, hard-coded URIs can contain sensitive information, like IP addresses, and they should not be stored in the code.
+For all those reasons, a URI should never be hard coded. Instead, it should be replaced by a customizable parameter.
+Further, even if the elements of a URI are obtained dynamically, portability can still be limited if the path delimiters are hard-coded.
+This rule raises an issue when URIs or path delimiters are hard-coded.
+public class Foo { public Collection<User> listUsers() { File userList = new File("/home/mylogin/Dev/users.txt"); // Noncompliant @@ -15,8 +22,8 @@-Noncompliant code example
} }
+Compliant solution
+public class Foo { // Configuration is a class that returns customizable properties: it can be mocked to be injected during tests. private Configuration config; @@ -33,8 +40,4 @@-Compliant solution
} }Resources
-
Magic numbers make the code more complex to understand as it requires the reader to have knowledge about the global context to understand the -number itself. Their usage may seem obvious at the moment you’re writing the code, but it may not be the case for another developer or later once the -context faded away. -1, 0 and 1 are not considered magic numbers.
+number itself. Their usage may seem obvious when writing the code, but it may not be the case for another developer or later once the context faded +away. -1, 0, and 1 are not considered magic numbers.This rule ignores hashCode
methods.
The use of parentheses, even those not required to enforce a desired order of operations, can clarify the intent behind a piece of code. But -redundant pairs of parentheses could be misleading, and should be removed.
-Parentheses can disambiguate the order of operations in complex expressions and make the code easier to understand.
-int x = (y / 2 + 1); //Compliant even if the parenthesis are ignored by the compiler +a = (b * c) + (d * e); // Compliant: the intent is clear. ++
Redundant parentheses are parenthesis that do not change the behavior of the code, and do not clarify the intent. They can mislead and complexify +the code. They should be removed.
++int x = ((y / 2 + 1)); // Noncompliant -if (a && ((x+y > 0))) { // Noncompliant - //... +if (a && ((x + y > 0))) { // Noncompliant + return ((x + 1)); // Noncompliant } - -return ((x + 1)); // Noncompliant
+int x = (y / 2 + 1); -if (a && (x+y > 0)) { - //... +if (a && (x + y > 0)) { + return (x + 1); } - -return (x + 1);diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1116.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1116.html index f98f80a5496..e9bedc56c37 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1116.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1116.html @@ -1,32 +1,32 @@Why is this an issue?
-Empty statements, i.e.
-;
, are usually introduced by mistake, for example because:
;;
. +Empty statements represented by a semicolon
+;
are statements that do not perform any operation. They are often the result of a typo or +a misunderstanding of the language syntax. It is a good practice to remove empty statements since they don’t add value and lead to confusion and +errors.Code examples
+Noncompliant code example
+void doSomething() { - ; // Noncompliant - was used as a kind of TODO marker + ; // Noncompliant - was used as a kind of TODO marker } void doSomethingElse() { - System.out.println("Hello, world!");; // Noncompliant - double ; - ... + System.out.println("Hello, world!");; // Noncompliant - double ; + // ... }-Compliant solution
-+Compliant solution
+void doSomething() {} void doSomethingElse() { System.out.println("Hello, world!"); - ... - for (int i = 0; i < 3; i++) ; // compliant if unique statement of a loop - ... + // ... + for (int i = 0; i < 3; i++) ; // Compliant if unique statement of a loop + // ... }Resources
+Documentation
Overriding or shadowing a variable declared in an outer scope can strongly impact the readability, and therefore the maintainability, of a piece of -code. Further, it could lead maintainers to introduce bugs because they think they’re using one variable but are really using another.
+Shadowing occurs when a local variable has the same name as a variable or a field in an outer scope.
+This can lead to three main problems:
+To avoid these problems, rename the shadowing, shadowed, or both identifiers to accurately represent their purpose with unique and meaningful +names.
+This rule focuses on variables in methods that shadow a field.
+class Foo { public int myField; public void doSomething() { int myField = 0; // Noncompliant - ... + // ... } }
Utility classes, which are collections of static
members, are not meant to be instantiated. Even abstract utility classes, which can
-be extended, should not have public constructors.
Java adds an implicit public constructor to every class which does not define at least one explicitly. Hence, at least one non-public constructor -should be defined.
-Whenever there are portions of code that are duplicated and do not depend on the state of their container class, they can be centralized inside a +"utility class". A utility class is a class that only has static members, hence it should not be instantiated.
+When a class contains public static void main(String[] args)
method it is not considered as a utility class and will be ignored by
+this rule.
To prevent the class from being instantiated, you should define a non-public constructor. This will prevent the compiler from implicitly generating +a public parameterless constructor.
+class StringUtils { // Noncompliant @@ -13,7 +18,7 @@-Noncompliant code example
}
class StringUtils { // Compliant @@ -27,7 +32,4 @@-Compliant solution
}
When class contains public static void main(String[] args)
method it is not considered as utility class and will be ignored by this
-rule.
This rule raises an issue when a generic exception (such as Error
, RuntimeException
, Throwable
, or
+Exception
) is thrown.
Using such generic exceptions as Error
, RuntimeException
, Throwable
, and Exception
prevents
-calling methods from handling true, system-generated exceptions differently than application-generated errors.
-public void foo(String bar) throws Throwable { // Noncompliant - throw new RuntimeException("My Message"); // Noncompliant -} --
-public void foo(String bar) { - throw new MyOwnRuntimeException("My Message"); -} -+
Throwing generic exceptions such as Error
, RuntimeException
, Throwable
, and Exception
will have
+a negative impact on any code trying to catch these exceptions.
From a consumer perspective, it is generally a best practice to only catch exceptions you intend to handle. Other exceptions should ideally be let +to propagate up the stack trace so that they can be dealt with appropriately. When a generic exception is thrown, it forces consumers to catch +exceptions they do not intend to handle, which they then have to re-throw.
+Besides, when working with a generic type of exception, the only way to distinguish between multiple exceptions is to check their message, which is +error-prone and difficult to maintain. Legitimate exceptions may be unintentionally silenced and errors may be hidden.
+For instance, when a Throwable
is caught and not re-thrown, it may mask errors such as OutOfMemoryError
and prevent the
+program from terminating gracefully.
When throwing an exception, it is therefore recommended to throw the most specific exception possible so that it can be handled intentionally by +consumers.
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).
+Generic exceptions in the signatures of overriding methods are ignored, because an overriding method has to follow the 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 { +public void myOtherMethod() throws Exception { doTheThing(); // this method throws Exception }+
To fix this issue, make sure to throw specific exceptions that are relevant to the context in which they arise. It is recommended to either:
+IllegalArgumentException
should be
+ thrown when a method receives an invalid argument. Exception
or one of its subclasses. +void checkValue(int value) throws Throwable { // Noncompliant: signature is too broad + if (value == 42) { + throw new RuntimeException("Value is 42"); // Noncompliant: This will be difficult for consumers to handle + } +} ++
+void checkValue(int value) { + if (value == 42) { + throw new IllegalArgumentException("Value is 42"); // Compliant + } +} +
Assignments within sub-expressions are hard to spot and therefore make the code less readable. Ideally, sub-expressions should not have -side-effects.
--if ((str = cont.substring(pos1, pos2)).isEmpty()) { // Noncompliant - //... --
-str = cont.substring(pos1, pos2); -if (str.isEmpty()) { - //... -+
A common code smell that can hinder the clarity of source code is making assignments within sub-expressions. This practice involves assigning a +value to a variable inside a larger expression, such as within a loop or a conditional statement.
+This practice essentially gives a side-effect to a larger expression, thus making it less readable. This often leads to confusion and potential +errors.
Assignments in while
statement conditions, and assignments enclosed in relational expressions are ignored.
This rule ignores assignments in conditions of while
statements and assignments enclosed in relational expressions.
-BufferedReader br = new BufferedReader(/* ... */); -String line; -while ((line = br.readLine()) != null) {...} -if ((i = j) >= 1) {...} +void processInput(BufferedReader br) { + String line; + while ((line = br.readLine()) != null) { + processLine(line); + } +} + +Object foo; +if ((foo = bar()) != null) { + // do something with "foo" +}-
Chained assignments, including compound assignments, are ignored.
+This rule also ignores chained assignments, including compound assignments.
-int i = j = 0; +int j, i = j = 0; int k = (j += 1); +byte[] result, bresult; result = (bresult = new byte[len]);+
Making assignments within sub-expressions can hinder the clarity of source code.
+This practice essentially gives a side-effect to a larger expression, thus making it less readable. This often leads to confusion and potential +errors.
+Extracting assignments into separate statements is encouraged to keep the code clear and straightforward.
++String str; +if (!(str = cont.substring(pos1, pos2)).isEmpty()) { // Noncompliant + // do something with "str" +} ++
+String str = cont.substring(pos1, pos2); +if (!str.isEmpty()) { + // do something with "str" +} +
Redundant Boolean literals should be removed from expressions to improve readability.
-+A boolean literal can be represented in two different ways:
+true
orfalse
. They can be combined with logical operators +(!, &&, ||, ==, !=
) to produce logical expressions that represent truth values. However, comparing a boolean literal to a +variable or expression that evaluates to a boolean value is unnecessary and can make the code harder to read and understand. The more complex a +boolean expression is, the harder it will be for developers to understand its meaning and expected behavior, and it will favour the introduction of +new bugs.How to tix it
+Remove redundant boolean literals from expressions to improve readability and make the code more maintainable.
+Code examples
+Noncompliant code example
+if (booleanMethod() == true) { /* ... */ } if (booleanMethod() == false) { /* ... */ } if (booleanMethod() || false) { /* ... */ } @@ -14,8 +21,8 @@-Noncompliant code example
booleanVariable = booleanMethod() ? exp : true; booleanVariable = booleanMethod() ? exp : false;Compliant solution
-+Compliant solution
+if (booleanMethod()) { /* ... */ } if (!booleanMethod()) { /* ... */ } if (booleanMethod()) { /* ... */ } diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.html index f43a958cd18..0f57c82054b 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.html @@ -1,17 +1,26 @@Why is this an issue?
-Using
-Collection.size()
to test for emptiness works, but usingCollection.isEmpty()
makes the code more readable and can -be more performant. The time complexity of anyisEmpty()
method implementation should beO(1)
whereas some implementations -ofsize()
can beO(n)
.Noncompliant code example
--if (myCollection.size() == 0) { // Noncompliant - /* ... */ +When you call
+isEmpty()
, it clearly communicates the code’s intention, which is to check if the collection is empty. Using +size() == 0
for this purpose is less direct and makes the code slightly more complex.Moreover, depending on the implementation, the
+size()
method can have a time complexity ofO(n)
wheren
is +the number of elements in the collection. On the other hand,isEmpty()
simply checks if there is at least one element in the collection, +which is a constant time operation,O(1)
.+public class MyClass { + public void doSomething(Collection<String> myCollection) { + if (myCollection.size() == 0) { // Noncompliant + doSomethingElse(); + } + } }-Compliant solution
--if (myCollection.isEmpty()) { - /* ... */ +Prefer using
+isEmpty()
to test for emptiness oversize()
.+public class MyClass { + public void doSomething(Collection<String> myCollection) { + if (myCollection.isEmpty()) { + doSomethingElse(); + } + } }diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.json b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.json index d0578f80372..8a96ab05033 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.json +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1155.json @@ -1,5 +1,5 @@ { - "title": "Collection.isEmpty() should be used to test for emptiness", + "title": "\"Collection.isEmpty()\" should be used to test for emptiness", "type": "CODE_SMELL", "code": { "impacts": { diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S117.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S117.html index b67712986e4..4669d0ef28b 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S117.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S117.html @@ -1,21 +1,26 @@ +Local variables and method parameters should be named consistently to communicate intent and improve maintainability. Rename your local variable or +method parameter to follow your project’s naming convention to address this issue.
Why is this an issue?
-Shared naming conventions allow teams to collaborate effectively. This rule raises an issue when a local variable or function parameter name does -not match the provided regular expression.
-Noncompliant code example
-With the default regular expression
-^[a-z][a-zA-Z0-9]*$
:-public void doSomething(int my_param) { - int LOCAL; - ... -} --Compliant solution
--public void doSomething(int myParam) { - int local; - ... -} -+A naming convention in software development is a set of guidelines for naming code elements like variables, functions, and classes.
+
Local +variables and method parameters hold the meaning of the written code. Their names should be meaningful and follow a consistent and easily recognizable +pattern.
Adhering to a consistent naming convention helps to make the code more readable and understandable, which makes it easier to maintain and +debug. It also ensures consistency in the code, especially when multiple developers are working on the same project.This rule checks that local variable and method parameter names match a provided regular expression.
+What is the potential impact?
+Inconsistent naming of local variables and method parameters can lead to several issues in your code:
+
In summary, not adhering to a naming convention for local variables and method parameters can lead to confusion, errors, and inefficiencies, making +the code harder to read, understand, and maintain.
Loop counters are ignored by this rule.
@@ -30,4 +35,50 @@+Exceptions
} catch (Exception e) { // Compliant }
First, familiarize yourself with the particular naming convention of the project in question. Then, update the name to match the convention, as +well as all usages of the name. For many IDEs, you can use built-in renaming and refactoring features to update all usages at once.
+With the default regular expression ^[a-z][a-zA-Z0-9]*$
:
+public class MyClass { + public void doSomething(int myParam) { + int LOCAL; // Noncompliant + // ... + } +} ++
+public class MyClass { + public void doSomething(int my_param) { + int local; + // ... + } +} ++
A good API documentation is a key factor in the usability and success of a software API. It ensures that developers can effectively use, maintain, +and collaborate on the API.
Try to imagine using the standard Java API (Collections, JDBC, IO, …) without Javadoc. It would be a nightmare, because Javadoc is the only way to -understand of the contract of the API. Documenting an API with Javadoc increases the productivity of the developers consuming it.
-On top of a main description for each member of a public API, the following Javadoc elements are required to be described:
+Undocumented APIs pose significant challenges in software development for several reasons:
+It is recommended to document the API using JavaDoc to clarify what is the contract of the API. This is especially important for +public APIs, as they are used by other developers.
+The following public methods and constructors are not taken into account by this rule:
+@Override
). On top of a main description for each member of a public API, the following Javadoc elements are required to be described:
@param parameterName
. @throws exceptionName
. @return
. @param <T>
. Furthermore the following guidelines should be followed:
+Furthermore, the following guidelines should be followed:
@param
, and names should match. @throws
@return
present and documented when not void
. "TODO"
, "FIXME"
, "..."
should be avoided. The following public methods and constructors are not taken into account by this rule:
-@Override
). @throws
@return
present and documented when method return type is not void
. "TODO"
, "FIXME"
, "…"
should be avoided. For the parameters of the rule, the following rules are applied:
java.internal.*
will match any member of java.internal
package. java.internal.**
same as above, but including sub-packages. +Code examples
+Noncompliant code example
+/** * This is a Javadoc comment */ -public class MyClass<T> implements Runnable { // Noncompliant - missing '@param <T>' +public class MyClass<T> implements Runnable { // Noncompliant - missing '@param <T>' - public static final DEFAULT_STATUS = 0; // Compliant - static constant + public static final int DEFAULT_STATUS = 0; // Compliant - static constant private int status; // Compliant - not public - public String message; // Noncompliant + public String message; // Noncompliant - public MyClass() { // Noncompliant - missing documentation + public MyClass() { // Noncompliant - missing documentation this.status = DEFAULT_STATUS; } - public void setStatus(int status) { // Compliant - setter + public void setStatus(int status) { // Compliant - setter this.status = status; } @Override - public void run() { // Compliant - has @Override annotation + public void run() { // Compliant - has @Override annotation } - protected void doSomething() { // Compliant - not public + protected void doSomething() { // Compliant - not public } - public void doSomething2(int value) { // Noncompliant + public void doSomething2(int value) { // Noncompliant } - public int doSomething3(int value) { // Noncompliant + public int doSomething3(int value) { // Noncompliant return value; } }-Compliant solution
-+Compliant solution
+/** * This is a Javadoc comment * @param <T> the parameter of the class */ public class MyClass<T> implements Runnable { - public static final DEFAULT_STATUS = 0; + public static final int DEFAULT_STATUS = 0; private int status; /** @@ -109,6 +126,7 @@+Compliant solution
* @param value the value to be used */ public void doSomething(int value) { + } /** * {@inheritDoc} @@ -118,4 +136,16 @@Compliant solution
} }Resources
+Documentation
+
There are several reasons for a method not to have a method body:
+An empty method is generally considered bad practice and can lead to confusion, readability, and maintenance issues. Empty methods bring no +functionality and are misleading to others as they might think the method implementation fulfills a specific and identified requirement.
+There are several reasons for a method not to have a body:
UnsupportedOperationException
should be thrown. -public void doSomething() { -} - -public void doSomethingElse() { -} --
-@Override -public void doSomething() { - // Do nothing because of X and Y. -} - -@Override -public void doSomethingElse() { - throw new UnsupportedOperationException(); -} -
This does not raise an issue in the following cases:
+public void shouldNotBeEmpty() { // Noncompliant - method is empty +} + +public void notImplemented() { // Noncompliant - method is empty +} + +@Override +public void emptyOnPurpose() { // Noncompliant - method is empty +} ++
+public void doSomething() { + doSomething(); +} + +public void notImplemented() { + throw new UnsupportedOperationException("notImplemented() cannot be performed because ..."); +} + +@Override +public void emptyOnPurpose() { + // comment explaining why the method is empty +} +diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S120.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S120.html index c5aeef2108d..f72684c762a 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S120.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S120.html @@ -1,12 +1,16 @@
Shared coding conventions allow teams to collaborate efficiently. This rule checks that all package names match a provided regular expression.
-Shared naming conventions improve readability and allow teams to collaborate efficiently. This rule checks that all package names match a provided +regular expression.
+Rename packages with the expected naming convention
+With the default regular expression ^[a-z_]+(\.[a-z_][a-z0-9_]*)*$
:
+package org.exAmple; // Noncompliant-Compliant solution
-+Compliant solution
+package org.example;diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S125.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S125.html index 86475f084cb..0d83de02ce7 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S125.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S125.html @@ -1,4 +1,5 @@Why is this an issue?
-Programmers should not comment out code as it bloats programs and reduces readability.
-Unused code should be deleted and can be retrieved from source control history if required.
+Commented-out code distracts the focus from the actual executed code. It creates a noise that increases maintenance code. And because it is never +executed, it quickly becomes out of date and invalid.
+Commented-out code should be deleted and can be retrieved from source control history if required.
diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1481.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1481.html index 992330e5ba0..080e96453ce 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1481.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1481.html @@ -1,15 +1,36 @@Why is this an issue?
-If a local variable is declared but not used, it is dead code and should be removed. Doing so will improve maintainability because developers will -not wonder what the variable is used for.
-Noncompliant code example
-+An unused local variable is a variable that has been declared but is not used anywhere in the block of code where it is defined. It is dead code, +contributing to unnecessary complexity and leading to confusion when reading the code. Therefore, it should be removed from your code to maintain +clarity and efficiency.
+What is the potential impact?
+Having unused local variables in your code can lead to several issues:
+
In summary, unused local variables can make your code less readable, more confusing, and harder to maintain, and they can potentially lead to bugs +or inefficient memory use. Therefore, it is best to remove them.
+The fix for this issue is straightforward. Once you ensure the unused variable is not part of an incomplete implementation leading to bugs, you +just need to remove it.
+public int numberOfMinutes(int hours) { - int seconds = 0; // seconds is never used + int seconds = 0; // Noncompliant - seconds is unused return hours * 60; }-
++Compliant solution
+public int numberOfMinutes(int hours) { return hours * 60; } diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1488.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1488.html index caf1f8de54a..f1bceb76327 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1488.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1488.html @@ -1,26 +1,34 @@Why is this an issue?
-Declaring a variable only to immediately return or throw it is a bad practice.
-Some developers argue that the practice improves code readability, because it enables them to explicitly name what is being returned. However, this -variable is an internal implementation detail that is not exposed to the callers of the method. The method name should be sufficient for callers to -know exactly what will be returned.
-Noncompliant code example
-+Declaring a variable only to immediately return or throw it is considered a bad practice because it adds unnecessary complexity to the code. This +practice can make the code harder to read and understand, as it introduces an extra step that doesn’t add any value. Instead of declaring a variable +and then immediately returning or throwing it, it is generally better to return or throw the value directly. This makes the code cleaner, simpler, and +easier to understand.
+How to fix it
+Declaring a variable only to immediately return or throw it is considered a bad practice because it adds unnecessary complexity to the code. To fix +the issue, return or throw the value directly.
+Code examples
+Noncompliant code example
+public long computeDurationInMilliseconds() { - long duration = (((hours * 60) + minutes) * 60 + seconds ) * 1000 ; + long duration = (((hours * 60) + minutes) * 60 + seconds) * 1000; return duration; } - ++Compliant solution
++public long computeDurationInMilliseconds() { + return (((hours * 60) + minutes) * 60 + seconds) * 1000; +} ++Noncompliant code example
+public void doSomething() { RuntimeException myException = new RuntimeException(); throw myException; }-Compliant solution
--public long computeDurationInMilliseconds() { - return (((hours * 60) + minutes) * 60 + seconds ) * 1000 ; -} - +Compliant solution
+public void doSomething() { throw new RuntimeException(); } diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1774.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1774.html index 341e8c3f42a..5d892f1ca5b 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1774.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1774.html @@ -1,11 +1,13 @@Why is this an issue?
-While the ternary operator is pleasingly compact, its use can make code more difficult to read. It should therefore be avoided in favor of the more -verbose
-if
/else
structure.Noncompliant code example
+Ternary expressions, while concise, can often lead to code that is difficult to read and understand, especially when they are nested or complex. +Prioritizing readability fosters maintainability and reduces the likelihood of bugs. Therefore, they should be removed in favor of more explicit +control structures, such as
+if
/else
statements, to improve the clarity and readability of the code.Code examples
+Noncompliant code example
-System.out.println(i>10?"yes":"no"); +System.out.println(i>10?"yes":"no"); // Noncompliant-Compliant solution
+Compliant solution
if (i > 10) { System.out.println("yes"); diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1854.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1854.html index c4f96d3e1de..2b6c94f0c7d 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1854.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S1854.html @@ -1,23 +1,41 @@Why is this an issue?
-A dead store happens when a local variable is assigned a value that is not read by any subsequent instruction. Calculating or retrieving a value -only to then overwrite it or throw it away, could indicate a serious error in the code. Even if it’s not an error, it is at best a waste of resources. -Therefore all calculated values should be used.
-Noncompliant code example
--i = a + b; // Noncompliant; calculation result not used before value is overwritten -i = compute(); +Dead stores refer to assignments made to local variables that are subsequently never used or immediately overwritten. Such assignments are +unnecessary and don’t contribute to the functionality or clarity of the code. They may even negatively impact performance. Removing them enhances code +cleanliness and readability. Even if the unnecessary operations do not do any harm in terms of the program’s correctness, they are - at best - a waste +of computing resources.
+Exceptions
+This rule ignores initializations to
+-1
,0
,1
,null
,true
,false
and +""
.How to fix it
+Remove the unnecesarry assignment, then test the code to make sure that the right-hand side of a given assignment had no side effects (e.g. a +method that writes certain data to a file and returns the number of written bytes).
+Code examples
+Noncompliant code example
++int foo(int y) { + int x = 100; // Noncompliant: dead store + x = 150; // Noncompliant: dead store + x = 200; + return x + y; +}-Compliant solution
--i = a + b; -i += compute(); +Compliant solution
++int foo(int y) { + int x = 200; // Compliant: no unnecessary assignment + return x + y; +}-Exceptions
-This rule ignores initializations to -1, 0, 1,
null
,true
,false
and""
.Resources
+Standards
+
Blindly importing all the classes in a package clutters the class namespace and could lead to conflicts between classes in different packages with -the same name. On the other hand, specifically listing the necessary classes avoids that problem and makes clear which versions were wanted.
-Using wildcards in imports may look cleaner as it reduces the number of lines in the import section and simplifies the code.
On the other hand,
+it makes the code harder to maintain:
That is why it is better to import only the specific classes or modules you need.
+Static imports are ignored by this rule. For example:
+import static java.lang.Math.*; ++
will not raise an issue;
+Depending on your IDE you can solve this issue almost automatically:
Look for Organize/Optimize imports
+actions. These actions can also often be applied automatically on save.
Note: To make this work properly, you must adjust IDE settings to
+use a very high allowed class count usage
before using wildcards.
Resolving this issue manually will require a step-by-step approach:
+import java.sql.*; // Noncompliant import java.util.*; // Noncompliant private Date date; // Date class exists in java.sql and java.util. Which one is this?-
+Compliant solution
+import java.sql.Date; import java.util.List; import java.util.ArrayList; private Date date;-Exceptions
-Static imports are ignored by this rule. E.G.
--import static java.lang.Math.*; -diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2230.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2230.html index 7436f978c3b..7e9a6abe8a8 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2230.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2230.html @@ -1,33 +1,39 @@Why is this an issue?
-Marking a non-
-public
method@Transactional
is both useless and misleading because Spring does not recognize -non-public
methods, and so makes no provision for their proper invocation. Nor does Spring make provision for the methods invoked by the -method it called.Therefore marking a
+private
method, for instance,@Transactional
can only result in a runtime error or exception if the -method is annotated as@Transactional
.Marking a non-public method
+@Async
or@Transactional
is misleading because Spring does not recognize non-public methods, +and so makes no provision for their proper invocation. Nor does Spring make provision for the methods invoked by the method it called.Therefore marking a private method, for instance, @Transactional can only result in a runtime error or exception if the method is annotated as +@Transactional.
How to fix it
-Make the method public or remove the
+@Transactional
annotation.Declare the method
public
. Note that this action alone does not resolve the issue of direct instance calls from within the same class +(see rule {rule:java:S6809}), but it is a required precondition to fix it.Code examples
Noncompliant code example
-@Transactional // Noncompliant -void doTheThing(ArgClass arg) { - // ... -} - -@Transactional // Noncompliant -private void doTheOtherThing(ArgClass arg) { - // ... +@Async +private Future<String> asyncMethodWithReturnType() { // Noncompliant, no proxy generated and + return "Hellow, world!"; // can only be invoked from same class }Compliant solution
-@Transactional -public void doTheThing(ArgClass arg) { - // ... -} - -private void doTheOtherThing(ArgClass arg) { - // ... +@Async +public Future<String> asyncMethodWithReturnType() { // Compliant + return "Hellow, world!"; }+Resources
+Documentation
+
Gratuitous boolean expressions are conditions that do not change the evaluation of a program. This issue can indicate logical errors and affect the +correctness of an application, as well as its maintainability.
If a boolean expression doesn’t change the evaluation of the condition, then it is entirely unnecessary, and can be removed. If it is gratuitous -because it does not match the programmer’s intent, then it’s a bug and the expression should be fixed.
--a = true; -if (a) { // Noncompliant - doSomething(); -} +Control flow constructs like
+if
-statements allow the programmer to direct the flow of a program depending on a boolean expression. +However, if the condition is always true or always false, only one of the branches will ever be executed. In that case, the control flow construct and +the condition no longer serve a purpose; they become gratuitous.What is the potential impact?
+The presence of gratuitous conditions can indicate a logical error. For example, the programmer intended to have the program branch into +different paths but made a mistake when formulating the branching condition. In this case, this issue might result in a bug and thus affect the +reliability of the application. For instance, it might lead to the computation of incorrect results.
+Additionally, gratuitous conditions and control flow constructs introduce unnecessary complexity. The source code becomes harder to understand, and +thus, the application becomes more difficult to maintain.
+How to fix it
+Gratuitous boolean expressions are suspicious and should be carefully removed from the code.
+First, the boolean expression in question should be closely inspected for logical errors. If a mistake was made, it can be corrected so the +condition is no longer gratuitous.
+If it becomes apparent that the condition is actually unnecessary, it can be removed. The associated control flow construct (e.g., the +
+if
-statement containing the condition) will be adapted or even removed, leaving only the necessary branches.Code examples
+Noncompliant code example
++public class MyClass { + public void doThings(boolean b, boolean c) { + a = true; + if (a) { // Noncompliant + doSomething(); + } -if (b && a) { // Noncompliant; "a" is always "true" - doSomething(); -} + if (b && a) { // Noncompliant; "a" is always "true" + doSomething(); + } -if (c || !a) { // Noncompliant; "!a" is always "false" - doSomething(); -} + if (c || !a) { // Noncompliant; "!a" is always "false" + doSomething(); + } -if (c || (!c && b)) { // Noncompliant; c || (!c && b) is equal to c || b - doSomething(); + if (c || (!c && b)) { // Noncompliant; c || (!c && b) is equal to c || b + doSomething(); + } + } }-Compliant solution
--a = true; -if (foo(a)) { - doSomething(); -} +Compliant solution
++public class MyClass { + public void doThings(boolean b, boolean c) { + a = true; + if (foo(a)) { + doSomething(); + } -if (b) { - doSomething(); -} + if (b) { + doSomething(); + } -if (c) { - doSomething(); -} + if (c) { + doSomething(); + } -if (c || b) { - doSomething(); + if (c || b) { + doSomething(); + } + } }Resources
diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2612.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2612.html index a4ec70420e7..e6f33c4f3fc 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2612.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S2612.html @@ -73,6 +73,5 @@See
Create files with appropriate access permissions
In the interest of code clarity, static
members of a base
class should never be accessed using a derived type’s name.
-Doing so is confusing and could create the illusion that two different static members exist.
In object-oriented programming, inappropriately accessing static members of a base class via derived types is considered a code smell.
+Static members are associated with the class itself, not with any specific instance of the class or its children classes. Accessing through the +wrong type suggests a misunderstanding of the ownership and role of this member. This can make the maintenance of the code more complicated.
+Therefore, the access should be done directly through the base class to maintain clarity and avoid potential misunderstandings.
+class Parent { public static int counter; } @@ -14,7 +16,7 @@Noncompliant code example
}Compliant solution
-+class Parent { public static int counter; } diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3330.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3330.html index e8d3047ff78..010fb4a62f5 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3330.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3330.html @@ -38,7 +38,6 @@See
The standard assertions library methods such as org.junit.Assert.assertEquals
, and org.junit.Assert.assertSame
expect the
-first argument to be the expected value and the second argument to be the actual value. For AssertJ, it’s the other way around, the argument of
-org.assertj.core.api.Assertions.assertThat
is the actual value, and the subsequent calls contain the expected values. Swap them, and your
-test will still have the same outcome (succeed/fail when it should) but the error messages will be confusing.
org.assertj.core.api.Assertions.assertThat
is the actual value, and the subsequent calls contain the expected values.
+Having the expected value and the actual value in the wrong order will not alter the outcome of tests, (succeed/fail when it should) but the error +messages will contain misleading information.
This rule raises an issue when the actual argument to an assertions library method is a hard-coded value and the expected argument is not.
+You should provide the assertion methods with a hard-coded value as the expected value, while the actual value of the assertion should derive from +the portion of code that you want to test.
Supported frameworks:
-+Code examples
+Noncompliant code example
+org.junit.Assert.assertEquals(runner.exitCode(), 0, "Unexpected exit code"); // Noncompliant; Yields error message like: Expected:<-1>. Actual:<0>. org.assertj.core.api.Assertions.assertThat(0).isEqualTo(runner.exitCode()); // Noncompliant-Compliant solution
-+Compliant solution
+org.junit.Assert.assertEquals(0, runner.exitCode(), "Unexpected exit code"); org.assertj.core.api.Assertions.assertThat(runner.exitCode()).isEqualTo(0);diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3457.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3457.html index 3b6078840ae..a1c8c0847c1 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3457.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S3457.html @@ -1,68 +1,56 @@Why is this an issue?
+A
printf-
-style format string is a string that contains placeholders, usually represented by special characters such as "%s" or "{}", +depending on the technology in use. These placeholders are replaced by values when the string is printed or logged.Because
-printf
-style format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that -result in the wrong strings being created. This rule statically validates the correlation ofprintf
-style format strings to their -arguments when calling theformat(...)
methods ofjava.util.Formatter
,java.lang.String
, -java.io.PrintStream
,MessageFormat
, andjava.io.PrintWriter
classes and theprintf(...)
methods of -java.io.PrintStream
orjava.io.PrintWriter
classes.Noncompliant code example
--String.format("First {0} and then {1}", "foo", "bar"); //Noncompliant. Looks like there is a confusion with the use of {{java.text.MessageFormat}}, parameters "foo" and "bar" will be simply ignored here -String.format("Display %3$d and then %d", 1, 2, 3); //Noncompliant; the second argument '2' is unused -String.format("Too many arguments %d and %d", 1, 2, 3); //Noncompliant; the third argument '3' is unused -String.format("First Line\n"); //Noncompliant; %n should be used in place of \n to produce the platform-specific line separator -String.format("Is myObject null ? %b", myObject); //Noncompliant; when a non-boolean argument is formatted with %b, it prints true for any nonnull value, and false for null. Even if intended, this is misleading. It's better to directly inject the boolean value (myObject == null in this case) -String.format("value is " + value); // Noncompliant -String s = String.format("string without arguments"); // Noncompliant - -MessageFormat.format("Result '{0}'.", value); // Noncompliant; String contains no format specifiers. (quote are discarding format specifiers) -MessageFormat.format("Result {0}.", value, value); // Noncompliant; 2nd argument is not used -MessageFormat.format("Result {0}.", myObject.toString()); // Noncompliant; no need to call toString() on objects - -java.util.Logger logger; -logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject.toString()); // Noncompliant; no need to call toString() on objects -logger.log(java.util.logging.Level.SEVERE, "Result.", new Exception()); // compliant, parameter is an exception -logger.log(java.util.logging.Level.SEVERE, "Result '{0}'", 14); // Noncompliant - String contains no format specifiers. -logger.log(java.util.logging.Level.SEVERE, "Result " + param, exception); // Noncompliant; Lambda should be used to differ string concatenation. +result in the wrong strings being created. +This rule checks whether every format string specifier can be correctly matched with one of the additional arguments when calling the following +methods:
+
java.lang.String#format
java.util.Formatter#format
java.io.PrintStream#format
java.text.MessageFormat#format
java.io.PrintWriter#format
java.io.PrintStream#printf
java.io.PrintWriter#printf
java.lang.String#formatted
(since Java 15) org.slf4j.Logger
, java.util.logging.Logger
, org.apache.logging.log4j.Logger
.
+ A printf-
-style format string is a string that contains placeholders, which are replaced by values when the string is printed or
+logged. Mismatch in the format specifiers and the arguments provided can lead to incorrect strings being created.
To avoid issues, a developer should ensure that the provided arguments match format specifiers.
++String.format("Too many arguments %d and %d", 1, 2, 3); // Noncompliant; the third argument '3' is unused +String.format("First {0} and then {1}", "foo", "bar"); //Noncompliant. It appears there is confusion with the use of "java.text.MessageFormat"; parameters "foo" and "bar" will be ignored here org.slf4j.Logger slf4jLog; -org.slf4j.Marker marker; - -slf4jLog.debug(marker, "message {}"); -slf4jLog.debug(marker, "message", 1); // Noncompliant - String contains no format specifiers. - -org.apache.logging.log4j.Logger log4jLog; -log4jLog.debug("message", 1); // Noncompliant - String contains no format specifiers. +slf4jLog.debug("The number: ", 1); // Noncompliant - String contains no format specifiers.-
+Compliant solution
++String.format("Too many arguments %d and %d", 1, 2); String.format("First %s and then %s", "foo", "bar"); -String.format("Display %2$d and then %d", 1, 3); -String.format("Too many arguments %d %d", 1, 2); -String.format("First Line%n"); -String.format("Is myObject null ? %b", myObject == null); -String.format("value is %d", value); -String s = "string without arguments"; - -MessageFormat.format("Result {0}.", value); -MessageFormat.format("Result '{0}' = {0}", value); -MessageFormat.format("Result {0}.", myObject); - -java.util.Logger logger; -logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject); -logger.log(java.util.logging.Level.SEVERE, "Result {0}'", 14); -logger.log(java.util.logging.Level.SEVERE, exception, () -> "Result " + param); org.slf4j.Logger slf4jLog; -org.slf4j.Marker marker; - -slf4jLog.debug(marker, "message {}"); -slf4jLog.debug(marker, "message {}", 1); - -org.apache.logging.log4j.Logger log4jLog; -log4jLog.debug("message {}", 1); +slf4jLog.debug("The number: {}", 1);Resources
Rejecting requests with significant content length is a good practice to control the network traffic intensity and thus resource consumption in -order to prevents DoS attacks.
+order to prevent DoS attacks.Java 9 introduced a flag for the @Deprecated
annotation, which allows to explicitly say if the deprecated code is planned to be
-removed at some point or not. This is done using forRemoval=true
as annotation parameter. The javadoc of the annotation explicitly
-mention the following:
With the introduction of Java 9, the standard annotation class java.lang.Deprecated
has been updated with new parameters. Notably, a
+boolean parameter forRemoval
has been added to clearly signify whether the deprecated code is intended to be removed in the future. This
+is indicated with forRemoval=true
. The javadoc of the annotation explicitly mentions the following:
--If true, it means that this API element is earmarked for removal in a future release.
-If false, the API element is deprecated, but there is currently no intention to remove it in a future release.
+This annotation type has a boolean-valued element
forRemoval
. A value oftrue
indicates intent to remove the annotated + program element in a future version. A value offalse
indicates that use of the annotated program element is discouraged, but at the + time the program element was annotated, there was no specific intent to remove it.
While usually deprecated classes, interfaces, and their deprecated members should be avoided rather than used, inherited or extended, those already -marked for removal are much more sensitive to causing trouble in your code soon. Consequently, any usage of such deprecated code should be avoided or -removed.
-While it is generally recommended for developers to steer clear of using deprecated classes, interfaces, and their deprecated members, those +already marked for removal will surely block you from upgrading your dependency. Usage of deprecated code should be avoided or eliminated as soon as +possible to prevent accumulation and allow a smooth upgrade of dependencies.
+The deprecated code is usually no longer maintained, can contain some bugs or vulnerabilities, and usually indicates that there is a better way to +do the same thing. Removing it can even lead to significant improvement of your software.
+Usage of deprecated classes, interfaces, and their methods explicitly marked for removal is discouraged. A developer should either migrate to +alternative methods or refactor the code to avoid the deprecated ones.
+/** * @deprecated As of release 1.3, replaced by {@link #Fee}. Will be dropped with release 1.4. diff --git a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S6288.html b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S6288.html index c661c86a8c3..ebce11313c6 100644 --- a/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S6288.html +++ b/java-checks/src/main/resources/org/sonar/l10n/java/rules/java/S6288.html @@ -41,9 +41,9 @@Compliant Solution
See
The Android Keystore system allows apps to store encryption keys in a +
The Android Keystore system allows apps to store encryption keys in a container that is protected on a system level. Additionally, it can restrict when and how the keys are used. For example, it allows the app to require user authentication (for example using a fingerprint) before the key is made available. This is the recommended way to store cryptographic keys on Android.
@@ -66,7 +66,7 @@The Android Keystore system allows apps to store encryption keys in a +
The Android Keystore system allows apps to store encryption keys in a container that is protected on a system level. Additionally, it can restrict when and how the keys are used. For example, it allows the app to require user authentication (for example using a fingerprint) before the key is made available. This is the recommended way to store cryptographic keys on Android.
@@ -82,8 +82,8 @@With regular expressions syntax, it’s possible to express the same thing in many ways. For example, to match a two-digit number, one could write
-[0-9]{2,2}
or \d{2}
. Latter is not only shorter in terms of expression length, but also easier to read and thus to maintain.
-This rule recommends to replace some bulky quantifiers and character classes with more concise equivalents:
A regular expression is a sequence of characters that specifies a match pattern in text. Among the most important concepts are:
+.
): matches all characters except line terminators (also matches them if the s
flag is set). Many of these features include shortcuts of widely used expressions, so there is more than one way to construct a regular expression to achieve the
+same results. For example, to match a two-digit number, one could write [0-9]{2,2}
or \d{2}
. The latter is not only shorter
+but easier to read and thus to maintain.
This rule recommends replacing some quantifiers and character classes with more concise equivalents:
\d
for [0-9]
and \D
for [^0-9]
\w
for [A-Za-z0-9_]
and \W
for [^A-Za-z0-9_]
x?
for x{0,1}
, x*
for x{0,}
, x+
for x{1,}
, x{N}
for
x{N,N}
-"[0-9]" // Noncompliant - same as "\\d" -"[^0-9]" // Noncompliant - same as "\\D" ++"[0-9]" // Noncompliant - same as "\\d" +"[^0-9]" // Noncompliant - same as "\\D" "[A-Za-z0-9_]" // Noncompliant - same as "\\w" -"[\\w\\W]" // Noncompliant - same as "." -"a{0,}" // Noncompliant - same as "a*" +"[\\w\\W]" // Noncompliant - same as "." +"a{0,}" // Noncompliant - same as "a*"-Compliant solution
-+Use the more concise version to make the regex expression more readable.
+"\\d" "\\D" "\\w" diff --git a/sonarpedia.json b/sonarpedia.json index 5180ac26a03..09651911a16 100644 --- a/sonarpedia.json +++ b/sonarpedia.json @@ -3,7 +3,7 @@ "languages": [ "JAVA" ], - "latest-update": "2023-10-13T09:53:32.596491Z", + "latest-update": "2023-10-20T09:15:09.502876096Z", "options": { "no-language-in-filenames": true, "preserve-filenames": false