[java] SwitchDensity false positive with pattern matching

Fixes #5030
This commit is contained in:
Andreas Dangel 2024-10-04 17:12:29 +02:00
parent a0818d5ab2
commit 49deb8d4a0
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
4 changed files with 40 additions and 3 deletions

View File

@ -32,6 +32,8 @@ The old rule names still work but are deprecated.
### 🐛 Fixed Issues ### 🐛 Fixed Issues
* java * java
* [#4532](https://github.com/pmd/pmd/issues/4532): \[java] Rule misnomer for JUnit* rules * [#4532](https://github.com/pmd/pmd/issues/4532): \[java] Rule misnomer for JUnit* rules
* java-design
* [#5030](https://github.com/pmd/pmd/issues/5030): \[java] SwitchDensity false positive with pattern matching
* java-errorprone * java-errorprone
* [#5067](https://github.com/pmd/pmd/issues/5067): \[java] CloseResource: False positive for FileSystems.getDefault() * [#5067](https://github.com/pmd/pmd/issues/5067): \[java] CloseResource: False positive for FileSystems.getDefault()

View File

@ -50,8 +50,9 @@ public final class ASTSwitchLabel extends AbstractJavaNode implements Iterable<A
/** /**
* Returns the expressions of this label, or an empty list if this * Returns the expressions of this label, or an empty list if this
* is the default label. This may contain {@linkplain ASTPatternExpression pattern expressions} * is the default label. This does neither contain {@linkplain ASTTypePattern TypePatterns}
* to represent patterns. * nor {@linkplain ASTRecordPattern RecordPatterns}. To check for this,
* use {@link #isPatternLabel()}.
*/ */
public NodeStream<ASTExpression> getExprList() { public NodeStream<ASTExpression> getExprList() {
return children(ASTExpression.class); return children(ASTExpression.class);
@ -66,4 +67,12 @@ public final class ASTSwitchLabel extends AbstractJavaNode implements Iterable<A
public Iterator<ASTExpression> iterator() { public Iterator<ASTExpression> iterator() {
return children(ASTExpression.class).iterator(); return children(ASTExpression.class).iterator();
} }
/**
* Checks whether this label tests a {@link ASTTypePattern} or a {@link ASTRecordPattern}.
* @since 7.7.0
*/
public boolean isPatternLabel() {
return children(ASTPattern.class).nonEmpty();
}
} }

View File

@ -55,7 +55,7 @@ public class SwitchDensityRule extends AbstractJavaRulechainRule {
int stmtCount = node.descendants(ASTStatement.class).count(); int stmtCount = node.descendants(ASTStatement.class).count();
int labelCount = node.getBranches() int labelCount = node.getBranches()
.map(ASTSwitchBranch::getLabel) .map(ASTSwitchBranch::getLabel)
.sumBy(label -> label.isDefault() ? 1 : label.getExprList().count()); .sumBy(label -> label.isDefault() || label.isPatternLabel() ? 1 : label.getExprList().count());
// note: if labelCount is zero, double division will produce +Infinity or NaN, not ArithmeticException // note: if labelCount is zero, double division will produce +Infinity or NaN, not ArithmeticException
double density = stmtCount / (double) labelCount; double density = stmtCount / (double) labelCount;

View File

@ -152,6 +152,32 @@ public class SwitchWithDefault
{ {
} }
} }
}
]]></code>
</test-code>
<test-code>
<description>[java] SwitchDensity false positive with pattern matching #5030</description>
<rule-property name="minimum">4</rule-property>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class SwitchDensityPattern {
public void foo(Object o) {
switch (o) {
case Integer i when i > 0 ->
{
System.err.println("I am a fish.");
}
case Integer i ->
{
System.err.println("I am not a fish.");
}
default ->
{
System.err.println("default");
}
}
}
} }
]]></code> ]]></code>
</test-code> </test-code>