Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import java.util.function.IntSupplier;
import java.util.function.IntUnaryOperator;
import java.util.function.Supplier;

abstract class A {

public void reproducer() {
Expand Down Expand Up @@ -329,4 +333,115 @@ void continueInTryFinallyOutsideLoop() {
foo();
}
}

Runnable emptyLambda = () -> {};

Runnable expressionLambda = () -> System.out.println("expression");

Supplier<Runnable> expressionReturningLambda = () -> () -> {
return; // Noncompliant {{Remove this redundant return.}}
// ^^^^^^^
};

Runnable fieldInitializer = () -> {
System.out.println("field");
return; // Noncompliant {{Remove this redundant return.}}
// ^^^^^^^
};

void immediatelyInvokedLambda(int x) {
Runnable r = () -> {
System.out.println(x);
return; // Noncompliant {{Remove this redundant return.}}
// ^^^^^^^
};
r.run();
System.out.println("after lambda");
}

Runnable conditionalReturns(int x) {
return () -> {
if (x < 0) {
return;
}
System.out.println(x);
if (x == 0) {
return; // Noncompliant {{Remove this redundant return.}}
// ^^^^^^^
}
};
}

IntSupplier valueReturningLambda(int x) {
return () -> {
System.out.println(x);
return x;
};
}

Runnable nestedLambdas(int x) {
return () -> {
Runnable inner = () -> {
System.out.println(x);
return; // Noncompliant {{Remove this redundant return.}}
// ^^^^^^^
};
inner.run();
System.out.println("after inner lambda");
};
}

Runnable loopJumps(int x) {
return () -> {
for (int i = 0; i < x; i++) {
if (i == 1) {
continue;
}
if (i == 2) {
return;
}
System.out.println(i);
continue; // Noncompliant {{Remove this redundant continue.}}
// ^^^^^^^^^
}
};
}

Runnable returnThroughFinally(int x) {
return () -> {
try {
System.out.println(x);
return; // Noncompliant {{Remove this redundant return.}}
// ^^^^^^^
} finally {
System.out.println("cleanup");
}
};
}

Runnable earlyReturnThroughFinally(int x) {
return () -> {
try {
if (x < 0) {
return;
}
} finally {
System.out.println("cleanup");
}
System.out.println(x);
};
}

IntUnaryOperator continueInSwitchExpressionLambda() {
return x -> switch (x) {
default -> {
for (int i = 0; i < x; i++) {
System.out.println(i);
continue; // Noncompliant {{Remove this redundant continue.}}
// ^^^^^^^^^
}
yield x;
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
import org.sonar.java.cfg.CFG.Block;
import org.sonar.java.cfg.CFGUtils;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.LambdaExpressionTree;
import org.sonar.plugins.java.api.tree.MethodTree;
import org.sonar.plugins.java.api.tree.ReturnStatementTree;
import org.sonar.plugins.java.api.tree.SyntaxToken;
import org.sonar.plugins.java.api.tree.Tree;

@Rule(key = "S3626")
Expand All @@ -35,14 +37,22 @@ public class RedundantJumpCheck extends IssuableSubscriptionVisitor {
public List<Tree.Kind> nodesToVisit() {
return Arrays.asList(
Tree.Kind.METHOD,
Tree.Kind.CONSTRUCTOR);
Tree.Kind.CONSTRUCTOR,
Tree.Kind.LAMBDA_EXPRESSION);
}

@Override
public void visitNode(Tree tree) {
MethodTree methodTree = (MethodTree) tree;
if (methodTree.block() != null) {
CFG cfg = (CFG) methodTree.cfg();
CFG cfg = null;
if (tree instanceof MethodTree methodTree) {
if (methodTree.block() != null) {
cfg = (CFG) methodTree.cfg();
}
} else {
// Expression-bodied lambdas can contain redundant continue statements in loops inside switch expressions.
cfg = (CFG) ((LambdaExpressionTree) tree).cfg();
}
if (cfg != null) {
cfg.blocks().forEach(this::checkBlock);
}
}
Expand All @@ -64,7 +74,9 @@ && hasValidContinueTarget(terminator)) {
Block successor = CFGUtils.nonEmptySuccessor(successors.next());
if (successor.equals(successorWithoutJump)
&& !CFGUtils.isJumpThroughFinallyWithDistinctContinuation(terminator, successor)) {
reportIssue(terminator, "Remove this redundant jump.");
SyntaxToken fstToken = terminator.firstToken();
String jump = fstToken != null ? fstToken.text() : "jump";
reportIssue(terminator, "Remove this redundant %s.".formatted(jump));
}
}
}
Expand Down
Loading