private void addIssue(List<StatementTree> statementsAtLine) { PreciseIssue issue = addIssue(statementsAtLine.get(1), MESSAGE); for (int i = 2; i < statementsAtLine.size(); i++) { issue.secondary(new IssueLocation(statementsAtLine.get(i))); } } }
private void checkSuperInvokedOnlyOnce(MethodDeclarationTree tree, List<SuperTree> superTrees) { if (isConstructor(tree) && superTrees.size() > 1) { SuperTree firstSuper = superTrees.get(0); superTrees.stream() .skip(1) .forEach(s -> addIssue(s, MESSAGE_SUPER_INVOKED_ONCE).secondary(new IssueLocation(firstSuper))); } }
private void raiseIssue(AccessorMethodDeclarationTree tree, String message) { addIssue(new PreciseIssue(this, new IssueLocation(tree, tree.name(), message))); }
private void leaveScopeAndCheckNumberOfJump(SyntaxToken loopKeyword) { List<Tree> jumps = jumpTargets.pop().jumps; int jumpStatementNumber = jumps.size(); if (jumpStatementNumber > 1) { PreciseIssue issue = addIssue(loopKeyword, MESSAGE).cost((double) jumpStatementNumber - 1); for (Tree jump : jumps) { issue.secondary(new IssueLocation(jump)); } } }
private void createIssue(Tree keyword, ExpressionTree condition) { LoopsShouldNotBeInfiniteCheck.this.addIssue(keyword, "Correct this loop's end condition as to not be invariant.") .secondary(new IssueLocation(condition, null)); }
private static IssueLocation issueLocation(IfStatementTree tree, String message) { return new IssueLocation(tree.ifKeyword(), tree.closeParenthesisToken(), message); }
private static <T extends Tree> IssueLocation issueLocation(T tree, String message) { if (tree.is(Kind.NEW_EXPRESSION)) { NewExpressionTree newExpressionTree = (NewExpressionTree) tree; return new IssueLocation( newExpressionTree.newKeyword(), newExpressionTree.expression(), message ); } else { CallExpressionTree callExpressionTree = (CallExpressionTree) tree; return new IssueLocation( callExpressionTree.callee(), message ); } }
@Override protected void checkDuplicatedBranches(List<Tree> branches) { Set<Tree> withIssue = new HashSet<>(); for (int i = 0; i < branches.size(); i++) { Tree currentBranch = branches.get(i); for (int j = i + 1; j < branches.size(); j++) { Tree comparedBranch = branches.get(j); if (!withIssue.contains(comparedBranch) && syntacticallyEqual(currentBranch, comparedBranch) && linesOfCodeForBranch(comparedBranch) > 1) { IssueLocation secondary = new IssueLocation(currentBranch, "Original"); String branchType = currentBranch instanceof SwitchClauseTree ? "case" : "branch"; String message = String.format(MESSAGE, branchType, secondary.startLine()); addIssue(comparedBranch, message).secondary(secondary); withIssue.add(comparedBranch); } } } }
private void issueIfLineMismatch(SyntaxToken curlyBrace, SyntaxToken target) { CodeLine curlyBraceLine = new CodeLine(curlyBrace.line()); if (curlyBraceLine.isJustBelow(target.line())) { addIssue(new PreciseIssue(this, new IssueLocation(curlyBrace, "Move this open curly brace to the end of the previous line."))); } else if (curlyBraceLine.isFarBelow(target.line())) { addIssue(new PreciseIssue(this, new IssueLocation(curlyBrace, "Move this open curly brace to the end of line " + target.line() + "."))); } }
private void raiseIssue(FunctionTree tree, List<Tree> complexityTrees) { int complexity = complexityTrees.size(); String message = String.format(MESSAGE, complexity, maximumFunctionComplexityThreshold); IssueLocation primaryIssueLocation = new IssueLocation(tree.firstToken(), tree.parameterClause(), message); PreciseIssue issue = addIssue(new PreciseIssue(this, primaryIssueLocation)); for (Tree complexityTree : complexityTrees) { issue.secondary(complexityTree, "+1"); } issue.cost((double) complexity - maximumFunctionComplexityThreshold); }
@Override public void visitNewExpression(NewExpressionTree tree) { if (isFunctionConstructorWithPossibleInjection(tree.expression(), tree.argumentClause())) { addIssue(new PreciseIssue(this, new IssueLocation(tree.newKeyword(), tree.expression(), MESSAGE))); } super.visitNewExpression(tree); }
private void checkCommentGroup(List<SyntaxTrivia> commentGroup) { String uncommentedText = uncomment(commentGroup); if (isRawExclusion(uncommentedText)) { return; } uncommentedText = injectMissingBraces(uncommentedText); try { ScriptTree parsedUncommentedText = (ScriptTree) PARSER.parse(uncommentedText); if (isExclusion(parsedUncommentedText)) { return; } IssueLocation primaryLocation = new IssueLocation(commentGroup.get(0), commentGroup.get(commentGroup.size() - 1), MESSAGE); addIssue(new PreciseIssue(this, primaryLocation)); } catch (RecognitionException e) { // do nothing, it's just a comment } }
private void checkArgumentIdentifier(IdentifierTree argument, ProgramState currentState) { Optional<Symbol> symbol = argument.symbol(); if (symbol.isPresent()) { SymbolicValue symbolicValue = currentState.getSymbolicValue(symbol.get()); if (symbolicValue instanceof FunctionWithTreeSymbolicValue) { FunctionTree functionTree = ((FunctionWithTreeSymbolicValue) symbolicValue).getFunctionTree(); if (!hasReturnWithValue(functionTree) && !isAsyncFunction(functionTree)) { IssueLocation secondaryLocation = new IssueLocation(functionToken(functionTree), "Callback declaration"); addUniqueIssue(argument, MESSAGE, secondaryLocation); } } } }
@Override public void visitElseClause(ElseClauseTree tree) { if (tree.statement().is(Kind.IF_STATEMENT)) { IfStatementTreeImpl ifStmt = (IfStatementTreeImpl) tree.statement(); if (!ifStmt.hasElse()) { addIssue(new PreciseIssue(this, new IssueLocation(tree.elseKeyword(), ifStmt.ifKeyword(), MESSAGE))); } } super.visitElseClause(tree); }
@Override public void visitNode(Tree tree) { AssignmentExpressionTree assignment = (AssignmentExpressionTree) tree; ExpressionTree expression = assignment.expression(); if (expression.is(Kind.UNARY_PLUS, Kind.UNARY_MINUS, Kind.LOGICAL_COMPLEMENT)) { UnaryExpressionTree unaryExpression = (UnaryExpressionTree) expression; SyntaxToken assignmentOperator = assignment.operatorToken(); SyntaxToken expressionOperator = unaryExpression.operatorToken(); if (areAdjacent(assignmentOperator, expressionOperator) && !areAdjacent(expressionOperator, unaryExpression.expression())) { String message = String.format(MESSAGE, unaryExpression.operatorToken()); addIssue(new PreciseIssue(this, new IssueLocation(assignmentOperator, expressionOperator, message))); } } super.visitNode(tree); }
private void addIssue(Tree statement, Tree nestingStatement, List<? extends Tree> otherStatements) { String primaryMessage = LOOP_PRIMARY_MESSAGE; String secondaryMessage = LOOP_SECONDARY_MESSAGE; if (nestingStatement.is(Kind.IF_STATEMENT)) { primaryMessage = IF_PRIMARY_MESSAGE; secondaryMessage = IF_SECONDARY_MESSAGE; } Tree firstStatementInPseudoBlock = nestedStatement(nestingStatement); Tree lastStatementInPseudoBlock = statement; List<IssueLocation> secondaryLocations = new ArrayList<>(); for (Tree otherStatement : otherStatements) { if (column(otherStatement) != column(statement)) { break; } secondaryLocations.add(new IssueLocation(otherStatement, secondaryMessage)); lastStatementInPseudoBlock = otherStatement; } int nbLines = line(lastStatementInPseudoBlock) - line(firstStatementInPseudoBlock) + 1; PreciseIssue issue = addIssue(statement, String.format(primaryMessage, nbLines)); for (IssueLocation secondaryLocation : secondaryLocations) { issue.secondary(secondaryLocation); } }
private void checkFunction(FunctionTree functionTree) { JavaScriptTree body = (JavaScriptTree) functionTree.body(); int firstLine = body.firstToken().line(); int lastLine = body.lastToken().endLine(); int nbLines = lastLine - firstLine + 1; if (nbLines > max) { String message = String.format(MESSAGE, nbLines, max); IssueLocation primaryLocation = new IssueLocation(functionTree.firstToken(), functionTree.parameterClause(), message); addIssue(new PreciseIssue(this, primaryLocation)); } } }
@Override public void beforeBlockElement(ProgramState currentState, Tree element, ProgramPoint programPoint) { if (element.is(Kind.RELATIONAL_IN)) { SymbolicValue rightOperandValue = currentState.peekStack(); Constraint rightOperandConstraint = currentState.getConstraint(rightOperandValue); if (rightOperandConstraint.isIncompatibleWith(Constraint.OBJECT)) { BinaryExpressionTree inOperation = (BinaryExpressionTree) element; addUniqueIssue(inOperation.rightOperand(), MESSAGE, new IssueLocation(inOperation.operatorToken())); } } }
@Override public void visitForStatement(ForStatementTree tree) { if (tree.condition() == null) { addIssue(tree.forKeyword(), "Add an end condition for this loop.").secondary(new IssueLocation(tree.firstSemicolonToken(), tree.secondSemicolonToken(), null)); } else { createIssue(tree.forKeyword(), tree.condition()); } }
private static IssueLocation getPrimaryLocation(Tree tree) { Tree firstTree; Tree lastTree; if (tree.is(Kind.GENERATOR_DECLARATION)) { FunctionDeclarationTree functionDeclarationTree = (FunctionDeclarationTree) tree; firstTree = functionDeclarationTree.functionKeyword(); lastTree = functionDeclarationTree.name(); } else if (tree.is(Kind.GENERATOR_METHOD)) { MethodDeclarationTree methodDeclarationTree = (MethodDeclarationTree) tree; firstTree = methodDeclarationTree.starToken(); lastTree = methodDeclarationTree.name(); } else { FunctionExpressionTree functionExpressionTree = (FunctionExpressionTree) tree; firstTree = functionExpressionTree.functionKeyword(); if (functionExpressionTree.name() != null) { lastTree = functionExpressionTree.name(); } else { lastTree = functionExpressionTree.starToken(); } } return new IssueLocation(firstTree, lastTree, MESSAGE); } }