@Override public Void visitUnary(UnaryTree tree, EnumSet<UseTypes> d) { if (tree.getExpression() instanceof IdentifierTree) { switch (tree.getKind()) { case PREFIX_INCREMENT: case PREFIX_DECREMENT: case POSTFIX_INCREMENT: case POSTFIX_DECREMENT: Set<UseTypes> useTypes = EnumSet.of(UseTypes.WRITE); if (d != null) { useTypes.addAll(d); } handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), useTypes); break; default: handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getExpression()), EnumSet.of(UseTypes.READ)); } } super.visitUnary(tree, d); return null; }
private static List<? extends TypeMirror> computeUnary(Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { UnaryTree tree = (UnaryTree) parent.getLeaf(); if (tree.getExpression() == error) { List<? extends TypeMirror> parentTypes = resolveType(types, info, parent.getParentPath(), tree, offset, null, null); if (parentTypes != null) { //may contain only "void", ignore: if (parentTypes.size() != 1) { return parentTypes; } if (parentTypes.get(0).getKind() != TypeKind.VOID) { return parentTypes; } } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.INT)); } return null; }
@Override public Void visitUnary(UnaryTree node, Void unused) { sync(node); String operatorName = operatorName(node); if (OpUtil.isPostUnaryOp(((JCTree) node).getTag())) { scan(node.getExpression(), null); splitToken(operatorName); } else { splitToken(operatorName); if (ambiguousUnaryOperator(node, operatorName)) { builder.space(); } scan(node.getExpression(), null); } return null; }
private boolean ambiguousUnaryOperator(UnaryTree node, String operatorName) { switch (node.getKind()) { case UNARY_MINUS: case UNARY_PLUS: break; default: return false; } if (!(node.getExpression() instanceof UnaryTree)) { return false; } int tag = ((JCTree) node.getExpression()).getTag(); if (OpUtil.isPostUnaryOp(tag)) { return false; } if (!operatorName(node).startsWith(operatorName)) { return false; } return true; }
@Override public Description matchMethodInvocation( MethodInvocationTree methodInvocationTree, VisitorState visitorState) { if (methodInvocationTree .getArguments() .stream() .filter(arg -> UNARY_OPERATORS.contains(arg.getKind())) .map(arg -> ASTHelpers.getSymbol(((UnaryTree) arg).getExpression())) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet() .stream() .anyMatch(e -> e.getValue() > 1)) { return describeMatch(methodInvocationTree); } return Description.NO_MATCH; }
private AnnotationMirror evaluateUnaryOperator( AnnotationMirror argAnno, String operation, Class<?> argClass, UnaryTree tree) { try { Class<?>[] argClasses = new Class<?>[] { argClass }; Method m = Operators.class.getMethod(operation, argClasses); List<?> annoValues = AnnotationUtils.getElementValueArray( argAnno, "value", argClass, true); ArrayList<Object> results = new ArrayList<Object>( annoValues.size()); for (Object val : annoValues) { results.add(m.invoke(null, new Object[] { val })); } return resultAnnotationHandler(m.getReturnType(), results); } catch (ReflectiveOperationException e) { checker.report(Result .warning("operator.unary.evaluation.failed", operation, argClass), tree); return null; } }
@Override public boolean match(TreePath path) { TreePath prev = path, p = path.getParentPath(); while (p != null) { if (p.getLeaf().getKind() == Tree.Kind.IF) { IfTree ifTree = (IfTree)p.getLeaf(); ExpressionTree cond = TreeUtils.skipParens(ifTree.getCondition()); if (ifTree.getThenStatement() == prev.getLeaf() && matcher.match(new TreePath(p, cond))) return true; if (cond.getKind() == Tree.Kind.LOGICAL_COMPLEMENT && matcher.match(new TreePath(p, ((UnaryTree)cond).getExpression()))) return true; } prev = p; p = p.getParentPath(); } return false; }
@Override public ExpressionModel visitUnary(UnaryTree node, VisitContext p) { ExpressionModel expression = scan(node.getExpression(), p); switch (node.getKind()) { case POSTFIX_INCREMENT: // Note we don't handle the case (3++) that is not legal in JavaScript return expression.onPostFixIncrement(); case POSTFIX_DECREMENT: // Note we don't handle the case (3--) that is not legal in JavaScript return expression.onPostFixDecrement(); case PREFIX_INCREMENT: // Note we don't handle the case (++3) that is not legal in JavaScript return expression.onPrefixIncrement(); case PREFIX_DECREMENT: // Note we don't handle the case (--3) that is not legal in JavaScript return expression.onPrefixDecrement(); case LOGICAL_COMPLEMENT: return expression.onLogicalComplement(); case UNARY_MINUS: return expression.unaryMinus(); case UNARY_PLUS: return expression.unaryPlus(); default: throw new UnsupportedOperationException("Unary operator " + node.getKind().name() + " not yet implemented"); } }
@Override public Tree visitUnary(UnaryTree tree, Void p) { UnaryTree n = make.Unary(tree.getKind(), tree.getExpression()); model.setType(n, model.getType(tree)); comments.copyComments(tree, n); model.setPos(n, model.getPos(tree)); return n; }
public Boolean visitUnary(UnaryTree node, TreePath p) { if (p == null) return super.visitUnary(node, p); UnaryTree t = (UnaryTree) p.getLeaf(); return scan(node.getExpression(), t.getExpression(), p); }
@Override public Number visitUnary(UnaryTree node, Void p) { Number op = scan(node.getExpression(), p); if (op != null) { Number result = null; switch (node.getKind()) { case UNARY_MINUS: if (op instanceof Double) { result = -op.doubleValue(); } else if (op instanceof Float) { result = -op.floatValue(); } else if (op instanceof Long) { result = -op.longValue(); } else if (op instanceof Integer) { result = -op.intValue(); } else { throw new IllegalStateException("op=" + op.getClass()); } break; case UNARY_PLUS: result = op; break; } if (result != null) { rewrite(node, make.Literal(result)); return result; } } return super.visitUnary(node, p); }
@Override public Object visitUnary(UnaryTree node, Object p) { if (node.getKind() == Tree.Kind.LOGICAL_COMPLEMENT) { negationsCount++; } return super.visitUnary(node, p); }
@Override public Object visitUnary(UnaryTree node, Object p) { boolean b = isCorrectType(node); currentMatches = b; Object o = super.visitUnary(node, p); increment(node, b); return o; }
@Override public Void visitUnary(UnaryTree tree, List<Node> d) { List<Node> below = new ArrayList<Node>(); addCorrespondingType(below); addCorrespondingComments(below); super.visitUnary(tree, below); d.add(new TreeNode(info, getCurrentPath(), below)); return null; }
private static ProspectiveOperation handlePreOrPostFixReducer(ExpressionTree expr, WorkingCopy workingCopy, TreeMaker tm, OperationType operationType, PreconditionsChecker precond, List<ProspectiveOperation> ls, ProspectiveOperation redOp) { ExpressionTree reducing = ((UnaryTree) expr).getExpression(); ProspectiveOperation map; if (isInteger(reducing, workingCopy) || isLong(reducing, workingCopy) || isChar(reducing, workingCopy)) { map = new ProspectiveOperation(tm.Literal(1), operationType.MAP, precond.getInnerVariables(), workingCopy, precond.getVarToName()); } else { map = new ProspectiveOperation(tm.Literal(1.), operationType.MAP, precond.getInnerVariables(), workingCopy, precond.getVarToName()); } ls.add(map); redOp = new ProspectiveOperation(expr, operationType, precond.getInnerVariables(), workingCopy, precond.getVarToName()); redOp.reducingVariable = reducing; return redOp; }
private ExpressionTree makeParenthesis(ExpressionTree arg) { Class c = arg.getKind().asInterface(); // if the original append argument was an expression, surround it in parenthesis, to get the same toString effect if (c == BinaryTree.class || c == UnaryTree.class || c == CompoundAssignmentTree.class || c == AssignmentTree.class || c == ConditionalExpressionTree.class) { return mk.Parenthesized(arg); } else { return arg; } }
@Override public Object visitUnary(UnaryTree node, Object p) { switch (node.getKind()) { case POSTFIX_DECREMENT: case POSTFIX_INCREMENT: case PREFIX_DECREMENT: case PREFIX_INCREMENT: break; default: return super.visitUnary(node, p); } checkVariableAccess(node.getExpression(), node); return super.visitUnary(node, p); }
@Hint(displayName = "#DN_org.netbeans.modules.java.hints.AssignmentIssues.assignmentToMethodParam", description = "#DESC_org.netbeans.modules.java.hints.AssignmentIssues.assignmentToMethodParam", category = "assignment_issues", enabled = false, suppressWarnings = "AssignmentToMethodParameter", options=Options.QUERY) //NOI18N @TriggerTreeKind({Kind.ASSIGNMENT, Kind.AND_ASSIGNMENT, Kind.DIVIDE_ASSIGNMENT, Kind.LEFT_SHIFT_ASSIGNMENT, Kind.MINUS_ASSIGNMENT, Kind.MULTIPLY_ASSIGNMENT, Kind.OR_ASSIGNMENT, Kind.PLUS_ASSIGNMENT, Kind.REMAINDER_ASSIGNMENT, Kind.RIGHT_SHIFT_ASSIGNMENT, Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT, Kind.XOR_ASSIGNMENT, Kind.PREFIX_INCREMENT, Kind.PREFIX_DECREMENT, Kind.POSTFIX_INCREMENT, Kind.POSTFIX_DECREMENT}) public static ErrorDescription assignmentToMethodParam(HintContext context) { final TreePath path = context.getPath(); Element element = null; switch (path.getLeaf().getKind()) { case ASSIGNMENT: element = context.getInfo().getTrees().getElement(TreePath.getPath(path, ((AssignmentTree) path.getLeaf()).getVariable())); break; case PREFIX_INCREMENT: case PREFIX_DECREMENT: case POSTFIX_INCREMENT: case POSTFIX_DECREMENT: element = context.getInfo().getTrees().getElement(TreePath.getPath(path, ((UnaryTree) path.getLeaf()).getExpression())); break; default: element = context.getInfo().getTrees().getElement(TreePath.getPath(path, ((CompoundAssignmentTree) path.getLeaf()).getVariable())); } if (element != null && element.getKind() == ElementKind.PARAMETER) { return ErrorDescriptionFactory.forTree(context, path, NbBundle.getMessage(AssignmentIssues.class, "MSG_AssignmentToMethodParam", element.getSimpleName())); //NOI18N } return null; }
@Override public Void visitUnary(UnaryTree node, List<TreePath> p) { switch (node.getKind()) { case PREFIX_INCREMENT: case PREFIX_DECREMENT: case POSTFIX_INCREMENT: case POSTFIX_DECREMENT: if (param == trees.getElement(TreePath.getPath(getCurrentPath(), node.getExpression()))) { p.add(getCurrentPath()); return null; } } return super.visitUnary(node, p); }
@Override public List<? extends TypeMirror> visitUnary(UnaryTree node, Object p) { switch (node.getKind()) { case POSTFIX_DECREMENT: case POSTFIX_INCREMENT: case PREFIX_DECREMENT: case PREFIX_INCREMENT: // the incremented value is a l-value, it's type cannot be changed. We shouldn't be at this code path at all return null; case PLUS: case BITWISE_COMPLEMENT: scanParent(); break; case LOGICAL_COMPLEMENT: return booleanType(); } return null; }
@Override public Void visitUnary(UnaryTree tree, VisitorState visitorState) { VisitorState state = visitorState.withPath(getCurrentPath()); for (UnaryTreeMatcher matcher : unaryMatchers) { if (!isSuppressed(matcher, state)) { try { reportMatch(matcher.matchUnary(tree, state), tree, state); } catch (Throwable t) { handleError(matcher, t); } } } return super.visitUnary(tree, state); }
@Override @Nullable public Choice<Unifier> visitUnary(UnaryTree unary, @Nullable Unifier unifier) { return Choice.condition(getKind().equals(unary.getKind()), unifier) .thenChoose( unifications(getExpression(), ASTHelpers.stripParentheses(unary.getExpression()))); }
@Override public Choice<State<JCUnary>> visitUnary(UnaryTree node, State<?> state) { final Tag tag = ((JCUnary) node).getTag(); return chooseSubtrees( state, s -> unifyExpression(node.getExpression(), s), expr -> maker().Unary(tag, expr)) .condition( s -> !MUTATING_UNARY_TAGS.contains(tag) || !(s.result().getExpression() instanceof PlaceholderParamIdent)); }
@Override public Description matchMethodInvocation( MethodInvocationTree methodInvocationTree, VisitorState visitorState) { if (GOOGLE_OPTIONAL_PRESENT.matches(methodInvocationTree, visitorState) || OPTIONAL_PRESENT.matches(methodInvocationTree, visitorState)) { Symbol optionalVar = ASTHelpers.getSymbol(ASTHelpers.getReceiver(methodInvocationTree)); // using an iterator to make sure that only !optional.isPresent() matches and not // !(optional.isPresent() || foo == 7) Iterator<Tree> iter = visitorState.getPath().iterator(); iter.next(); Tree upTree = iter.next(); if (!(upTree instanceof UnaryTree) || upTree.getKind() != Kind.LOGICAL_COMPLEMENT) { return Description.NO_MATCH; } IfTree ifTree = null; ifTree = possibleIf(ifTree, upTree, iter); if (ifTree == null) { return Description.NO_MATCH; } TreeScannerInside treeScannerInside = new TreeScannerInside(); treeScannerInside.scan(ifTree.getThenStatement(), optionalVar); if (treeScannerInside.hasGet && !treeScannerInside.hasAssignment) { return describeMatch(methodInvocationTree); } } return Description.NO_MATCH; }
@Override public Number visitUnary(UnaryTree node, Void p) { Number value = node.getExpression().accept(this, null); if (value == null) { return value; } if (value instanceof Long) { return unop(node.getKind(), value.longValue()); } else { return unop(node.getKind(), value.intValue()); } }
@Override public Description matchForLoop(ForLoopTree forLoopTree, VisitorState visitorState) { List<? extends ExpressionStatementTree> updates = forLoopTree.getUpdate(); // keep track of all the symbols that are updated in the for loop header final Set<Symbol> incrementedSymbols = updates .stream() .filter(expStateTree -> expStateTree.getExpression() instanceof UnaryTree) .map( expStateTree -> ASTHelpers.getSymbol( ((UnaryTree) expStateTree.getExpression()).getExpression())) .collect(Collectors.toCollection(HashSet::new)); // track if they are updated in the body without a conditional surrounding them StatementTree body = forLoopTree.getStatement(); List<? extends StatementTree> statementTrees = body instanceof BlockTree ? ((BlockTree) body).getStatements() : ImmutableList.of(body); for (StatementTree s : statementTrees) { if (!CONDITIONALS.contains(s.getKind())) { Optional<Symbol> opSymbol = returnUnarySym(s); if (opSymbol.isPresent() && incrementedSymbols.contains(opSymbol.get())) { // both ++ and -- return describeMatch(forLoopTree); } } } return Description.NO_MATCH; }
private static Optional<Symbol> returnUnarySym(StatementTree s) { if (s instanceof ExpressionStatementTree) { if (((ExpressionStatementTree) s).getExpression() instanceof UnaryTree) { UnaryTree unaryTree = (UnaryTree) ((ExpressionStatementTree) s).getExpression(); return Optional.ofNullable(ASTHelpers.getSymbol(unaryTree.getExpression())); } } return Optional.empty(); }
@Override public boolean matches(ExpressionTree tree, VisitorState state) { if (tree.getKind() == Kind.UNARY_PLUS || tree.getKind() == Kind.UNARY_MINUS) { tree = ((UnaryTree) tree).getExpression(); } return tree.getKind() == Kind.DOUBLE_LITERAL; }
@Override public Void visitUnary(UnaryTree tree, ExpressionTree expr) { if (tree.getKind().equals(Kind.LOGICAL_COMPLEMENT)) { notApplicable = true; } return super.visitUnary(tree, expr); }
/** Extracts the expression from a UnaryTree and applies a matcher to it. */ private static Matcher<UnaryTree> expressionFromUnaryTree( final Matcher<ExpressionTree> exprMatcher) { return new Matcher<UnaryTree>() { @Override public boolean matches(UnaryTree tree, VisitorState state) { return exprMatcher.matches(tree.getExpression(), state); } }; }
@Override public Description matchUnary(UnaryTree tree, VisitorState state) { if (unaryIncrementDecrementMatcher.matches(tree, state)) { return describeMatch(tree); } return Description.NO_MATCH; }
@Override public Void visitUnary(UnaryTree node, Void unused) { switch (node.getKind()) { case PREFIX_DECREMENT: case PREFIX_INCREMENT: case POSTFIX_DECREMENT: case POSTFIX_INCREMENT: recordWrite(node.getExpression()); break; default: break; } return super.visitUnary(node, null); }
@Override public Void visitUnary(UnaryTree tree, Void unused) { switch (tree.getKind()) { case POSTFIX_INCREMENT: case PREFIX_INCREMENT: case POSTFIX_DECREMENT: case PREFIX_DECREMENT: check(tree.getExpression()); break; default: // fall out } return super.visitUnary(tree, unused); }
@Override public boolean matches(UnaryTree tree, VisitorState state) { return allOf( not(withinThrowOrAnnotation), enclosingMethod(noAllocationMethodMatcher), anyOf( kindIs(POSTFIX_DECREMENT), kindIs(POSTFIX_INCREMENT), kindIs(PREFIX_DECREMENT), kindIs(PREFIX_INCREMENT))) .matches(tree, state) && not(isPrimitiveType()).matches(tree, state); }
@Override public Description matchUnary(UnaryTree tree, VisitorState state) { if (!boxingUnary.matches(tree, state)) { return Description.NO_MATCH; } return buildDescription(tree) .setMessage( "Pre- and post- increment/decrement operations on a non-primitive variable or" + " array element will autobox the result, which " + COMMON_MESSAGE_SUFFIX) .build(); }
/** * Extracts the expression from a UnaryTree and applies a matcher to it. */ private static Matcher<UnaryTree> expressionFromUnaryTree( final Matcher <ExpressionTree> exprMatcher) { return new Matcher<UnaryTree>() { @Override public boolean matches(UnaryTree tree, VisitorState state) { return exprMatcher.matches(tree.getExpression(), state); } }; }
@Override public Description matchUnary(UnaryTree tree, VisitorState state) { if (unaryIncrementDecrementMatcher.matches(tree, state)) { return describeMatch(tree, Fix.NO_FIX); } return Description.NO_MATCH; }
/** * Performs assignability check using * {@link #checkAssignability(AnnotatedTypeMirror, Tree)}. */ @Override public Void visitUnary(UnaryTree node, Void p) { if ((node.getKind() == Tree.Kind.PREFIX_DECREMENT) || (node.getKind() == Tree.Kind.PREFIX_INCREMENT) || (node.getKind() == Tree.Kind.POSTFIX_DECREMENT) || (node.getKind() == Tree.Kind.POSTFIX_INCREMENT)) { AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(node.getExpression()); checkAssignability(type, node.getExpression()); } return super.visitUnary(node, p); }
/** * NOTE: Because of the way CFGBuilder handles increment and decrement, * the value of any variable with being incremented or decrement will be * at least @IntVal (or higher if original type was higher). Thus, there * will be an error if you try to assign an incremented value to a * CharVal, ByteVal, ShortVal, or FloatVal, even if that is what the * incremented value originally was. * * @param tree * @param type */ @Override public Void visitUnary(UnaryTree tree, AnnotatedTypeMirror type) { super.visitUnary(tree, type); if (isClassCovered(type)) { Tree.Kind operation = tree.getKind(); String finalTypeString = type.getUnderlyingType().toString(); AnnotatedTypeMirror argType = getAnnotatedType(tree .getExpression()); if (!nonValueAnno(argType)) { Class<?> argClass = getTypeValueClass(finalTypeString, tree); handleCast(tree.getExpression(), finalTypeString, argType); AnnotationMirror argAnno = getValueAnnotation(argType); AnnotationMirror newAnno = evaluateUnaryOperator(argAnno, operation.toString(), argClass, tree); if (newAnno != null) { type.replaceAnnotation(newAnno); return null; } } type.replaceAnnotation(UNKNOWNVAL); } return null; }