private static Stream<JavaScriptTree> addUpdateExpression(IterationStatementTree iterationStatement, Stream<JavaScriptTree> iterationTrees) { if (iterationStatement instanceof ForStatementTree) { return Stream.concat(iterationTrees, Stream.of((JavaScriptTree) ((ForStatementTree) iterationStatement).update())); } return iterationTrees; }
private static boolean hasPredecessorInsideLoopBody(CfgBranchingBlock conditionBlock, IterationStatementTree loopTree) { for (CfgBlock loopPredecessor : conditionBlock.predecessors()) { List<Tree> predecessorElements = loopPredecessor.elements(); Tree predecessorLastElement = predecessorElements.get(predecessorElements.size() - 1); if (loopTree.is(Kind.FOR_STATEMENT)) { ForStatementTree forTree = (ForStatementTree) loopTree; if (forTree.update() != null && forTree.update().equals(predecessorLastElement)) { return !loopPredecessor.predecessors().isEmpty(); } } StatementTree loopBody = loopTree.statement(); if (isDescendant(predecessorLastElement, loopBody)) { return true; } } return false; }
private static boolean isInfiniteFor(IterationStatementTree loopTree) { if (loopTree.is(Kind.FOR_STATEMENT)) { ForStatementTree forLoop = (ForStatementTree) loopTree; return forLoop.update() == null && forLoop.init() == null && forLoop.condition() == null; } return false; }
private static boolean isNontrivialConditionException(ForStatementTree forStatement) { ExpressionTree condition = forStatement.condition(); ExpressionTree update = forStatement.update(); if (update != null && condition != null && condition.is(KindSet.EQUALITY_KINDS)) { Set<String> counters = new HashSet<>(); counters(update, counters); ExpressionTree leftOperand = ((BinaryExpressionTree) condition).leftOperand(); return !leftOperand.is(IDENTIFIER_REFERENCE) || !counters.contains(((IdentifierTree) leftOperand).name()); } return false; }
private static boolean isTrivialIteratorException(ForStatementTree forStatement) { // todo(Lena): SONARJS-383 consider usage of counter inside the loop. Do it with symbol table. ExpressionTree condition = forStatement.condition(); if (condition != null && condition.is(NOT_EQUAL_TO)) { ExpressionTree update = forStatement.update(); Tree init = forStatement.init(); if (init != null && update != null) { return checkForTrivialIteratorException(init, condition, update); } } return false; }
@Override public void visitForStatement(ForStatementTree tree) { if (tree.init() == null && tree.update() == null) { getContext().addIssue(this, tree, "Replace this \"for\" loop with a \"while\" loop"); } super.visitForStatement(tree); } }
private boolean isTrivialIteratorException(ForStatementTree forStatement) { // todo(Lena): SONARJS-383 consider usage of counter inside the loop. Do it with symbol table. ExpressionTree condition = forStatement.condition(); if (condition != null && condition.is(Tree.Kind.NOT_EQUAL_TO)) { ExpressionTree update = forStatement.update(); Tree init = forStatement.init(); if (init != null && update != null) { return checkForTrivialIteratorException(init, condition, update); } } return false; }
@Override public void visitForStatement(ForStatementTree forStatement) { List<ExpressionTree> updatedExpressions = updatedExpressions(forStatement.update()); ExpressionTree condition = forStatement.condition(); if (!updatedExpressions.isEmpty() && condition != null) { ConditionVisitor conditionVisitor = new ConditionVisitor(updatedExpressions); condition.accept(conditionVisitor); if (!conditionVisitor.foundUpdatedExpression) { String updated = expressionList(updatedExpressions); String tested = expressionList(conditionVisitor.testedExpressions); String message = String.format(MESSAGE, tested, updated); addIssue(forStatement.forKeyword(), message); } } super.visitForStatement(forStatement); }
@Override public void visitForStatement(ForStatementTree tree) { ExpressionTree condition = tree.condition(); ExpressionTree update = tree.update(); boolean conditionCondition = condition != null && isEquality(condition); boolean updateCondition = update != null && isUpdateIncDec(update); if (conditionCondition && updateCondition && !isException(tree)) { addIssue((BinaryExpressionTree) condition); } super.visitForStatement(tree); }
@Override public void visitForStatement(ForStatementTree forStatement) { List<ExpressionTree> updatedExpressions = updatedExpressions(forStatement.update()); ExpressionTree condition = forStatement.condition(); if (!updatedExpressions.isEmpty() && condition != null) { ConditionVisitor conditionVisitor = new ConditionVisitor(updatedExpressions); condition.accept(conditionVisitor); if (!conditionVisitor.foundUpdatedExpression) { String updated = expressionList(updatedExpressions); String tested = expressionList(conditionVisitor.testedExpressions); String message = String.format("This loop's stop condition tests \"%s\" but the incrementer updates \"%s\".", tested, updated); getContext().addIssue(this, forStatement, message); } } super.visitForStatement(forStatement); }
@Override public void visitForStatement(ForStatementTree tree) { scan(tree.init()); scan(tree.condition()); currentLoopCounters = new HashSet<>(); inUpdate = true; scan(tree.update()); inUpdate = false; enterLoopBody(); scan(tree.statement()); leaveLoopBody(); }
@Override public void visitForStatement(ForStatementTree tree) { scan(tree.init()); scan(tree.condition()); scan(tree.update()); scan(tree.statement()); }
@Override public void visitForStatement(ForStatementTree tree) { visitPossibleException(tree.init()); super.scan(tree.condition()); visitPossibleException(tree.update()); super.scan(tree.statement()); }
@Override public void visitForStatement(ForStatementTree tree) { scan(tree.init()); scan(tree.condition()); scanUpdateClause(tree.update()); scan(tree.statement()); }
@Override public void visitForStatement(ForStatementTree tree) { visitPossibleException(tree.init()); super.scan(tree.condition()); visitPossibleException(tree.update()); super.scan(tree.statement()); }
@Override public void visitForStatement(ForStatementTree tree) { ExpressionTree condition = tree.condition(); ExpressionTree update = tree.update(); boolean conditionCondition = condition != null && isEquality(condition); boolean updateCondition = update != null && isUpdateIncDec(update); if (conditionCondition && updateCondition && (condition.is(Tree.Kind.EQUAL_TO) || !isException(tree))) { addIssue(condition); } super.visitForStatement(tree); }
@CheckForNull public static ForLoopIncrement findInLoopUpdate(ForStatementTree forStatement) { ForLoopIncrement result = null; ExpressionTree expression = forStatement.update(); if (expression != null) { if (expression.is(Tree.Kind.POSTFIX_INCREMENT, Tree.Kind.PREFIX_INCREMENT)) { UnaryExpressionTree unaryExp = (UnaryExpressionTree) expression; result = increment(expression, unaryExp.expression(), 1.); } else if (expression.is(Tree.Kind.POSTFIX_DECREMENT, Tree.Kind.PREFIX_DECREMENT)) { UnaryExpressionTree unaryExp = (UnaryExpressionTree) expression; result = increment(expression, unaryExp.expression(), -1.); } else if (expression.is(Tree.Kind.PLUS_ASSIGNMENT)) { AssignmentExpressionTree assignmentExp = (AssignmentExpressionTree) expression; result = increment(expression, assignmentExp.variable(), numericValue(assignmentExp.expression())); } else if (expression.is(Tree.Kind.MINUS_ASSIGNMENT)) { AssignmentExpressionTree assignmentExp = (AssignmentExpressionTree) expression; result = increment(expression, assignmentExp.variable(), minus(numericValue(assignmentExp.expression()))); } else if (expression.is(Tree.Kind.ASSIGNMENT)) { AssignmentExpressionTree assignment = (AssignmentExpressionTree) expression; result = assignmentIncrement(assignment); } } return result; }
@CheckForNull public static ForLoopIncrement findInLoopUpdate(ForStatementTree forStatement) { ForLoopIncrement result = null; ExpressionTree expression = forStatement.update(); if (expression != null) { if (expression.is(Tree.Kind.POSTFIX_INCREMENT, Tree.Kind.PREFIX_INCREMENT)) { UnaryExpressionTree unaryExp = (UnaryExpressionTree) expression; result = increment(unaryExp.expression(), 1.); } else if (expression.is(Tree.Kind.POSTFIX_DECREMENT, Tree.Kind.PREFIX_DECREMENT)) { UnaryExpressionTree unaryExp = (UnaryExpressionTree) expression; result = increment(unaryExp.expression(), -1.); } else if (expression.is(Tree.Kind.PLUS_ASSIGNMENT)) { AssignmentExpressionTree assignmentExp = (AssignmentExpressionTree) expression; result = increment(assignmentExp.variable(), numericValue(assignmentExp.expression())); } else if (expression.is(Tree.Kind.MINUS_ASSIGNMENT)) { AssignmentExpressionTree assignmentExp = (AssignmentExpressionTree) expression; result = increment(assignmentExp.variable(), minus(numericValue(assignmentExp.expression()))); } else if (expression.is(Tree.Kind.ASSIGNMENT)) { AssignmentExpressionTree assignment = (AssignmentExpressionTree) expression; result = assignmentIncrement(assignment); } } return result; }