Fix #3362: [java] ImplicitSwitchFallThrough should consider switch expressions (#5248)

This commit is contained in:
Andreas Dangel
2024-10-24 10:46:59 +02:00
3 changed files with 41 additions and 9 deletions

View File

@@ -48,6 +48,7 @@ The old rule names still work but are deprecated.
* java-design
* [#5030](https://github.com/pmd/pmd/issues/5030): \[java] SwitchDensity false positive with pattern matching
* java-errorprone
* [#3362](https://github.com/pmd/pmd/issues/3362): \[java] ImplicitSwitchFallThrough should consider switch expressions
* [#5067](https://github.com/pmd/pmd/issues/5067): \[java] CloseResource: False positive for FileSystems.getDefault()
### 🚨 API Changes
@@ -67,6 +68,7 @@ The old rule names still work but are deprecated.
* [#5241](https://github.com/pmd/pmd/pull/5241): Ignore javacc code in coverage report - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
* [#5245](https://github.com/pmd/pmd/pull/5245): \[java] Improve UnitTestShouldUse{After,Before}Annotation rules to support JUnit5 and TestNG - [Andreas Dangel](https://github.com/adangel) (@adangel)
* [#5247](https://github.com/pmd/pmd/pull/5247): Fix #5030: \[java] SwitchDensity false positive with pattern matching - [Andreas Dangel](https://github.com/adangel) (@adangel)
* [#5248](https://github.com/pmd/pmd/pull/5248): Fix #3362: \[java] ImplicitSwitchFallThrough should consider switch expressions - [Andreas Dangel](https://github.com/adangel) (@adangel)
* [#5258](https://github.com/pmd/pmd/pull/5258): Ignore generated antlr classes in coverage reports - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
* [#5264](https://github.com/pmd/pmd/pull/5264): Fix #5261: \[java] Fix NPE with empty pattern list - [Clément Fournier](https://github.com/oowekyala) (@oowekyala)
* [#5269](https://github.com/pmd/pmd/pull/5269): Fix #5253: \[java] Support Boolean wrapper class for BooleanGetMethodName rule - [Aryant Tripathi](https://github.com/Aryant-Tripathi) (@Aryant-Tripathi)

View File

@@ -9,28 +9,40 @@ import java.util.regex.Pattern;
import net.sourceforge.pmd.lang.ast.GenericToken;
import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchFallthroughBranch;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchLike;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
import net.sourceforge.pmd.lang.java.ast.JavaNode;
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass;
import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.DataflowResult;
import net.sourceforge.pmd.reporting.RuleContext;
import net.sourceforge.pmd.util.OptionalBool;
public class ImplicitSwitchFallThroughRule extends AbstractJavaRulechainRule {
//todo should consider switch exprs
private static final Pattern IGNORED_COMMENT = Pattern.compile("/[/*].*\\bfalls?[ -]?thr(ough|u)\\b.*",
Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
public ImplicitSwitchFallThroughRule() {
super(ASTSwitchStatement.class);
super(ASTSwitchStatement.class, ASTSwitchExpression.class);
}
@Override
public Object visit(ASTSwitchStatement node, Object data) {
checkSwitchLike(node, asCtx(data));
return null;
}
@Override
public Object visit(ASTSwitchExpression node, Object data) {
checkSwitchLike(node, asCtx(data));
return null;
}
private void checkSwitchLike(ASTSwitchLike node, RuleContext ruleContext) {
DataflowResult dataflow = DataflowPass.getDataflowResult(node.getRoot());
for (ASTSwitchBranch branch : node.getBranches()) {
@@ -38,15 +50,14 @@ public class ImplicitSwitchFallThroughRule extends AbstractJavaRulechainRule {
ASTSwitchFallthroughBranch fallthrough = (ASTSwitchFallthroughBranch) branch;
OptionalBool bool = dataflow.switchBranchFallsThrough(branch);
if (bool != OptionalBool.NO
&& fallthrough.getStatements().nonEmpty()
&& !nextBranchHasComment(branch)) {
asCtx(data).addViolation(branch.getNextBranch().getLabel());
&& fallthrough.getStatements().nonEmpty()
&& !nextBranchHasComment(branch)) {
ruleContext.addViolation(branch.getNextBranch().getLabel());
}
} else {
return null;
return;
}
}
return null;
}
boolean nextBranchHasComment(ASTSwitchBranch branch) {
@@ -62,5 +73,4 @@ public class ImplicitSwitchFallThroughRule extends AbstractJavaRulechainRule {
}
return false;
}
}

View File

@@ -581,4 +581,24 @@ public class Test {
}
]]></code>
</test-code>
<test-code>
<description>switch expression with one case, which is not empty</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>6</expected-linenumbers>
<code><![CDATA[
public class Foo {
public static void main(String[] args) {
int i = 1;
String result = switch(i) {
case 1: doSomething();
default: yield "default case fall through";
};
System.out.println(result);
}
private static void doSomething() {}
}
]]></code>
</test-code>
</test-data>