
org.sonar.java.checks.BigDecimalDoubleConstructorCheck Maven / Gradle / Ivy
/*
* SonarQube Java
* Copyright (C) 2012-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
package org.sonar.java.checks;
import java.util.Collections;
import java.util.List;
import org.sonar.check.Rule;
import org.sonar.java.model.DefaultJavaFileScannerContext;
import org.sonar.java.reporting.InternalJavaIssueBuilder;
import org.sonar.java.reporting.JavaQuickFix;
import org.sonar.java.reporting.JavaTextEdit;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.MethodMatchers;
import org.sonar.plugins.java.api.tree.Arguments;
import org.sonar.plugins.java.api.tree.ExpressionTree;
import org.sonar.plugins.java.api.tree.LiteralTree;
import org.sonar.plugins.java.api.tree.NewClassTree;
import org.sonar.plugins.java.api.tree.Tree;
@Rule(key = "S2111")
public class BigDecimalDoubleConstructorCheck extends IssuableSubscriptionVisitor {
private static final MethodMatchers BIG_DECIMAL_DOUBLE_FLOAT =
MethodMatchers.create().ofTypes("java.math.BigDecimal")
.constructor()
.addParametersMatcher("double")
.addParametersMatcher("float")
.addParametersMatcher("double", MethodMatchers.ANY)
.addParametersMatcher("float", MethodMatchers.ANY)
.build();
@Override
public List nodesToVisit() {
return Collections.singletonList(Tree.Kind.NEW_CLASS);
}
@Override
public void visitNode(Tree tree) {
NewClassTree newClassTree = (NewClassTree) tree;
if (BIG_DECIMAL_DOUBLE_FLOAT.matches(newClassTree)) {
InternalJavaIssueBuilder builder = ((InternalJavaIssueBuilder) ((DefaultJavaFileScannerContext) context).newIssue())
.forRule(this)
.onTree(tree);
Arguments arguments = newClassTree.arguments();
if (arguments.size() == 1) {
builder.withMessage("Use \"BigDecimal.valueOf\" instead.");
builder.withQuickFix(() -> valueOfQuickFix(newClassTree));
} else {
builder.withMessage("Use \"new BigDecimal(String, MathContext)\" instead.");
ExpressionTree firstArgument = arguments.get(0);
if (firstArgument instanceof LiteralTree literalTree) {
builder.withQuickFix(() -> stringConstructorQuickFix(literalTree));
}
}
builder.report();
}
}
private static JavaQuickFix valueOfQuickFix(NewClassTree newClassTree) {
return JavaQuickFix.newQuickFix("Replace with BigDecimal.valueOf")
.addTextEdit(JavaTextEdit.replaceBetweenTree(newClassTree.newKeyword(), newClassTree.identifier(), "BigDecimal.valueOf"))
.build();
}
private static JavaQuickFix stringConstructorQuickFix(LiteralTree argument) {
String argumentValue = argument.value();
if (argumentValue.endsWith("f") || argumentValue.endsWith("d") || argumentValue.endsWith("F") || argumentValue.endsWith("D")) {
argumentValue = argumentValue.substring(0, argumentValue.length() - 1);
}
String newArgument = String.format("\"%s\"", argumentValue);
return JavaQuickFix.newQuickFix("Replace with BigDecimal(%s,", newArgument)
.addTextEdit(JavaTextEdit.replaceTree(argument, newArgument))
.build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy