private Object literalValue(Tree arg) { if (!(arg instanceof LiteralTree)) { return null; } return ((LiteralTree) arg).getValue(); } }
private boolean canBooleanExpressionEvalToTrue(ExpressionTree expressionTree) { if (expressionTree instanceof LiteralTree) { LiteralTree expressionAsLiteral = (LiteralTree) expressionTree; if (expressionAsLiteral.getValue() instanceof Boolean) { return (boolean) expressionAsLiteral.getValue(); } else { throw new RuntimeException("not a boolean expression!"); } } // We are fairly conservative, anything other than 'return false;' is assumed to potentially be // true. // No SAT-solving or any other funny business. return true; }
@Override public boolean matches(ExpressionTree expressionTree, VisitorState state) { if (expressionTree instanceof LiteralTree) { LiteralTree literalTree = (LiteralTree) expressionTree; Object actualValue = literalTree.getValue(); return actualValue instanceof String && pattern.matcher((String) actualValue).matches(); } else { return false; } } }
private boolean matches(List<? extends ExpressionTree> expressionTrees) { Set<Integer> foundValues = new HashSet<>(); for (Tree tree : expressionTrees) { if (tree instanceof LiteralTree) { Object value = ((LiteralTree) tree).getValue(); if (value instanceof Integer) { boolean duplicate = !foundValues.add((Integer) value); if (!duplicate && foundValues.size() > 1) { return true; } } } } return false; } }
@Override public boolean matches(ExpressionTree expressionTree, VisitorState state) { if (expressionTree.getKind() == Kind.INT_LITERAL) { return ((Integer) ((LiteralTree) expressionTree).getValue()).equals(value); } return false; } };
@Override public boolean matches(ExpressionTree expressionTree, VisitorState state) { if (expressionTree.getKind() == Tree.Kind.BOOLEAN_LITERAL) { return value == (Boolean) (((LiteralTree) expressionTree).getValue()); } return false; } };
@Override public ULiteral visitLiteral(LiteralTree tree, Void v) { return ULiteral.create(tree.getKind(), tree.getValue()); }
@Override public Description matchMethodInvocation(MethodInvocationTree t, VisitorState state) { if (PRECONDITIONS_CHECK.matches(t, state) && t.getArguments().size() >= 2 && t.getArguments().get(1) instanceof LiteralTree) { LiteralTree formatStringTree = (LiteralTree) t.getArguments().get(1); if (formatStringTree.getValue() instanceof String) { String formatString = (String) formatStringTree.getValue(); int expectedArgs = expectedArguments(formatString); if (expectedArgs < t.getArguments().size() - 2 && BAD_PLACEHOLDER_REGEX.matcher(formatString).find()) { return describe(t, state); } } } return Description.NO_MATCH; }
@Override public Choice<Unifier> visitLiteral(LiteralTree literal, Unifier unifier) { return Choice.condition(match(getValue(), literal.getValue()), unifier); }
@Override public Description matchLiteral(LiteralTree tree, VisitorState state) { // Is there a literal matching the message SWIG uses to indicate a // destructor problem? if (tree.getValue() == null || !tree.getValue().equals("C++ destructor does not have public access")) { return NO_MATCH; } // Is it within a delete method? MethodTree enclosingMethodTree = ASTHelpers.findEnclosingNode(state.getPath(), MethodTree.class); Name name = enclosingMethodTree.getName(); if (!name.contentEquals("delete")) { return NO_MATCH; } // Does the enclosing class lack a finalizer? if (ENCLOSING_CLASS_HAS_FINALIZER.matches(enclosingMethodTree, state)) { return NO_MATCH; } return buildDescription(tree).build(); } }
private ExpressionType isGreaterThanEqualToZero(BinaryTree tree) { ExpressionTree literalOperand; ExpressionType returnType; switch (tree.getKind()) { case GREATER_THAN_EQUAL: literalOperand = tree.getRightOperand(); returnType = ExpressionType.GREATER_THAN_EQUAL; break; case LESS_THAN_EQUAL: literalOperand = tree.getLeftOperand(); returnType = ExpressionType.LESS_THAN_EQUAL; break; default: return ExpressionType.MISMATCH; } if (literalOperand.getKind() != Kind.INT_LITERAL) { return ExpressionType.MISMATCH; } if (!((LiteralTree) literalOperand).getValue().equals(0)) { return ExpressionType.MISMATCH; } return returnType; } }
@Override public Boolean visitBlock(BlockTree node, VisitorState state) { if (inBoxedVoidReturningMethod) { // Must have exactly 2 statements if (node.getStatements().size() != 2) { return false; } // Where the first one is a call to the methodToCall if (!node.getStatements().get(0).accept(this, state)) { return false; } // And the second one is "return null;" if (node.getStatements().get(1) instanceof ReturnTree) { ReturnTree returnTree = (ReturnTree) node.getStatements().get(1); if (returnTree.getExpression() instanceof LiteralTree) { Object returnValue = ((LiteralTree) returnTree.getExpression()).getValue(); return returnValue == null; } } return false; } else { return node.getStatements().size() == 1 && Iterables.getOnlyElement(node.getStatements()).accept(this, state); } }
@Override public boolean matches(BinaryTree tree, VisitorState state) { Type leftType = ((JCTree) tree.getLeftOperand()).type; Types types = state.getTypes(); Symtab symtab = state.getSymtab(); if (!(types.isSameType(leftType, symtab.intType)) && !(types.isSameType(leftType, symtab.byteType)) && !(types.isSameType(leftType, symtab.shortType)) && !(types.isSameType(leftType, symtab.charType))) { return false; } ExpressionTree rightOperand = tree.getRightOperand(); if (rightOperand instanceof LiteralTree) { Object rightValue = ((LiteralTree) rightOperand).getValue(); if (rightValue instanceof Number) { int intValue = ((Number) rightValue).intValue(); return intValue < 0 || intValue > 31; } } return false; } };
@Override public Description matchBinary(BinaryTree tree, VisitorState state) { if (!BINARY_TREE_MATCHER.matches(tree, state)) { return Description.NO_MATCH; } /* * For shift amounts in [32, 63], cast the left operand to long. Otherwise change the shift * amount to whatever would actually be used. */ int intValue = ((Number) ((LiteralTree) tree.getRightOperand()).getValue()).intValue(); Fix fix; if (intValue >= 32 && intValue <= 63) { if (tree.getLeftOperand().getKind() == Kind.INT_LITERAL) { fix = SuggestedFix.postfixWith(tree.getLeftOperand(), "L"); } else { fix = SuggestedFix.prefixWith(tree, "(long) "); } } else { // This is the equivalent shift distance according to JLS 15.19. String actualShiftDistance = Integer.toString(intValue & 0x1f); fix = SuggestedFix.replace(tree.getRightOperand(), actualShiftDistance); } return describeMatch(tree, fix); } }
@Override public Description matchNewClass(NewClassTree tree, VisitorState state) { if (ASTHelpers.isSameType( state.getSymtab().stringBuilderType, ASTHelpers.getType(tree.getIdentifier()), state) && tree.getArguments().size() == 1) { ExpressionTree argument = tree.getArguments().get(0); Type type = ((JCTree) argument).type; if (type.getKind() == TypeKind.CHAR) { if (argument.getKind() == Kind.CHAR_LITERAL) { char ch = (Character) ((LiteralTree) argument).getValue(); return describeMatch( tree, SuggestedFix.replace(argument, "\"" + Convert.quote(Character.toString(ch)) + "\"")); } else { return describeMatch( tree, SuggestedFix.replace( tree, "new StringBuilder().append(" + state.getSourceForNode((JCTree) argument) + ")")); } } } return Description.NO_MATCH; } }
@Override public Description matchLiteral(LiteralTree tree, VisitorState state) { Object value = tree.getValue(); if (!(value instanceof String)) { return NO_MATCH; } if (!missingFormatArgs((String) value)) { return NO_MATCH; } Tree parent = state.getPath().getParentPath().getLeaf(); if (LIKELY_MISTAKE_METHOD_CALL.matches(parent, state)) { // If someone has added new API methods to a subtype of the commonly-misused classes, we can // check to see if they made it @FormatMethod and the format-string slots in correctly. if (parent.getKind() == Kind.METHOD_INVOCATION && literalIsFormatMethodArg(tree, (MethodInvocationTree) parent, state)) { return NO_MATCH; } return describeMatch(tree); } return NO_MATCH; }
private Description matchDivZero(Tree tree, ExpressionTree operand, VisitorState state) { if (!anyOf(kindIs(Kind.DIVIDE), kindIs(Kind.DIVIDE_ASSIGNMENT)).matches(tree, state)) { return Description.NO_MATCH; } if (!kindIs(Kind.INT_LITERAL).matches(operand, state)) { return Description.NO_MATCH; } LiteralTree rightOperand = (LiteralTree) operand; if (((Integer) rightOperand.getValue()) != 0) { return Description.NO_MATCH; } // Find and replace enclosing Statement. StatementTree enclosingStmt = ASTHelpers.findEnclosingNode(state.getPath(), StatementTree.class); return (enclosingStmt != null) ? describeMatch( tree, SuggestedFix.replace(enclosingStmt, "throw new ArithmeticException(\"/ by zero\");")) : describeMatch(tree); } }