1 package no.uio.ifi.refaktor.analyze.checkers;
5 import no.uio.ifi.refaktor.analyze.collectors.LastStatementCollector;
6 import no.uio.ifi.refaktor.analyze.collectors.PropertyCollector;
7 import no.uio.ifi.refaktor.analyze.exceptions.IllegalExpressionFoundException;
8 import no.uio.ifi.refaktor.analyze.exceptions.IllegalStatementFoundException;
9 import no.uio.ifi.refaktor.utils.CompilationUnitTextSelection;
11 import org.eclipse.jdt.core.dom.ASTNode;
12 import org.eclipse.jdt.core.dom.Block;
13 import org.eclipse.jdt.core.dom.CatchClause;
14 import org.eclipse.jdt.core.dom.DoStatement;
15 import org.eclipse.jdt.core.dom.IfStatement;
16 import org.eclipse.jdt.core.dom.LabeledStatement;
17 import org.eclipse.jdt.core.dom.MethodDeclaration;
18 import org.eclipse.jdt.core.dom.ReturnStatement;
19 import org.eclipse.jdt.core.dom.Statement;
20 import org.eclipse.jdt.core.dom.SynchronizedStatement;
21 import org.eclipse.jdt.core.dom.ThrowStatement;
22 import org.eclipse.jdt.core.dom.TryStatement;
24 class LastStatementOfSelectionEndsInReturnOrThrowChecker extends PropertyCollector implements Checker {
26 public LastStatementOfSelectionEndsInReturnOrThrowChecker(CompilationUnitTextSelection selection) {
31 public void clearData() {
35 public boolean preVisit2(ASTNode node) {
36 if (!(node instanceof Statement) || isReturnOrThrowOrImplicitReturn((Statement) node))
39 if (!nodeIsOfHandledType(node))
45 private boolean isReturnOrThrowOrImplicitReturn(Statement statement) {
46 if (statementIsReturnOrThrow(statement) || statementIsImplicitReturn(statement))
52 private boolean statementIsReturnOrThrow(Statement statement) {
53 return statement instanceof ReturnStatement || statement instanceof ThrowStatement;
56 private boolean statementIsImplicitReturn(Statement statement) {
57 Block methodDeclarationBlock = getMethodDeclarationBlockOf(selection.getCoveredNode());
58 LastStatementFinder lastStatementOfMethodFinder = new LastStatementFinder(methodDeclarationBlock);
59 methodDeclarationBlock.accept(lastStatementOfMethodFinder);
60 return lastStatementOfMethodFinder.getLastStatement() == statement
61 || isLastReachableStatement(statement);
64 private Block getMethodDeclarationBlockOf(ASTNode statement) {
65 ASTNode node = statement.getParent();
66 while (!(node instanceof Block && node.getParent() instanceof MethodDeclaration))
67 node = node.getParent();
71 private boolean isLastReachableStatement(Statement statement) {
72 if (!isLastStatementOfParent(statement))
75 ASTNode node = statement.getParent();
76 while (isUnconditionalStatement(node) && isLastStatementOfParent(node))
77 node = node.getParent();
78 return node instanceof MethodDeclaration;
81 private boolean isUnconditionalStatement(ASTNode node) {
82 return node instanceof Block || node instanceof LabeledStatement
83 || node instanceof SynchronizedStatement || node instanceof TryStatement;
86 private boolean isLastStatementOfParent(ASTNode node) {
87 if (!(node.getParent() instanceof Block))
90 List<?> parentStatements = ((Block) node.getParent()).statements();
91 return node == lastElementOfList(parentStatements);
94 private Object lastElementOfList(List<?> list) {
95 return list.get(list.size() - 1);
98 private boolean nodeIsOfHandledType(ASTNode node) {
99 return node instanceof IfStatement || node instanceof TryStatement
100 || node instanceof Block || node instanceof LabeledStatement || node instanceof DoStatement;
103 private boolean check(ASTNode node) {
104 if (!nodeIsLastStatementOfParentInSelection(node))
107 throw new IllegalStatementFoundException(ReturnStatement.class);
110 private boolean nodeIsLastStatementOfParentInSelection(ASTNode node) {
111 ASTNode parent = node.getParent();
112 LastStatementCollector collector = new LastStatementCollector(selection, parent);
113 parent.accept(collector);
114 return nodeInSelection(node) && node == collector.getLastStatement();
118 public boolean visit(IfStatement node) {
119 if (!nodeIsLastStatementOfParentInSelection(node))
122 ReturnOrThrowStatementFinder statementFinder = new ReturnOrThrowStatementFinder();
123 node.getThenStatement().accept(statementFinder);
125 if (statementFinder.hasFoundReturnOrThrowStatement()) {
126 Statement elseStatement = node.getElseStatement();
128 if (elseStatement == null) {
129 throw new IllegalStatementFoundException(ReturnStatement.class);
132 statementFinder.reset();
133 elseStatement.accept(statementFinder);
135 if (!statementFinder.hasFoundReturnOrThrowStatement()) {
136 throw new IllegalStatementFoundException(ReturnStatement.class);
139 throw new IllegalStatementFoundException(ReturnStatement.class);
146 public boolean visit(TryStatement node) {
147 if (!nodeIsLastStatementOfParentInSelection(node))
150 ReturnOrThrowStatementFinder statementFinder = new ReturnOrThrowStatementFinder();
151 node.getBody().accept(statementFinder);
152 if (!statementFinder.hasFoundReturnOrThrowStatement())
153 throw new IllegalStatementFoundException(ReturnStatement.class);
155 for (Object obj: node.catchClauses()) {
156 assert obj instanceof CatchClause;
157 CatchClause catchClause = (CatchClause) obj;
158 statementFinder.reset();
159 catchClause.accept(statementFinder);
161 if (!statementFinder.hasFoundReturnOrThrowStatement())
162 throw new IllegalStatementFoundException(ReturnStatement.class);
165 if (node.getFinally() != null) {
166 statementFinder.reset();
167 node.getFinally().accept(statementFinder);
169 if (!statementFinder.hasFoundReturnOrThrowStatement())
170 throw new IllegalStatementFoundException(ReturnStatement.class);
177 public void check() throws IllegalStatementFoundException, IllegalExpressionFoundException {
178 selection.getLastStatement().accept(this);