[java] Fix #2368 - UnsynchronizedStaticFormatter FP in static initializer

This commit is contained in:
Clément Fournier
2024-05-13 17:18:11 +02:00
parent e5f55c08a5
commit 228a1f5017
2 changed files with 29 additions and 7 deletions
@@ -8,14 +8,15 @@ import java.text.Format;
import java.util.Arrays;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
import net.sourceforge.pmd.lang.java.ast.ASTClassType;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTInitializer;
import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.ast.ASTVariableId;
import net.sourceforge.pmd.lang.java.ast.JModifier;
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
@@ -62,12 +63,13 @@ public class UnsynchronizedStaticFormatterRule extends AbstractJavaRulechainRule
if (!node.hasModifiers(JModifier.STATIC)) {
return data;
}
ASTClassType cit = node.descendants(ASTClassType.class).first();
if (cit == null || !TypeTestUtil.isA(formatterClassToCheck, cit)) {
ASTType cit = node.getTypeNode();
if (!(cit instanceof ASTClassType)
|| !TypeTestUtil.isA(formatterClassToCheck, cit)) {
return data;
}
ASTVariableId var = node.descendants(ASTVariableId.class).first();
ASTVariableId var = node.getVarIds().firstOrThrow();
for (String formatter: THREAD_SAFE_FORMATTER) {
if (TypeTestUtil.isA(formatter, var)) {
return data;
@@ -83,8 +85,6 @@ public class UnsynchronizedStaticFormatterRule extends AbstractJavaRulechainRule
continue;
}
Node n = ref;
// is there a block-level synch?
ASTSynchronizedStatement syncStatement = ref.ancestors(ASTSynchronizedStatement.class).first();
if (syncStatement != null) {
@@ -102,7 +102,12 @@ public class UnsynchronizedStaticFormatterRule extends AbstractJavaRulechainRule
}
}
asCtx(data).addViolation(n);
boolean hasStaticInit = ref.ancestors(ASTInitializer.class).any(ASTInitializer::isStatic);
if (hasStaticInit) {
continue;
}
asCtx(data).addViolation(ref);
}
return data;
}
@@ -304,4 +304,21 @@ public class Foo {
}
]]></code>
</test-code>
<test-code>
<description> [java] False positive UnsynchronizedStaticFormatter in static initializer #2368 </description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import java.text.NumberFormat;
class WithFormatter {
private static final NumberFormat formatter;
static {
formatter = NumberFormat.getInstance();
formatter.setMaximumFractionDigits(2); // FALSE POSITIVE
}
// …
}
]]></code>
</test-code>
</test-data>