public Boolean visitForLoop(ForLoopTree node, TreePath p) { if (p == null) return super.visitForLoop(node, p); ForLoopTree t = (ForLoopTree) p.getLeaf(); if (!checkLists(node.getInitializer(), t.getInitializer(), p)) { return false; } if (!scan(node.getCondition(), t.getCondition(), p)) return false; if (!checkLists(node.getUpdate(), t.getUpdate(), p)) return false; return scan(node.getStatement(), t.getStatement(), p); }
@Override public Object visitVariable(VariableTree node, Object p) { TreePath path = getCurrentPath(); Tree parent = path.getParentPath().getLeaf(); if (parent instanceof StatementTree) { boolean count = true; if (parent instanceof ForLoopTree) { count = !((ForLoopTree)parent).getInitializer().contains(node); } else if (parent instanceof EnhancedForLoopTree) { count = ((EnhancedForLoopTree)parent).getVariable() != node; } if (count) { statements++; } } return super.visitVariable(node, p); }
@Override public Void visitForLoop(ForLoopTree node, Void p) { super.visitForLoop(node, p); if (isMethodCode() && phase == PHASE_AFTER_SELECTION) { //#109663𛞨: //the selection was inside the for-loop, the variables inside the //condition, update and statement parts of the for loop need to be considered to be used again after the loop: if (!secondPass) { secondPass = true; scan(node.getCondition(), p); scan(node.getUpdate(), p); scan(node.getStatement(), p); secondPass = false; stopSecondPass = false; } } return null; }
@Override public List<? extends TypeMirror> visitForLoop(ForLoopTree node, Object p) { if (theExpression == null) { // ambigous return null; } if (theExpression.getLeaf() == node.getCondition()) { return booleanType(); } else { if (!((node.getInitializer() != null && node.getInitializer().contains(theExpression.getLeaf())) || (node.getUpdate() != null && node.getUpdate().contains(theExpression.getLeaf())))) { return null; } // initializer and update operation can have any result type, including none TypeElement tel = info.getElements().getTypeElement("java.lang.Void"); if (tel == null) { return null; } return Collections.singletonList(tel.asType()); // NOI18N } }
private boolean testBlock(StringWriter writer, SourcePositions sp, String text, CompilationUnitTree cut, BlockTree blockTree) { boolean success = true; for (StatementTree st : blockTree.getStatements()) { if (isLegal(st)) { success &= testStatement(writer, sp, text, cut, st); } if (st instanceof IfTree) { IfTree ifTree = (IfTree) st; success &= testBranch(writer, sp, text, cut, ifTree.getThenStatement()); success &= testBranch(writer, sp, text, cut, ifTree.getElseStatement()); } else if (st instanceof WhileLoopTree) { WhileLoopTree whileLoopTree = (WhileLoopTree) st; success &= testBranch(writer, sp, text, cut, whileLoopTree.getStatement()); } else if (st instanceof DoWhileLoopTree) { DoWhileLoopTree doWhileLoopTree = (DoWhileLoopTree) st; success &= testBranch(writer, sp, text, cut, doWhileLoopTree.getStatement()); } else if (st instanceof ForLoopTree) { ForLoopTree forLoopTree = (ForLoopTree) st; success &= testBranch(writer, sp, text, cut, forLoopTree.getStatement()); } else if (st instanceof LabeledStatementTree) { LabeledStatementTree labelTree = (LabeledStatementTree) st; success &= testBranch(writer, sp, text, cut, labelTree.getStatement()); } else if (st instanceof SwitchTree) { SwitchTree switchTree = (SwitchTree) st; for (CaseTree caseTree : switchTree.getCases()) { for (StatementTree statementTree : caseTree.getStatements()) { success &= testBranch(writer, sp, text, cut, statementTree); } } } } return success; }
@Test public void testVisitForLoop() throws ParseException, BadLocationException, IOException { List<ReformatOption> optionsToReformat = new ArrayList<>(); CompilationUnitTree unit = getCompilationUnitTree(INPUT_FILE); MethodTree methodTree = TreeNavigationUtils.findMethodTreeByName("doSomething", unit).get(0); ForLoopTree forLoopTree = (ForLoopTree) getStatementTreeByClassName(ForLoopTree.class, methodTree); if (forLoopTree == null) { fail(ERROR_MESSAGE); } ReformatTreeVisitor reformatTreeVisitor = getReformatTreeVisitor(INPUT_FILE); reformatTreeVisitor.visitForLoop(forLoopTree, optionsToReformat); assertFalse(optionsToReformat.isEmpty()); }
@Test public void testVisitForLoopNotReformat() throws ParseException, BadLocationException, IOException { List<ReformatOption> optionsToReformat = new ArrayList<>(); CompilationUnitTree unit = getCompilationUnitTree(INPUT_FILE); MethodTree methodTree = TreeNavigationUtils.findMethodTreeByName("doSomething", unit).get(0); ForLoopTree forLoopTree = (ForLoopTree) getStatementTreeByClassName(ForLoopTree.class, methodTree); if (forLoopTree == null) { fail(ERROR_MESSAGE); } ReformatTreeVisitor reformatTreeVisitor = getReformatTreeVisitor(INPUT_FILE, 0, 10); reformatTreeVisitor.visitForLoop(forLoopTree, optionsToReformat); assertTrue(optionsToReformat.isEmpty()); }
@Override public Boolean visitForLoop(ForLoopTree that, Void unused) { Boolean condValue = ASTHelpers.constValue(that.getCondition(), Boolean.class); if (!Objects.equals(condValue, false)) { scan(that.getStatement()); } // (1) if (that.getCondition() != null && !Objects.equals(condValue, true)) { return true; } // (2) if (breaks.contains(that)) { return true; } return false; }
@Override public Tree visitForLoop(ForLoopTree tree, Void p) { ForLoopTree n = make.ForLoop(tree.getInitializer(), tree.getCondition(), tree.getUpdate(), tree.getStatement()); model.setType(n, model.getType(tree)); comments.copyComments(tree, n); model.setPos(n, model.getPos(tree)); return n; }
@Override public Void visitForLoop(ForLoopTree node, EnumSet<UseTypes> p) { if (node.getCondition() != null && node.getCondition().getKind() == Kind.IDENTIFIER) { handlePossibleIdentifier(new TreePath(getCurrentPath(), node.getCondition()), EnumSet.of(UseTypes.READ)); } return super.visitForLoop(node, p); }
@Override public Object visitExpressionStatement(ExpressionStatementTree node, Object p) { boolean count = true; TreePath path = getCurrentPath(); Tree parent = path.getParentPath().getLeaf(); // do not count the update statement in a for-loop if (parent instanceof ForLoopTree) { count = !((ForLoopTree)parent).getUpdate().contains(node); } if (count) { statements++; } return super.visitExpressionStatement(node, p); }
@Override public Object visitForLoop(ForLoopTree node, Object p) { boolean saveFlag = switchCase; switchCase = false; complexity++; Object o = super.visitForLoop(node, p); this.switchCase = saveFlag; return o; }
@Override public Object visitForLoop(ForLoopTree node, Object p) { depth++; Object o = super.visitForLoop(node, p); depth--; return o; }
@Override public Void visitForLoop(ForLoopTree tree, List<Node> d) { List<Node> below = new ArrayList<Node>(); addCorrespondingType(below); addCorrespondingComments(below); super.visitForLoop(tree, below); d.add(new TreeNode(info, getCurrentPath(), below)); return null; }
@Hint(displayName="#LBL_Braces_For", description="#DSC_Braces_For", category="braces", id=BRACES_ID + "FOR_LOOP", enabled=false, suppressWarnings={"", "ControlFlowStatementWithoutBraces"}) @TriggerTreeKind({Tree.Kind.FOR_LOOP, Tree.Kind.ENHANCED_FOR_LOOP}) public static ErrorDescription checkFor(HintContext ctx) { StatementTree st; switch (ctx.getPath().getLeaf().getKind()){ case FOR_LOOP: st = ((ForLoopTree) ctx.getPath().getLeaf()).getStatement(); break; case ENHANCED_FOR_LOOP: st = ((EnhancedForLoopTree) ctx.getPath().getLeaf()).getStatement(); break; default: throw new IllegalStateException(); } return checkStatement(ctx, "LBL_Braces_For", st, ctx.getPath()); }
@Override public State visitForLoop(ForLoopTree node, Void p) { State s; registerBreakTarget((node)); if (returnIfRecurse(s = scan(node.getInitializer(), p))) { return s; } returnIfRecurse(s = s.append(scan(node.getCondition(), p))); // the body + update might be skipped if condition evaluates to false immediately. // PENDING: speculatively report recursions, if unconditionally reachable from cycles ? return s; }
@Override public Mirror visitForLoop(ForLoopTree arg0, EvaluationContext evaluationContext) { try { evaluationContext.pushBlock(); for (StatementTree st : arg0.getInitializer()) { st.accept(this, evaluationContext); } Mirror result = null; ExpressionTree condition = arg0.getCondition(); List<? extends ExpressionStatementTree> updateList = arg0.getUpdate(); StatementTree statement = arg0.getStatement(); while (condition == null || evaluateCondition(arg0, evaluationContext, condition)) { Mirror value = null; try { evaluationContext.pushBlock(); value = statement.accept(this, evaluationContext); if (value instanceof Break) { break; } else if (value instanceof Continue) { continue; } if (value != null) { result = value; } } finally { evaluationContext.popBlock(); if ((value instanceof Continue) || !(value instanceof CommandMirror)) { for (Tree tree : updateList) { tree.accept(this, evaluationContext); } // for } // if } // finally } // while return result; } finally { evaluationContext.popBlock(); } }
@Override public Description matchForLoop(ForLoopTree tree, VisitorState state) { if (tree.getCondition() != null) { return doUnboxingCheck(state, tree.getCondition()); } return Description.NO_MATCH; }
@Override public Void visitForLoop(ForLoopTree forLoopTree, List<ReformatOption> optionsToReformat) { StatementTree statement = forLoopTree.getStatement(); if (statement instanceof BlockTree) { addLeftBraceToList(optionsToReformat, ((BlockTree) statement), PreferencesFormatOptions.BRACES_IN_OTHER_DECLARATION); addRightBraceToList(optionsToReformat, ((CompoundTree) statement), PreferencesFormatOptions.AFTER_OTHER_DECLARATION); } return null; }
@Override public UForLoop visitForLoop(ForLoopTree tree, Void v) { return UForLoop.create( templateStatements(tree.getInitializer()), (tree.getCondition() == null) ? null : template(tree.getCondition()), cast(templateStatements(tree.getUpdate()), UExpressionStatement.class), template(tree.getStatement())); }
@Override @Nullable public Unifier visitForLoop(ForLoopTree loop, @Nullable Unifier unifier) { unifier = Unifier.unifyList(unifier, getInitializer(), loop.getInitializer()); unifier = Unifier.unifyNullable(unifier, getCondition(), loop.getCondition()); unifier = Unifier.unifyList(unifier, getUpdate(), loop.getUpdate()); return getStatement().unify(loop.getStatement(), unifier); }
/** * Finds all variable declarations which are unused at this point in the AST (i.e. they might be * used further on). */ public static ImmutableSet<VarSymbol> findUnusedIdentifiers(VisitorState state) { ImmutableSet.Builder<VarSymbol> definedVariables = ImmutableSet.builder(); ImmutableSet.Builder<Symbol> usedSymbols = ImmutableSet.builder(); Tree prev = state.getPath().getLeaf(); for (Tree curr : state.getPath().getParentPath()) { createFindIdentifiersScanner(usedSymbols, prev).scan(curr, null); switch (curr.getKind()) { case BLOCK: // If we see a block then walk over each statement to see if it defines a variable for (StatementTree statement : ((BlockTree) curr).getStatements()) { if (statement.equals(prev)) { // break if we see the tree we have just processed so that we only consider things // declared/used before us in the tree break; } addIfVariable(statement, definedVariables); } break; case FOR_LOOP: ForLoopTree forLoop = (ForLoopTree) curr; forLoop.getInitializer().stream().forEach(t -> addIfVariable(t, definedVariables)); break; case ENHANCED_FOR_LOOP: EnhancedForLoopTree enhancedFor = (EnhancedForLoopTree) curr; addIfVariable(enhancedFor.getVariable(), definedVariables); break; default: break; } prev = curr; } return ImmutableSet.copyOf(Sets.difference(definedVariables.build(), usedSymbols.build())); }
@Override public Void visitForLoop(ForLoopTree tree, VisitorState visitorState) { VisitorState state = visitorState.withPath(getCurrentPath()); for (ForLoopTreeMatcher matcher : forLoopMatchers) { if (!isSuppressed(matcher, state)) { try { reportMatch(matcher.matchForLoop(tree, state), tree, state); } catch (Throwable t) { handleError(matcher, t); } } } return super.visitForLoop(tree, state); }
@Override public Result visitForLoop(ForLoopTree node, BreakContext cxt) { cxt.loopDepth++; try { return node.getStatement().accept(this, cxt).or(NEVER_EXITS); } finally { cxt.loopDepth--; } }
@Override public Choice<State<JCForLoop>> visitForLoop(final ForLoopTree node, State<?> state) { return chooseSubtrees( state, s -> unifyStatements(node.getInitializer(), s), s -> unifyExpression(node.getCondition(), s), s -> unifyStatements(node.getUpdate(), s), s -> unifyStatement(node.getStatement(), s), (inits, cond, update, stmt) -> maker().ForLoop(inits, cond, List.convert(JCExpressionStatement.class, update), stmt)); }
@Override @Nullable public Choice<Unifier> visitForLoop(ForLoopTree loop, @Nullable Unifier unifier) { return UBlock.unifyStatementList(getInitializer(), loop.getInitializer(), unifier) .thenChoose(unifications(getCondition(), loop.getCondition())) .thenChoose(unifications(getUpdate(), loop.getUpdate())) .thenChoose(unifications(getStatement(), loop.getStatement())); }
@Override public boolean matches(TryTree tryTree, VisitorState state) { return ASTHelpers.findEnclosingNode(state.getPath(), DoWhileLoopTree.class) != null || ASTHelpers.findEnclosingNode(state.getPath(), EnhancedForLoopTree.class) != null || ASTHelpers.findEnclosingNode(state.getPath(), WhileLoopTree.class) != null || ASTHelpers.findEnclosingNode(state.getPath(), ForLoopTree.class) != null; }
@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; }
boolean forLoopVariable(VariableTree tree, TreePath path) { Tree parent = path.getParentPath().getLeaf(); if (!(parent instanceof ForLoopTree)) { return false; } ForLoopTree forLoop = (ForLoopTree) parent; return forLoop.getInitializer().contains(tree); }
@Override public Description matchForLoop(ForLoopTree tree, VisitorState state) { if (tree.getCondition() == null) { return NO_MATCH; } return check( tree.getCondition(), ImmutableList.<Tree>builder() .add(tree.getCondition()) .add(tree.getStatement()) .addAll(tree.getUpdate()) .build()); }
@Override public boolean matches(T t, VisitorState state) { if (state.getPath().getParentPath() == null) { return false; } Tree parent = state.getPath().getParentPath().getLeaf(); return (parent instanceof ForLoopTree && (interestingPartOfLoop((ForLoopTree) parent) == t)); }
@Override public PurityResult visitForLoop(ForLoopTree node, PurityResult p) { PurityResult r = scan(node.getInitializer(), p); r = scan(node.getCondition(), r); r = scan(node.getUpdate(), r); r = scan(node.getStatement(), r); return r; }
@Override public Void visitForLoop(ForLoopTree node, Void p) { if (node.getCondition() != null) { // Condition is null e.g. in "for (;;) {...}" checkForNullability(node.getCondition(), CONDITION_NULLABLE); } return super.visitForLoop(node, p); }
@Override public CodeModel visitForLoop(ForLoopTree node, VisitContext context) { if (node.getInitializer().size() != 1) { throw new UnsupportedOperationException(); } if (node.getUpdate().size() != 1) { throw new UnsupportedOperationException(); } StatementModel body = scan(node.getStatement(), context); if (node.getInitializer().size() == 1 && node.getInitializer().get(0).getKind() == Tree.Kind.VARIABLE && node.getCondition().getKind() == Tree.Kind.LESS_THAN && node.getUpdate().size() == 1 && node.getUpdate().get(0).getKind() == Tree.Kind.EXPRESSION_STATEMENT && node.getUpdate().get(0).getExpression().getKind() == Tree.Kind.POSTFIX_INCREMENT) { VariableTree init = (VariableTree) node.getInitializer().get(0); BinaryTree lessThan = (BinaryTree) node.getCondition(); UnaryTree increment = (UnaryTree) node.getUpdate().get(0).getExpression(); if (lessThan.getLeftOperand().getKind() == Tree.Kind.IDENTIFIER && increment.getExpression().getKind() == Tree.Kind.IDENTIFIER) { String id1 = init.getName().toString(); String id2 = ((IdentifierTree) lessThan.getLeftOperand()).getName().toString(); String id3 = ((IdentifierTree) increment.getExpression()).getName().toString(); if (id1.equals(id2) && id2.equals(id3)) { ExpressionModel from = scan(init.getInitializer(), context); ExpressionModel to = scan(lessThan.getRightOperand(), context); return context.builder.sequenceForLoop(id1, from, to, body); } } } StatementModel initializer = scan(node.getInitializer().get(0), context); ExpressionModel update = scan(node.getUpdate().get(0).getExpression(), context); ExpressionModel condition = scan(node.getCondition(), context); return context.builder.forLoop(initializer, condition, update, body); }
@Override public Void visitForLoop(ForLoopTree expected, Tree actual) { Optional<ForLoopTree> other = checkTypeAndCast(expected, actual); if (!other.isPresent()) { addTypeMismatch(expected, actual); return null; } parallelScan(expected.getInitializer(), other.get().getInitializer()); scan(expected.getCondition(), other.get().getCondition()); parallelScan(expected.getUpdate(), other.get().getUpdate()); scan(expected.getStatement(), other.get().getStatement()); return null; }