Modify S1199: Migrate to LayC - Nested code blocks should not be used (#3233)
Co-authored-by: Marco Borgeaud <89914223+marco-antognini-sonarsource@users.noreply.github.com>
This commit is contained in:
parent
5ed9a4f18a
commit
c24d13b88a
@ -1,16 +1,20 @@
|
|||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
Nested code blocks can be used to create a new scope: variables declared within that block cannot be accessed from the outside, and their lifetime end at the end of the block.
|
include::../description.adoc[]
|
||||||
|
|
||||||
While this might seem convenient, using this feature in a function often indicates that it has too many responsibilities and should be refactored into smaller functions.
|
However, nested code blocks are acceptable when they encapsulate all statements within a `switch` (a `case xxx:` or a `default:`)
|
||||||
|
to prevent variable declarations from interfering with other `cases`.
|
||||||
|
|
||||||
A nested code block is acceptable when it surrounds all the statements inside an alternative of a `switch` (a `case xxx:` or a `default:`) because it prevents variable declarations from polluting other `cases`.
|
== How to fix it
|
||||||
|
|
||||||
=== Noncompliant code example
|
The nested code blocks should be extracted into separate methods.
|
||||||
|
|
||||||
[source,cpp]
|
=== Code examples
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,cpp,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
|
|
||||||
void f(Cache &c, int data) {
|
void f(Cache &c, int data) {
|
||||||
int value;
|
int value;
|
||||||
{ // Noncompliant
|
{ // Noncompliant
|
||||||
@ -37,9 +41,9 @@ void f(Cache &c, int data) {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
==== Compliant solution
|
||||||
|
|
||||||
[source,cpp]
|
[source,cpp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
int getValue(Cache &c, int data) {
|
int getValue(Cache &c, int data) {
|
||||||
std::scoped_lock l(c.getMutex());
|
std::scoped_lock l(c.getMutex());
|
||||||
@ -66,8 +70,14 @@ void f(Cache &c, int data) {
|
|||||||
case 2:
|
case 2:
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
== Resources
|
||||||
|
|
||||||
|
=== Documentation
|
||||||
|
* Wikipedia - https://en.wikipedia.org/wiki/Single-responsibility_principle[Single Responsibility Principle]
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
ifdef::env-github,rspecator-view[]
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -80,6 +90,4 @@ include::../message.adoc[]
|
|||||||
== Comments And Links
|
== Comments And Links
|
||||||
(visible only on this page)
|
(visible only on this page)
|
||||||
|
|
||||||
include::../comments-and-links.adoc[]
|
include::../comments-and-links.adoc[]
|
||||||
|
|
||||||
endif::env-github,rspecator-view[]
|
|
@ -2,9 +2,19 @@
|
|||||||
|
|
||||||
include::../description.adoc[]
|
include::../description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
=== Exceptions
|
||||||
|
|
||||||
[source,csharp]
|
The usage of a code block after a `case` is allowed.
|
||||||
|
|
||||||
|
== How to fix it
|
||||||
|
|
||||||
|
The nested code blocks should be extracted into separate methods.
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
public void Evaluate()
|
public void Evaluate()
|
||||||
{
|
{
|
||||||
@ -19,9 +29,9 @@ public void Evaluate()
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
==== Compliant solution
|
||||||
|
|
||||||
[source,csharp]
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public void Evaluate()
|
public void Evaluate()
|
||||||
{
|
{
|
||||||
@ -39,9 +49,10 @@ private void StackAdd()
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Exceptions
|
== Resources
|
||||||
|
|
||||||
The usage of a code block after a "case" is allowed for this rule.
|
=== Documentation
|
||||||
|
* Wikipedia - https://en.wikipedia.org/wiki/Single-responsibility_principle[Single Responsibility Principle]
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
ifdef::env-github,rspecator-view[]
|
||||||
|
|
||||||
@ -55,6 +66,4 @@ include::../message.adoc[]
|
|||||||
== Comments And Links
|
== Comments And Links
|
||||||
(visible only on this page)
|
(visible only on this page)
|
||||||
|
|
||||||
include::../comments-and-links.adoc[]
|
include::../comments-and-links.adoc[]
|
||||||
|
|
||||||
endif::env-github,rspecator-view[]
|
|
@ -1 +1,6 @@
|
|||||||
Nested code blocks can be used to create a new scope and restrict the visibility of the variables defined inside it. Using this feature in a method typically indicates that the method has too many responsibilities, and should be refactored into smaller methods.
|
Nested code blocks create new scopes where variables declared within are inaccessible from the outside, and their lifespan ends with the block.
|
||||||
|
|
||||||
|
Although this may appear beneficial, their usage within a function often suggests that the function is overloaded.
|
||||||
|
Thus, it may violate the Single Responsibility Principle, and the function needs to be broken down into smaller functions.
|
||||||
|
|
||||||
|
The presence of nested blocks that don't affect the control flow might suggest possible mistakes in the code.
|
||||||
|
@ -2,50 +2,74 @@
|
|||||||
|
|
||||||
include::../description.adoc[]
|
include::../description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
=== Exceptions
|
||||||
|
|
||||||
[source,java]
|
The usage of a code block after a `case` is allowed.
|
||||||
|
|
||||||
|
== How to fix it
|
||||||
|
|
||||||
|
The nested code blocks should be extracted into separate methods.
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
public void evaluate(int operator) {
|
class Example {
|
||||||
// Do some computation...
|
|
||||||
{
|
private final Deque<Integer> stack = new LinkedList<>();
|
||||||
int a = stack.pop();
|
|
||||||
int b = stack.pop();
|
public void evaluate(int operator) {
|
||||||
int result = a + b;
|
switch (operator) {
|
||||||
stack.push(result);
|
case ADD: {
|
||||||
}
|
/* ... */
|
||||||
|
{ // Noncompliant - Extract this nested code block into a method
|
||||||
|
int a = stack.pop();
|
||||||
|
int b = stack.pop();
|
||||||
|
int result = a + b;
|
||||||
|
stack.push(result);
|
||||||
|
}
|
||||||
|
/* ... */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Compliant solution
|
==== Compliant solution
|
||||||
|
|
||||||
[source,java]
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public void evaluate(int operator) {
|
class Example {
|
||||||
// Do some computation...
|
|
||||||
evaluateAdd();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void evaluateAdd() {
|
private final Deque<Integer> stack = new LinkedList<>();
|
||||||
int a = stack.pop();
|
|
||||||
int b = stack.pop();
|
public void evaluate(int operator) {
|
||||||
int result = a + b;
|
switch (operator) {
|
||||||
stack.push(result);
|
case ADD: {
|
||||||
|
/* ... */
|
||||||
|
evaluateAdd();
|
||||||
|
/* ... */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluateAdd() {
|
||||||
|
int a = stack.pop();
|
||||||
|
int b = stack.pop();
|
||||||
|
int result = a + b;
|
||||||
|
stack.push(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
ifdef::env-github,rspecator-view[]
|
== Resources
|
||||||
|
|
||||||
'''
|
=== Documentation
|
||||||
== Implementation Specification
|
* Wikipedia - https://en.wikipedia.org/wiki/Single-responsibility_principle[Single Responsibility Principle]
|
||||||
(visible only on this page)
|
* Baeldung - https://www.baeldung.com/java-single-responsibility-principle[Single Responsibility Principle]
|
||||||
|
|
||||||
include::../message.adoc[]
|
|
||||||
|
|
||||||
'''
|
|
||||||
== Comments And Links
|
|
||||||
(visible only on this page)
|
|
||||||
|
|
||||||
include::../comments-and-links.adoc[]
|
|
||||||
|
|
||||||
endif::env-github,rspecator-view[]
|
|
||||||
|
@ -1,37 +1,13 @@
|
|||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
Nested code blocks can be used to create a new scope: variables declared within that block cannot be accessed from the outside, and their lifetime end at the end of the block. However this only happens when you use ES6 `let` or `const` keywords, a class declaration or a function declaration (in strict mode). Otherwise the nested block is redundant and should be removed.
|
Nested code blocks can be used to create a new scope: variables declared within that block cannot be accessed from the outside,
|
||||||
|
and their lifetime end at the end of the block. However, this only happens when you use ES6 `let` or `const` keywords,
|
||||||
The presense of redundant blocks (the ones which are not part of control flow and do not create a new scope) is confusing and may point to errors in the code.
|
a class declaration or a function declaration (in strict mode). Otherwise, the nested block is redundant and should be removed.
|
||||||
|
|
||||||
[source,javascript,diff-id=1,diff-type=noncompliant]
|
|
||||||
----
|
|
||||||
{ // Noncompliant: redundant code block
|
|
||||||
var foo = bar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
doSomething();
|
|
||||||
{ // Noncompliant: redundant code block
|
|
||||||
doOtherStuff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
To fix your code remove redundant blocks.
|
|
||||||
|
|
||||||
[source,javascript,diff-id=1,diff-type=compliant]
|
|
||||||
----
|
|
||||||
var foo = bar();
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
doSomething();
|
|
||||||
doOtherStuff();
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Exceptions
|
=== Exceptions
|
||||||
|
|
||||||
|
The rule does not apply to the following cases:
|
||||||
|
|
||||||
* Block statements containing variable declarations using `let` or `const` keywords or class declarations are not redundant as they create a new scope.
|
* Block statements containing variable declarations using `let` or `const` keywords or class declarations are not redundant as they create a new scope.
|
||||||
|
|
||||||
[source,javascript]
|
[source,javascript]
|
||||||
@ -60,14 +36,48 @@ if (condition) {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
== How to fix it
|
||||||
|
|
||||||
|
The nested code blocks should be extracted into separate methods.
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,javascript,diff-id=1,diff-type=noncompliant]
|
||||||
|
----
|
||||||
|
{ // Noncompliant: redundant code block
|
||||||
|
var foo = bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition) {
|
||||||
|
doSomething();
|
||||||
|
{ // Noncompliant: redundant code block
|
||||||
|
doOtherStuff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
==== Compliant solution
|
||||||
|
|
||||||
|
[source,javascript,diff-id=1,diff-type=compliant]
|
||||||
|
----
|
||||||
|
var foo = bar();
|
||||||
|
|
||||||
|
if (condition) {
|
||||||
|
doSomething();
|
||||||
|
doOtherStuff();
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
== Resources
|
== Resources
|
||||||
=== Documentation
|
|
||||||
|
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block[MDN - block statement]
|
=== Documentation
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var[MDN - var]
|
* Wikipedia - https://en.wikipedia.org/wiki/Single-responsibility_principle[Single Responsibility Principle]
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let[MDN - let]
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block[block statement]
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const[MDN - const]
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var[var]
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class[MDN - class declaration]
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let[let]
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function[MDN - function declaration]
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const[const]
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode[MDN - strict mode]
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class[class declaration]
|
||||||
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function[function declaration]
|
||||||
|
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode[strict mode]
|
@ -2,9 +2,15 @@
|
|||||||
|
|
||||||
include::description.adoc[]
|
include::description.adoc[]
|
||||||
|
|
||||||
=== Noncompliant code example
|
== How to fix it
|
||||||
|
|
||||||
[source,text]
|
The superfluous code blocks should be extracted into separate methods
|
||||||
|
|
||||||
|
=== Code examples
|
||||||
|
|
||||||
|
==== Noncompliant code example
|
||||||
|
|
||||||
|
[source,text,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
public void evaluate(int operator) {
|
public void evaluate(int operator) {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
@ -21,10 +27,11 @@ public void evaluate(int operator) {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
==== Compliant solution
|
||||||
|
|
||||||
=== Compliant solution
|
To fix your code remove redundant blocks.
|
||||||
|
|
||||||
[source,text]
|
[source,text,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public void evaluate(int operator) {
|
public void evaluate(int operator) {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
@ -44,3 +51,7 @@ private void evaluateAdd() {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
== Resources
|
||||||
|
|
||||||
|
=== Documentation
|
||||||
|
* https://en.wikipedia.org/wiki/Single-responsibility_principle[Single Responsibility Principle | Wikipedia]
|
Loading…
x
Reference in New Issue
Block a user