package quickfix;
import static edu.umd.cs.findbugs.plugin.eclipse.quickfix.util.ASTUtil.getASTNode;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.plugin.eclipse.quickfix.BugResolution;
import edu.umd.cs.findbugs.plugin.eclipse.quickfix.CustomLabelVisitor;
import edu.umd.cs.findbugs.plugin.eclipse.quickfix.exception.BugResolutionException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
public class BigDecimalConstructorResolution extends BugResolution {
private boolean useConstructor;
@Override
protected boolean resolveBindings() {
return true;
}
@Override
public void setOptions(@Nonnull Map<String, String> options) {
useConstructor = Boolean.parseBoolean(options.get("useConstructor"));
}
@Override
protected ASTVisitor getCustomLabelVisitor() {
return new BigDecimalVisitor();
}
@Override
protected void repairBug(ASTRewrite rewrite, CompilationUnit workingUnit, BugInstance bug) throws BugResolutionException {
ASTNode node = getASTNode(workingUnit, bug.getPrimarySourceLineAnnotation());
BigDecimalVisitor visitor = new BigDecimalVisitor();
node.accept(visitor);
Expression fixedExpression = makeFixedExpression(rewrite, visitor);
rewrite.replace(visitor.badBigDecimalConstructor, fixedExpression, null);
}
private Expression makeFixedExpression(ASTRewrite rewrite, BigDecimalVisitor visitor) {
if (useConstructor) {
return makeConstructor(rewrite, visitor);
}
return makeValueOf(rewrite, visitor);
}
@SuppressWarnings("unchecked")
private Expression makeValueOf(ASTRewrite rewrite, BigDecimalVisitor visitor) {
AST ast = rewrite.getAST();
MethodInvocation fixedMethod = ast.newMethodInvocation();
fixedMethod.setName(ast.newSimpleName("valueOf"));
SimpleName staticType = ast.newSimpleName("BigDecimal");
fixedMethod.setExpression(staticType);
fixedMethod.arguments().add(rewrite.createMoveTarget(visitor.decimalVar));
return fixedMethod;
}
@SuppressWarnings("unchecked")
private Expression makeConstructor(ASTRewrite rewrite, BigDecimalVisitor visitor) {
AST ast = rewrite.getAST();
ClassInstanceCreation fixedConstructor = ast.newClassInstanceCreation();
fixedConstructor.setType((Type) rewrite.createCopyTarget(visitor.badBigDecimalConstructor.getType()));
StringLiteral stringLiteral = ast.newStringLiteral();
stringLiteral.setLiteralValue(visitor.decimalVar.getToken());
fixedConstructor.arguments().add(stringLiteral);
return fixedConstructor;
}
private static class BigDecimalVisitor extends ASTVisitor implements CustomLabelVisitor {
public ClassInstanceCreation badBigDecimalConstructor = null;
private NumberLiteral decimalVar;
@Override
public boolean visit(ClassInstanceCreation node) {
if (badBigDecimalConstructor != null) {
return false;
}
Type type = node.getType();
if (type instanceof SimpleType
&& "BigDecimal".equals(((SimpleType) type).getName().getFullyQualifiedName())) {
@SuppressWarnings("unchecked")
List<Expression> args = node.arguments();
if (args.size() == 1 && args.get(0) instanceof NumberLiteral) {
badBigDecimalConstructor = node;
this.decimalVar = (NumberLiteral) node.arguments().get(0);
}
}
return true;
}
@Override
public String getLabelReplacement() {
return decimalVar.getToken();
}
}
}