@Override public Boolean visitTypeCast(TypeCastTree tree, Void unused) { return scan(tree.getExpression(), null); }
@Override public boolean matches(TypeCastTree t, VisitorState state) { return typeMatcher.matches(t.getType(), state) && expressionMatcher.matches(t.getExpression(), state); } };
/** * Unwraps expressions like `(Foo) foo` or `((Foo) foo)` to return the VarSymbol of `foo`, or * null if the expression wasn't of this form. */ @Nullable private VarSymbol findVariable(Tree tree) { while (tree != null) { switch (tree.getKind()) { case TYPE_CAST: tree = ((TypeCastTree) tree).getExpression(); break; case PARENTHESIZED: tree = ((ParenthesizedTree) tree).getExpression(); break; case IDENTIFIER: Symbol symbol = getSymbol(tree); return symbol instanceof VarSymbol ? (VarSymbol) symbol : null; default: return null; } } return null; } }.scan(state.getPath(), null);
@Override public Number visitTypeCast(TypeCastTree node, Void p) { Number value = node.getExpression().accept(this, null); if (value == null) { return null; } if (!(node.getType() instanceof PrimitiveTypeTree)) { return null; } TypeKind kind = ((PrimitiveTypeTree) node.getType()).getPrimitiveTypeKind(); return cast(kind, value); }
@Override public UTypeCast visitTypeCast(TypeCastTree tree, Void v) { return UTypeCast.create(templateType(tree.getType()), template(tree.getExpression())); }
@Override public Description matchTypeCast(TypeCastTree typeCastTree, VisitorState visitorState) { CastingMatcher castingMatcher = new CastingMatcher(); if (!(typeCastTree.getExpression() instanceof IdentifierTree || typeCastTree.getExpression() instanceof ArrayAccessTree)) { return Description.NO_MATCH; } if (castingMatcher.matches(typeCastTree, visitorState)) { return buildDescription(typeCastTree) .addFix( SuggestedFix.replace( castingMatcher.nodeToReplace, visitorState.getSourceForNode(typeCastTree.getType()))) .build(); } return Description.NO_MATCH; }
@Override public Choice<State<JCTypeCast>> visitTypeCast(final TypeCastTree node, State<?> state) { return chooseSubtrees( state, s -> unifyExpression(node.getExpression(), s), expr -> maker().TypeCast((JCTree) node.getType(), expr)); }
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (!MATCHER.matches(tree, state)) { return NO_MATCH; } Tree parent = state.getPath().getParentPath().getLeaf(); if (!(parent instanceof TypeCastTree)) { return NO_MATCH; } if (!((TypeCastTree) parent).getExpression().equals(tree)) { return NO_MATCH; } Type type = ASTHelpers.getType(parent); if (type == null || !INTEGRAL.contains(type.getKind())) { return NO_MATCH; } return describeMatch(tree); } }
private static boolean matchesThis(ExpressionTree tree) { ExpressionTree receiver = getReceiver(tree); if (receiver == null) { return true; } while (!(receiver instanceof IdentifierTree)) { if (receiver instanceof ParenthesizedTree) { receiver = ((ParenthesizedTree) receiver).getExpression(); } else if (receiver instanceof TypeCastTree) { receiver = ((TypeCastTree) receiver).getExpression(); } else { return false; } } Symbol symbol = getSymbol(receiver); return symbol != null && symbol.getSimpleName().contentEquals("this"); }
@Override public Choice<Unifier> visitTypeCast(TypeCastTree cast, Unifier unifier) { return getType() .unify(cast.getType(), unifier) .thenChoose(unifications(getExpression(), cast.getExpression())); }
@Override public Void visitTypeCast(TypeCastTree node, Void unused) { ExpressionTree expression = node.getExpression(); if (!methodInvoked && expression.getKind() == Kind.IDENTIFIER && parameter.equals(getSymbol(expression)) && checkedTypes.stream().noneMatch(t -> isSubtype(t, getType(node.getType()), state))) { StatementTree enclosingStatement = findEnclosingNode(getCurrentPath(), StatementTree.class); state.reportMatch( describeMatch( node, SuggestedFix.prefixWith( enclosingStatement, String.format( INSTANCEOF_CHECK, state.getSourceForNode(expression), state.getSourceForNode(node.getType()))))); } return super.visitTypeCast(node, null); } }.scan(state.getPath(), null);
/** * strip out enclosing parentheses and type casts. * * @param expr * @return */ private static ExpressionTree stripParensAndCasts(ExpressionTree expr) { boolean someChange = true; while (someChange) { someChange = false; if (expr.getKind().equals(PARENTHESIZED)) { expr = ((ParenthesizedTree) expr).getExpression(); someChange = true; } if (expr.getKind().equals(TYPE_CAST)) { expr = ((TypeCastTree) expr).getExpression(); someChange = true; } } return expr; }
Type operandType = ASTHelpers.getType(tree.getExpression()); if (castType == null || operandType == null) { return NO_MATCH; return NO_MATCH; if (BLACKLIST.matches(tree.getExpression(), state)) { return NO_MATCH; if (POW.matches(tree.getExpression(), state)) { MethodInvocationTree pow = (MethodInvocationTree) tree.getExpression(); if (pow.getArguments().stream() .map(ASTHelpers::getType) .addFix( SuggestedFix.builder() .prefixWith(tree.getExpression(), "(") .postfixWith(enclosing, ")") .build())
/** * Matches if this is a narrowing integral cast between signed types where the expression is a * subtract. */ private boolean matches(TypeCastTree tree, VisitorState state) { Type treeType = ASTHelpers.getType(tree.getType()); // If the cast isn't narrowing to an int then don't implicate it in the bug pattern. if (treeType.getTag() != TypeTag.INT) { return false; } // The expression should be a subtract but remove parentheses. ExpressionTree expression = ASTHelpers.stripParentheses(tree.getExpression()); if (expression.getKind() != Kind.MINUS) { return false; } // Ensure the expression type is wider and signed (ie a long) than the cast type ignoring // boxing. Type expressionType = getTypeOfSubtract((BinaryTree) expression, state); TypeTag expressionTypeTag = state.getTypes().unboxedTypeOrType(expressionType).getTag(); return (expressionTypeTag == TypeTag.LONG); }
TreeScannerInstanceOfWrongType treeScannerInstanceOfWrongType = new TreeScannerInstanceOfWrongType(state); treeScannerInstanceOfWrongType.scan(expressionTree, ((TypeCastTree) tree).getExpression()); types.erasure(ASTHelpers.getType(tree))); ExpressionTree typeCastExp = ((TypeCastTree) tree).getExpression(); boolean isSameExpression = expressionsEqual(typeCastExp, instanceOfTree.getExpression()); return isSameExpression && !isCastable;
@Override public Description matchTypeCast(TypeCastTree typeCastTree, VisitorState state) { ExpressionTree newInstanceTree = ASTHelpers.stripParentheses(typeCastTree.getExpression()); ((JCTree) typeCastTree.getExpression()).getStartPosition(), "");
BinaryTree subtract = (BinaryTree) ASTHelpers.stripParentheses(tree.getExpression()); ExpressionTree lhs = subtract.getLeftOperand(); ExpressionTree rhs = subtract.getRightOperand();
@Override public Void visitTypeCast(TypeCastTree expected, Tree actual) { Optional<TypeCastTree> other = checkTypeAndCast(expected, actual); if (!other.isPresent()) { addTypeMismatch(expected, actual); return null; } scan(expected.getType(), other.get().getType()); scan(expected.getExpression(), other.get().getExpression()); return null; }
@Override public Void visitTypeCast(TypeCastTree expected, Tree actual) { Optional<TypeCastTree> other = checkTypeAndCast(expected, actual); if (!other.isPresent()) { addTypeMismatch(expected, actual); return null; } scan(expected.getType(), other.get().getType()); scan(expected.getExpression(), other.get().getExpression()); return null; }
@Override public JExpression visitTypeCast(TypeCastTree tt, Void __) { return $b.invoke("cast") .arg(loc(tt)) .arg(visit(tt.getExpression())) .arg(erasure(tt.getType()).dotclass()) .arg(JExpr.lit(false)); }