Skip to content

Commit cbda730

Browse files
authored
Updated rules metadata (#1629)
1 parent 75c1690 commit cbda730

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+654
-330
lines changed
Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
<h2>Why is this an issue?</h2>
2-
<p>Merging collapsible <code>if</code> statements increases the code’s readability.</p>
3-
<h3>Noncompliant code example</h3>
2+
<p>Nested code - blocks of code inside blocks of code - is eventually necessary, but increases complexity. This is why keeping the code as flat as
3+
possible, by avoiding unnecessary nesting, is considered a good practice.</p>
4+
<p>Merging <code>if</code> statements when possible will decrease the nesting of the code and improve its readability.</p>
5+
<p>Code like</p>
46
<pre>
57
if condition1:
6-
if condition2:
8+
if condition2: # Noncompliant
79
# ...
810
</pre>
9-
<h3>Compliant solution</h3>
11+
<p>Will be more readable as</p>
1012
<pre>
11-
if condition1 and condition2:
13+
if condition1 and condition2: # Compliant
1214
# ...
1315
</pre>
16+
<h2>How to fix it</h2>
17+
<p>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
18+
better approach to fix readability.</p>
19+
<h3>Code examples</h3>
20+
<h4>Noncompliant code example</h4>
21+
<pre>
22+
if file.isValid():
23+
if file.isfile() or file.isdir(): # Noncompliant
24+
# ...
25+
</pre>
26+
<h4>Compliant solution</h4>
27+
<pre>
28+
def isFileOrDirectory(File file):
29+
return file.isFile() or file.isDirectory()
30+
31+
if file.isValid() and isFileOrDirectory(file): # Compliant
32+
# ...
33+
</pre>
1434

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"title": "Collapsible \"if\" statements should be merged",
2+
"title": "Mergeable \"if\" statements should be combined",
33
"type": "CODE_SMELL",
44
"code": {
55
"impacts": {

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1110.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<h2>Why is this an issue?</h2>
2-
<p>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
3-
redundant pairs of parentheses could be misleading, and should be removed.</p>
2+
<p>Parentheses can disambiguate the order of operations in complex expressions and make the code easier to understand.</p>
3+
<pre>
4+
a = (b * c) + (d * e) # Compliant: the intent is clear.
5+
</pre>
6+
<p>Redundant parentheses are parenthesis that do not change the behavior of the code, and do not clarify the intent. They can mislead and complexify
7+
the code. They should be removed.</p>
48
<h3>Noncompliant code example</h3>
59
<pre>
610
return ((3)) # Noncompliant
Lines changed: 26 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,40 @@
1+
<p>This rule raises an issue when a generic exception (such as <code>Exception</code> or <code>BaseException</code>) is raised.</p>
12
<h2>Why is this an issue?</h2>
23
<p>Raising instances of <a href="https://docs.python.org/3/library/exceptions.html#Exception"><code>Exception</code></a> and <a
34
href="https://docs.python.org/3/library/exceptions.html#BaseException"><code>BaseException</code></a> will have a negative impact on any code trying
45
to catch these exceptions.</p>
5-
<p>First, the only way to handle differently multiple Exceptions is to check their message, which is error-prone and difficult to maintain.</p>
6-
<p>What’s more, it becomes difficult to catch only your exception. The best practice is to catch only exceptions which require a specific handling.
7-
When you raise <code>Exception</code> or <code>BaseException</code> in a function the caller will have to add an <code>except Exception</code> or
8-
<code>except BaseException</code> and re-raise all exceptions which were unintentionally caught. This can create tricky bugs when the caller forgets
9-
to re-raise exceptions such as <code>SystemExit</code> and the software cannot be stopped.</p>
10-
<p>It is recommended to either:</p>
6+
<p>From a consumer perspective, it is generally a best practice to only catch exceptions you intend to handle. Other exceptions should ideally not be
7+
caught and let to propagate up the stack trace so that they can be dealt with appropriately. When a generic exception is thrown, it forces consumers
8+
to catch exceptions they do not intend to handle, which they then have to re-raise.</p>
9+
<p>Besides, when working with a generic type of exception, the only way to distinguish between multiple exceptions is to check their message, which is
10+
error-prone and difficult to maintain. Legitimate exceptions may be unintentionally silenced and errors may be hidden.</p>
11+
<p>For instance, if an exception such as <code>SystemExit</code> is caught and not re-raised, it will prevent the program from stopping.</p>
12+
<p>When raising an exception, it is therefore recommended to raising the most specific exception possible so that it can be handled intentionally by
13+
consumers.</p>
14+
<h2>How to fix it</h2>
15+
<p>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:</p>
1116
<ul>
12-
<li> raise a more specific <a href="https://docs.python.org/3/library/exceptions.html">Built-in exception</a> when one matches. For example
17+
<li> Raise a specific <a href="https://docs.python.org/3/library/exceptions.html">Built-in exception</a> when one matches. For example
1318
<code>TypeError</code> should be raised when the type of a parameter is not the one expected. </li>
14-
<li> create a custom exception class deriving from <code>Exception</code> or one of its subclasses. A common practice for libraries is to have one
15-
custom root exception class from which every other custom exception class inherits. It enables other projects using this library to catch all errors
16-
coming from the library with a single "except" statement </li>
19+
<li> Create a custom exception class deriving from <code>Exception</code> or one of its subclasses. </li>
1720
</ul>
18-
<p>This rule raises an issue when <code>Exception</code> or <code>BaseException</code> are raised.</p>
19-
<h3>Noncompliant code example</h3>
20-
<pre>
21-
def process1():
22-
raise BaseException("Wrong user input for field X") # Noncompliant
23-
24-
def process2():
25-
raise BaseException("Wrong configuration") # Noncompliant
26-
27-
def process3(param):
28-
if not isinstance(param, int):
29-
raise Exception("param should be an integer") # Noncompliant
30-
31-
def caller():
32-
try:
33-
process1()
34-
process2()
35-
process3()
36-
except BaseException as e:
37-
if e.args[0] == "Wrong user input for field X":
38-
# process error
39-
pass
40-
elif e.args[0] == "Wrong configuration":
41-
# process error
42-
pass
43-
else:
44-
# re-raise other exceptions
45-
raise
21+
<h3>Code examples</h3>
22+
<h4>Noncompliant code example</h4>
23+
<pre data-diff-id="1" data-diff-type="noncompliant">
24+
def check_value(value):
25+
if value &lt; 0:
26+
raise BaseException("Value cannot be negative") # Noncompliant: this will be difficult for consumers to handle
4627
</pre>
47-
<h3>Compliant solution</h3>
48-
<pre>
49-
class MyProjectError(Exception):
50-
"""Exception class from which every exception in this library will derive.
51-
It enables other projects using this library to catch all errors coming
52-
from the library with a single "except" statement
53-
"""
54-
pass
55-
56-
class BadUserInputError(MyProjectError):
57-
"""A specific error"""
58-
pass
59-
60-
class ConfigurationError(MyProjectError):
61-
"""A specific error"""
62-
pass
63-
64-
def process1():
65-
raise BadUserInputError("Wrong user input for field X")
66-
67-
def process2():
68-
raise ConfigurationError("Wrong configuration")
69-
70-
def process3(param):
71-
if not isinstance(param, int):
72-
raise TypeError("param should be an integer")
73-
74-
def caller():
75-
try:
76-
process1()
77-
process2()
78-
process3()
79-
except BadUserInputError as e:
80-
# process error
81-
pass
82-
except ConfigurationError as e:
83-
# process error
84-
pass
28+
<h4>Compliant solution</h4>
29+
<pre data-diff-id="1" data-diff-type="compliant">
30+
def check_value(value):
31+
if value &lt; 0:
32+
raise ValueError("Value cannot be negative") # Compliant
8533
</pre>
8634
<h2>Resources</h2>
35+
<h3>Documentation</h3>
8736
<ul>
88-
<li> PEP 352 - <a href="https://www.python.org/dev/peps/pep-0352/#exception-hierarchy-changes">Required Superclass for Exceptions</a> </li>
8937
<li> Python Documentation - <a href="https://docs.python.org/3/library/exceptions.html#BaseException">Built-in exceptions</a> </li>
90-
<li> <a href="https://cwe.mitre.org/data/definitions/397">MITRE, CWE-397</a> - Declaration of Throws for Generic Exception </li>
38+
<li> PEP 352 - <a href="https://www.python.org/dev/peps/pep-0352/#exception-hierarchy-changes">Required Superclass for Exceptions</a> </li>
9139
</ul>
9240

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1128.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"status": "ready",
1111
"remediation": {
1212
"func": "Constant\/Issue",
13-
"constantCost": "2min"
13+
"constantCost": "1min"
1414
},
1515
"tags": [
1616
"unused"

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S113.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"title": "Files should contain an empty newline at the end",
2+
"title": "Files should end with a newline",
33
"type": "CODE_SMELL",
44
"code": {
55
"impacts": {
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<h2>Why is this an issue?</h2>
2-
<p>Trailing whitespaces are simply useless and should not stay in code. They may generate noise when comparing different versions of the same
3-
file.</p>
4-
<p>If you encounter issues from this rule, this probably means that you are not using an automated code formatter - which you should if you have the
5-
opportunity to do so.</p>
2+
<p>Trailing whitespaces bring no information, they may generate noise when comparing different versions of the same file, and they can create bugs
3+
when they appear after a <code>\</code> marking a line continuation. They should be systematically removed.</p>
4+
<p>An automated code formatter allows to completely avoid this family of issues and should be used wherever possible.</p>
65

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1135.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<h2>Why is this an issue?</h2>
2-
<p>Developers often use <code>TOOO</code> tags to mark areas in the code where additional work or improvements are needed but are not implemented
2+
<p>Developers often use <code>TODO</code> tags to mark areas in the code where additional work or improvements are needed but are not implemented
33
immediately. However, these <code>TODO</code> tags sometimes get overlooked or forgotten, leading to incomplete or unfinished code. This code smell
44
class aims to identify and address such unattended <code>TODO</code> tags to ensure a clean and maintainable codebase. This description will explore
55
why this is a problem and how it can be fixed to improve the overall code quality.</p>

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
<p>This rule raises an issue when a "class-private" method is never called inside the class where it was declared.</p>
12
<h2>Why is this an issue?</h2>
2-
<p>"Class-Private" methods that are never executed inside their enclosing class are dead code: unnecessary, inoperative code that should be removed.
3-
Cleaning out dead code decreases the size of the maintained codebase, making it easier to understand the program and preventing bugs from being
4-
introduced.</p>
3+
<p>A method that is never called is dead code, and should be removed. Cleaning out dead code decreases the size of the maintained codebase, making it
4+
easier to understand the program and preventing bugs from being introduced.</p>
55
<p>Python has no real private methods. Every method is accessible. There are however two conventions indicating that a method is not meant to be
66
"public":</p>
77
<ul>
@@ -15,7 +15,8 @@ <h2>Why is this an issue?</h2>
1515
</ul>
1616
<p>This rule raises an issue when a class-private method (two leading underscores, max one underscore at the end) is never called inside the class.
1717
Class methods, static methods and instance methods will all raise an issue.</p>
18-
<h3>Noncompliant code example</h3>
18+
<h3>Code examples</h3>
19+
<h4>Noncompliant code example</h4>
1920
<pre>
2021
class Noncompliant:
2122

@@ -30,7 +31,7 @@ <h3>Noncompliant code example</h3>
3031
def __mangled_instance_method(self): # Noncompliant
3132
print("__mangled_instance_method")
3233
</pre>
33-
<h3>Compliant solution</h3>
34+
<h4>Compliant solution</h4>
3435
<pre>
3536
class Compliant:
3637

python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"status": "ready",
1111
"remediation": {
1212
"func": "Constant\/Issue",
13-
"constantCost": "5min"
13+
"constantCost": "2min"
1414
},
1515
"tags": [
1616
"unused"

0 commit comments

Comments
 (0)