@Override public Void visitCompoundAssignment(CompoundAssignmentTree tree, EnumSet<UseTypes> d) { Set<UseTypes> useTypes = EnumSet.of(UseTypes.WRITE); if (d != null) { useTypes.addAll(d); } handlePossibleIdentifier(new TreePath(getCurrentPath(), tree.getVariable()), useTypes); Tree expr = tree.getExpression(); if (expr instanceof IdentifierTree) { TreePath tp = new TreePath(getCurrentPath(), expr); handlePossibleIdentifier(tp, EnumSet.of(UseTypes.READ)); } scan(tree.getVariable(), EnumSet.of(UseTypes.WRITE)); scan(tree.getExpression(), EnumSet.of(UseTypes.READ)); return null; }
/** * Returns the string name of an operator, including assignment and compound assignment. */ static String operatorName(ExpressionTree expression) { // JCTree.Tag tag = ((JCTree) expression).getTag(); // if (tag == JCTree.Tag.ASSIGN) { // return "="; // } // boolean assignOp = expression instanceof CompoundAssignmentTree; // if (assignOp) { // tag = tag.noAssignOp(); // } int tag = ((JCTree) expression).getTag(); if (tag == JCTree.ASSIGN) { return "="; } boolean assignOp = expression instanceof CompoundAssignmentTree; if (assignOp) { // tag = tag.noAssignOp(); // TODO: 22-Jul-17 ????? } String name = new Pretty(/*writer*/ null, /*sourceOutput*/ true).operatorName(tag); return assignOp ? name + "=" : name; }
/** * Matchers when a string concatenates-and-assigns an array. */ @Override public Description matchCompoundAssignment(CompoundAssignmentTree t, VisitorState state) { if (!assignmentMatcher.matches(t, state)) { return Description.NO_MATCH; } /* * Replace instances of implicit array toString() calls due to string * concatenation-and-assignment with Arrays.toString(array). Also adds * the necessary import statement for java.util.Arrays. */ String receiver = t.getVariable().toString(); String expression = t.getExpression().toString(); Fix fix = new SuggestedFix() .replace(t, receiver + " += Arrays.toString(" + expression + ")") .addImport("java.util.Arrays"); return describeMatch(t, fix); }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) { ExpressionTree var = node.getVariable(); ExpressionTree expr = node.getExpression(); AnnotatedTypeMirror varType = atypeFactory.getAnnotatedType(var); AnnotatedTypeMirror exprType = atypeFactory.getAnnotatedType(expr); Kind kind = node.getKind(); if ( (kind == Kind.PLUS_ASSIGNMENT || kind == Kind.MINUS_ASSIGNMENT)) { if (!atypeFactory.getTypeHierarchy().isSubtype(exprType, varType)) { checker.report(Result.failure("compound.assignment.type.incompatible", varType, exprType), node); } } else if (exprType.getAnnotation(UnknownUnits.class) == null) { // Only allow mul/div with unqualified units checker.report(Result.failure("compound.assignment.type.incompatible", varType, exprType), node); } return null; // super.visitCompoundAssignment(node, p); }
@Override public Tree visitCompoundAssignment(CompoundAssignmentTree tree, Void p) { CompoundAssignmentTree n = make.CompoundAssignment(tree.getKind(), tree.getVariable(), tree.getExpression()); model.setType(n, model.getType(tree)); comments.copyComments(tree, n); model.setPos(n, model.getPos(tree)); return n; }
public Boolean visitCompoundAssignment(CompoundAssignmentTree node, TreePath p) { if (p == null) { super.visitCompoundAssignment(node, p); return false; } CompoundAssignmentTree bt = (CompoundAssignmentTree) p.getLeaf(); boolean result = scan(node.getExpression(), bt.getExpression(), p); return result && scan(node.getVariable(), bt.getVariable(), p); }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree tree, List<Node> d) { List<Node> below = new ArrayList<Node>(); addCorrespondingType(below); addCorrespondingComments(below); super.visitCompoundAssignment(tree, below); d.add(new TreeNode(info, getCurrentPath(), below)); return null; }
private static ProspectiveOperation handleCompoundAssignementReducer(TreeMaker tm, ExpressionTree expr, OperationType operationType, PreconditionsChecker precond, WorkingCopy workingCopy, List<ProspectiveOperation> ls, ProspectiveOperation redOp) { //this variable will be removed at a later stage. VariableTree var = tm.Variable(tm.Modifiers(new HashSet<Modifier>()), "dummyVar18912", tm.Type("Object"), ((CompoundAssignmentTree) expr).getExpression()); ProspectiveOperation map = new ProspectiveOperation(var, operationType.MAP, precond.getInnerVariables(), workingCopy, precond.getVarToName()); map.getAvailableVariables().add(var.getName()); ls.add(map); redOp = new ProspectiveOperation(expr, operationType, precond.getInnerVariables(), workingCopy, precond.getVarToName()); redOp.neededVariables = new HashSet<Name>(); redOp.neededVariables.add(var.getName()); redOp.reducingVariable = ((CompoundAssignmentTree) expr).getVariable(); 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; } }
@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 visitCompoundAssignment(CompoundAssignmentTree node, List<TreePath> p) { if (param == trees.getElement(TreePath.getPath(getCurrentPath(), node.getVariable()))) { p.add(getCurrentPath()); return null; } return super.visitCompoundAssignment(node, p); }
/** * Compound assignment expects the assigned-to variable's type. */ @Override public List<? extends TypeMirror> visitCompoundAssignment(CompoundAssignmentTree node, Object p) { if (theExpression == null) { initExpression(new TreePath(getCurrentPath(), node.getExpression())); } return Collections.singletonList(info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), node.getVariable()))); }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree node, Void unused) { sync(node); builder.open(plusFour); scan(node.getVariable(), null); builder.space(); splitToken(operatorName(node)); builder.breakOp(" "); scan(node.getExpression(), null); builder.close(); return null; }
@Override @Nullable public Unifier visitCompoundAssignment( CompoundAssignmentTree assignOp, @Nullable Unifier unifier) { unifier = (getKind() == assignOp.getKind()) ? unifier : null; unifier = getVariable().unify(assignOp.getVariable(), unifier); return getExpression().unify(assignOp.getExpression(), unifier); }
@Override public boolean matches(CompoundAssignmentTree compoundAssignmentTree, VisitorState state) { if (!operators.contains(compoundAssignmentTree.getKind())) { return false; } return receiverMatcher.matches(compoundAssignmentTree.getVariable(), state) && expressionMatcher.matches(compoundAssignmentTree.getExpression(), state); }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree tree, VisitorState visitorState) { VisitorState state = visitorState.withPath(getCurrentPath()); for (CompoundAssignmentTreeMatcher matcher : compoundAssignmentMatchers) { if (!isSuppressed(matcher, state)) { try { reportMatch(matcher.matchCompoundAssignment(tree, state), tree, state); } catch (Throwable t) { handleError(matcher, t); } } } return super.visitCompoundAssignment(tree, state); }
@Override public Choice<State<JCAssignOp>> visitCompoundAssignment( final CompoundAssignmentTree node, State<?> state) { return chooseSubtrees( state, s -> unifyExpression(node.getVariable(), s), s -> unifyExpression(node.getExpression(), s), (var, expr) -> maker().Assignop(((JCAssignOp) node).getTag(), var, expr)) .condition(assignOp -> !(assignOp.result().getVariable() instanceof PlaceholderParamIdent)); }
@Override public Description matchCompoundAssignment(CompoundAssignmentTree tree, VisitorState state) { String message = identifyBadCast( getType(tree.getVariable()), getType(tree.getExpression()), state.getTypes()); if (message == null) { return Description.NO_MATCH; } Optional<Fix> fix = rewriteCompoundAssignment(tree, state); if (!fix.isPresent()) { return Description.NO_MATCH; } return buildDescription(tree).addFix(fix.get()).setMessage(message).build(); }
/** Desugars a compound assignment, making the cast explicit. */ private static Optional<Fix> rewriteCompoundAssignment( CompoundAssignmentTree tree, VisitorState state) { CharSequence var = state.getSourceForNode(tree.getVariable()); CharSequence expr = state.getSourceForNode(tree.getExpression()); if (var == null || expr == null) { return Optional.absent(); } switch (tree.getKind()) { case RIGHT_SHIFT_ASSIGNMENT: // narrowing the result of a signed right shift does not lose information return Optional.absent(); default: break; } Kind regularAssignmentKind = regularAssignmentFromCompound(tree.getKind()); String op = assignmentToString(regularAssignmentKind); // Add parens to the rhs if necessary to preserve the current precedence // e.g. 's -= 1 - 2' -> 's = s - (1 - 2)' if (tree.getExpression() instanceof JCBinary) { Kind rhsKind = tree.getExpression().getKind(); if (!OperatorPrecedence.from(rhsKind) .isHigher(OperatorPrecedence.from(regularAssignmentKind))) { expr = String.format("(%s)", expr); } } // e.g. 's *= 42' -> 's = (short) (s * 42)' String castType = getType(tree.getVariable()).toString(); String replacement = String.format("%s = (%s) (%s %s %s)", var, castType, var, op, expr); return Optional.of(SuggestedFix.replace(tree, replacement)); }
/** Extracts the variable from a CompoundAssignmentTree and applies a matcher to it. */ private static Matcher<CompoundAssignmentTree> variableFromCompoundAssignmentTree( final Matcher<ExpressionTree> exprMatcher) { return new Matcher<CompoundAssignmentTree>() { @Override public boolean matches(CompoundAssignmentTree tree, VisitorState state) { return exprMatcher.matches(tree.getVariable(), state); } }; }
@Override public Description matchCompoundAssignment(CompoundAssignmentTree tree, VisitorState state) { if (compoundAssignmentIncrementDecrementMatcher.matches(tree, state)) { return describeMatch(tree); } return Description.NO_MATCH; }
@Override public Description matchCompoundAssignment(CompoundAssignmentTree tree, VisitorState state) { if (!compoundAssignmentMatcher.matches(tree, state)) { return Description.NO_MATCH; } return buildDescription(tree) .setMessage( "Compound assignment to a String or boxed primitive allocates a new object," + " which " + COMMON_MESSAGE_SUFFIX) .build(); }
@Override public Description matchCompoundAssignment(CompoundAssignmentTree cat, VisitorState state) { StatementTree exprStat = ASTHelpers.findEnclosingNode(state.getPath(), ExpressionStatementTree.class); assertNotNull(exprStat); if (new NextStatement<StatementTree>(Matchers.<StatementTree>anything()) .matches(exprStat, state)) { return describeMatch(cat); } return Description.NO_MATCH; }
private Scanner compoundAssignmentMatches( final boolean shouldMatch, final CompoundAssignment toMatch) { return new Scanner() { @Override public Void visitCompoundAssignment(CompoundAssignmentTree node, VisitorState visitorState) { assertTrue(node.toString(), !shouldMatch ^ toMatch.matches(node, visitorState)); return super.visitCompoundAssignment(node, visitorState); } }; }
/** * Extracts the variable from a CompoundAssignmentTree and applies a matcher to it. */ private static Matcher<CompoundAssignmentTree> variableFromCompoundAssignmentTree( final Matcher <ExpressionTree> exprMatcher) { return new Matcher<CompoundAssignmentTree>() { @Override public boolean matches(CompoundAssignmentTree tree, VisitorState state) { return exprMatcher.matches(tree.getVariable(), state); } }; }
@Override public Description matchCompoundAssignment(CompoundAssignmentTree tree, VisitorState state) { if (compoundAssignmentIncrementDecrementMatcher.matches(tree, state)) { return describeMatch(tree, Fix.NO_FIX); } return Description.NO_MATCH; }
@Override public PurityResult visitCompoundAssignment( CompoundAssignmentTree node, PurityResult p) { ExpressionTree variable = node.getVariable(); p = assignmentCheck(p, variable); PurityResult r = scan(variable, p); r = scan(node.getExpression(), r); return r; }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) { type.replaceAnnotation(NONNULL); // call super for initialization defaults return super.visitCompoundAssignment(node, type); }
/** Case 7: unboxing case: primitive operation */ @Override public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) { // ignore String concatenation if (!isString(node)) { checkForNullability(node.getVariable(), UNBOXING_OF_NULLABLE); checkForNullability(node.getExpression(), UNBOXING_OF_NULLABLE); } return super.visitCompoundAssignment(node, p); }
/** * Case 2: Also handle compound String concatenation. */ @Override public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) { if (TreeUtils.isStringCompoundConcatenation(node)) { AnnotatedTypeMirror rhs = getAnnotatedType(node.getExpression()); AnnotatedTypeMirror lhs = getAnnotatedType(node.getVariable()); if (lhs.hasAnnotation(Regex.class) && rhs.hasAnnotation(Regex.class)) { int lCount = getGroupCount(lhs.getAnnotation(Regex.class)); int rCount = getGroupCount(rhs.getAnnotation(Regex.class)); type.removeAnnotationInHierarchy(REGEX); type.addAnnotation(createRegexAnnotation(lCount + rCount)); } } return null; // super.visitCompoundAssignment(node, type); }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) { ExpressionTree var = node.getVariable(); AnnotatedTypeMirror varType = getAnnotatedType(var); type.replaceAnnotations(varType.getAnnotations()); return super.visitCompoundAssignment(node, type); }
/** * Performs assignability check using * {@link #checkAssignability(AnnotatedTypeMirror, Tree)}. */ @Override public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) { commonAssignmentCheck(node.getVariable(), node.getExpression(), "compound.assignment.type.incompatible"); return super.visitCompoundAssignment(node, p); }
@Override public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) { // TODO: should we perform default action to get trees/tree kinds/...? // defaultAction(node, type); AnnotatedTypeMirror rhs = atypeFactory.getAnnotatedType(node.getExpression()); AnnotatedTypeMirror lhs = atypeFactory.getAnnotatedType(node.getVariable()); Set<? extends AnnotationMirror> lubs = qualHierarchy.leastUpperBounds(rhs.getAnnotations(), lhs.getAnnotations()); type.addMissingAnnotations(lubs); return super.visitCompoundAssignment(node, type); }
@Override public AnnotatedTypeMirror visitCompoundAssignment( CompoundAssignmentTree node, AnnotatedTypeFactory f) { // Recurse on the type of the variable. AnnotatedTypeMirror res = visit(node.getVariable(), f); // TODO: why do we need to clear the type? res.clearAnnotations(); return res; }
/** * Returns the tree with the assignment context for the treePath leaf node. (Does not handle * pseudo-assignment of an argument to a parameter or a receiver expression to a receiver.) * * <p>The assignment context for the {@code treePath} is the leaf of its parent, if the parent * is one of the following trees: * * <ul> * <li>AssignmentTree * <li>CompoundAssignmentTree * <li>MethodInvocationTree * <li>NewArrayTree * <li>NewClassTree * <li>ReturnTree * <li>VariableTree * </ul> * * If the parent is a ConditionalExpressionTree we need to distinguish two cases: If the leaf is * either the then or else branch of the ConditionalExpressionTree, then recurse on the parent. * If the leaf is the condition of the ConditionalExpressionTree, then return null to not * consider this assignment context. * * <p>If the leaf is a ParenthesizedTree, then recurse on the parent. * * <p>Otherwise, null is returned. * * @return the assignment context as described */ public static Tree getAssignmentContext(final TreePath treePath) { TreePath parentPath = treePath.getParentPath(); if (parentPath == null) { return null; } Tree parent = parentPath.getLeaf(); switch (parent.getKind()) { case PARENTHESIZED: return getAssignmentContext(parentPath); case CONDITIONAL_EXPRESSION: ConditionalExpressionTree cet = (ConditionalExpressionTree) parent; if (cet.getCondition() == treePath.getLeaf()) { // The assignment context for the condition is simply boolean. // No point in going on. return null; } // Otherwise use the context of the ConditionalExpressionTree. return getAssignmentContext(parentPath); case ASSIGNMENT: case METHOD_INVOCATION: case NEW_ARRAY: case NEW_CLASS: case RETURN: case VARIABLE: return parent; default: // 11 Tree.Kinds are CompoundAssignmentTrees, // so use instanceof rather than listing all 11. if (parent instanceof CompoundAssignmentTree) { return parent; } return null; } }
@Override public PurityResult visitCompoundAssignment(CompoundAssignmentTree node, PurityResult p) { ExpressionTree variable = node.getVariable(); p = assignmentCheck(p, variable); PurityResult r = scan(variable, p); r = scan(node.getExpression(), r); return r; }