private boolean isCallbackException() { for (ReturnStatementTree returnStatementTree : valuesPerReturn.keySet()) { ExpressionTree expression = returnStatementTree.expression(); if (expression != null && !expression.is(Kind.BOOLEAN_LITERAL)) { return false; } } return true; }
private void raiseIssue(Tree functionTree) { SyntaxToken firstFunctionToken = functionTree.firstToken(); PreciseIssue issue = addIssue(firstFunctionToken, MESSAGE); for (ReturnStatementTree returnStatement : returnedValueConstraintsByReturnStatement.keySet()) { Set<Constraint> returnedTypes = new HashSet<>(returnedValueConstraintsByReturnStatement.get(returnStatement)); if (!returnedTypes.isEmpty()) { List<String> typeNames = returnedTypes.stream().map(TYPES::get).collect(Collectors.toList()); Collections.sort(typeNames); String typesForSecondaryMessage = String.join(" or ", typeNames); issue.secondary(returnStatement.returnKeyword(), "Returns " + typesForSecondaryMessage); } } }
@Override public void visitReturnStatement(ReturnStatementTree tree) { super.visitReturnStatement(tree); checkEOS(tree, tree.semicolonToken()); }
private void raiseIssue(Tree functionTree, FunctionReturns functionReturns, BlockTree body) { SyntaxToken tokenToRaiseIssue = functionTree.firstToken(); if (functionTree.is(Kind.ARROW_FUNCTION)) { tokenToRaiseIssue = ((ArrowFunctionTree) functionTree).doubleArrowToken(); } if (functionTree.is(Kind.GENERATOR_METHOD)) { tokenToRaiseIssue = ((MethodDeclarationTree) functionTree).name().firstToken(); } PreciseIssue issue = addIssue(tokenToRaiseIssue, MESSAGE); for (ReturnStatementTree returnStatement : functionReturns.returnStatements()) { issue.secondary(returnStatement.returnKeyword(), returnStatement.expression() == null ? "Return without value" : "Return with value"); } if (functionReturns.containsImplicitReturn()) { issue.secondary(body.closeCurlyBraceToken(), "Implicit return without value"); } }
@Override public void visitReturnStatement(ReturnStatementTree tree) { scan(tree.expression()); }
@Override public void visitReturnStatement(ReturnStatementTree tree) { check(tree, tree.returnKeyword(), SAFE_PARENTS_FOR_RETURN); super.visitReturnStatement(tree); }
@Override public void visitReturnStatement(ReturnStatementTree tree) { if (tree.expression() != null) { ReturnInSetterCheck check = ReturnInSetterCheck.this; check.addIssue(tree, MESSAGE); } super.visitReturnStatement(tree); }
@Override public void visitReturnStatement(ReturnStatementTree tree){ checkExpression(tree.expression()); super.visitReturnStatement(tree); }
public static boolean isSimpleReturnBooleanLiteral(AstNode astNode) { if (astNode.isNot(Kind.RETURN_STATEMENT)) { return false; } ReturnStatementTree statement = (ReturnStatementTree) astNode; ExpressionTree expression = statement.expression(); return expression != null && expression.is(Kind.BOOLEAN_LITERAL); }
@Override public void visitReturnStatement(ReturnStatementTree tree) { if (tree.expression() != null) { ReturnInSetterCheck check = ReturnInSetterCheck.this; check.getContext().addIssue(check, tree, "Remove this return statement."); } super.visitReturnStatement(tree); }
@Override public void beforeBlockElement(ProgramState currentState, Tree element, ProgramPoint programPoint) { if (element.is(Kind.RETURN_STATEMENT)) { ReturnStatementTree returnStatement = (ReturnStatementTree) element; if (returnStatement.expression() != null) { SymbolicValue symbolicValue = currentState.peekStack(); Constraint typeConstraint = toTypeConstraint(currentState.getConstraint(symbolicValue)); if (!UNKNOWN_TYPE.equals(typeConstraint)) { returnedValueConstraintsByReturnStatement.put(returnStatement, typeConstraint); } } } }
private static boolean isReturnThrowExclusion(Tree item) { ExpressionTree expression = null; if (item.is(Kind.RETURN_STATEMENT)) { expression = ((ReturnStatementTree)item).expression(); } else if (item.is(Kind.THROW_STATEMENT)) { expression = ((ThrowStatementTree) item).expression(); } return expression != null && expression.is(Kind.IDENTIFIER_REFERENCE); }
private static boolean hasReturnWithValue(FunctionTree functionTree) { if (functionTree.body().is(Kind.BLOCK)) { ControlFlowGraph cfg = ControlFlowGraph.build((BlockTree) functionTree.body()); for (CfgBlock cfgBlock : cfg.blocks()) { if (cfgBlock.elements().isEmpty()) { continue; } Tree lastElement = cfgBlock.elements().get(cfgBlock.elements().size() - 1); if (lastElement.is(Kind.RETURN_STATEMENT) && ((ReturnStatementTree) lastElement).expression() != null) { return true; } } return false; } // for arrow function with expression body return true; }
private static boolean isRemovableReturn(StatementTree tree) { if (tree.is(Kind.RETURN_STATEMENT)) { ExpressionTree expression = ((ReturnStatementTree) tree).expression(); if (expression != null && !expression.is(Kind.OBJECT_LITERAL)) { int firstLine = expression.firstToken().line(); int lastLine = expression.lastToken().line(); return firstLine == lastLine; } } return false; }
public static FunctionReturns getFunctionReturns(BlockTree functionBody) { FunctionReturns functionReturns = new FunctionReturns(); ControlFlowGraph cfg = ControlFlowGraph.build(functionBody); if (containsTry(cfg)) { return functionReturns; } CfgBlock endBlock = cfg.end(); // Possible predecessors for end block: // * return statement -> check for expression // * last statement in function -> implicit return without value // * throw statement -> we only target return here, so ignore for (CfgBlock cfgBlock : endBlock.predecessors()) { Tree lastElement = cfgBlock.elements().get(cfgBlock.elements().size() - 1); if (lastElement.is(Kind.RETURN_STATEMENT)) { ReturnStatementTree returnStatement = (ReturnStatementTree) lastElement; if (returnStatement.expression() == null) { functionReturns.containsReturnWithoutValue = true; } else { functionReturns.containsReturnWithValue = true; } functionReturns.returnStatements.add(returnStatement); } else if (!isThrowStatement(lastElement) && isReachableBlock(cfgBlock, cfg)) { functionReturns.containsReturnWithoutValue = true; functionReturns.containsImplicitReturn = true; } } return functionReturns; }