/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.controversial; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; public class OnlyOneReturnRule extends AbstractJavaRule { @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { if (node.isInterface()) { return data; } return super.visit(node, data); } @Override public Object visit(ASTMethodDeclaration node, Object data) { if (node.isAbstract()) { return data; } List<ASTReturnStatement> returnNodes = new ArrayList<>(); node.findDescendantsOfType(ASTReturnStatement.class, returnNodes, false); returnNodes = filterLambdaExpressions(returnNodes); if (returnNodes.size() > 1) { for (Iterator<ASTReturnStatement> i = returnNodes.iterator(); i.hasNext();) { Node problem = i.next(); // skip the last one, it's OK if (!i.hasNext()) { continue; } addViolation(data, problem); } } return data; } /** * Checks whether the return statement is inside a lambda expression, and if * so, this return statement is removed. * * @param returnNodes * all the return statements inside the method * @return all return statements, that are NOT within a lambda expression. */ private List<ASTReturnStatement> filterLambdaExpressions(List<ASTReturnStatement> returnNodes) { List<ASTReturnStatement> filtered = new ArrayList<>(); for (ASTReturnStatement ret : returnNodes) { if (ret.getFirstParentOfType(ASTLambdaExpression.class) == null) { filtered.add(ret); } } return filtered; } }