]> git.uio.no Git - ifi-stolz-refaktor.git/blob - software/no.uio.ifi.refaktor/src/no/uio/ifi/refaktor/analyze/checkers/LastStatementOfSelectionEndsInReturnOrThrowChecker.java
Software: moving stuff around
[ifi-stolz-refaktor.git] / software / no.uio.ifi.refaktor / src / no / uio / ifi / refaktor / analyze / checkers / LastStatementOfSelectionEndsInReturnOrThrowChecker.java
1 package no.uio.ifi.refaktor.analyze.checkers;
2
3 import java.util.List;
4
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;
10
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;
23
24 class LastStatementOfSelectionEndsInReturnOrThrowChecker extends PropertyCollector implements Checker {
25
26         public LastStatementOfSelectionEndsInReturnOrThrowChecker(CompilationUnitTextSelection selection) {
27                 super(selection);
28         }
29
30         @Override
31         public void clearData() {
32         }
33
34         @Override
35         public boolean preVisit2(ASTNode node) {
36                 if (!(node instanceof Statement) || isReturnOrThrowOrImplicitReturn((Statement) node))
37                         return false;
38                 
39                 if (!nodeIsOfHandledType(node))
40                         return check(node);
41
42                 return true;
43         }
44
45         private boolean isReturnOrThrowOrImplicitReturn(Statement statement) {
46                 if (statementIsReturnOrThrow(statement) || statementIsImplicitReturn(statement))
47                         return true;
48
49                 return false;
50         }
51
52         private boolean statementIsReturnOrThrow(Statement statement) {
53                 return statement instanceof ReturnStatement || statement instanceof ThrowStatement;
54         }
55
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);
62         }
63
64         private Block getMethodDeclarationBlockOf(ASTNode statement) {
65                 ASTNode node = statement.getParent();
66                 while (!(node instanceof Block && node.getParent() instanceof MethodDeclaration))
67                         node = node.getParent();
68                 return (Block) node;
69         }
70
71         private boolean isLastReachableStatement(Statement statement) {
72                 if (!isLastStatementOfParent(statement))
73                         return false;
74
75                 ASTNode node = statement.getParent();
76                 while (isUnconditionalStatement(node) && isLastStatementOfParent(node))
77                         node = node.getParent();
78                 return node instanceof MethodDeclaration;
79         }
80
81         private boolean isUnconditionalStatement(ASTNode node) {
82                 return node instanceof Block || node instanceof LabeledStatement 
83                                 || node instanceof SynchronizedStatement || node instanceof TryStatement;
84         }
85
86         private boolean isLastStatementOfParent(ASTNode node) {
87                 if (!(node.getParent() instanceof Block))
88                         return true;
89
90                 List<?> parentStatements = ((Block) node.getParent()).statements();
91                 return node == lastElementOfList(parentStatements);
92         }
93
94         private Object lastElementOfList(List<?> list) {
95                 return list.get(list.size() - 1);
96         }
97
98         private boolean nodeIsOfHandledType(ASTNode node) {
99                 return node instanceof IfStatement || node instanceof TryStatement 
100                                 || node instanceof Block || node instanceof LabeledStatement || node instanceof DoStatement;
101         }
102
103         private boolean check(ASTNode node) {
104                 if (!nodeIsLastStatementOfParentInSelection(node))
105                         return false;
106
107                 throw new IllegalStatementFoundException(ReturnStatement.class);
108         }
109
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();
115         }
116
117         @Override
118         public boolean visit(IfStatement node) {
119                 if (!nodeIsLastStatementOfParentInSelection(node))
120                         return false;
121
122                 ReturnOrThrowStatementFinder statementFinder = new ReturnOrThrowStatementFinder();
123                 node.getThenStatement().accept(statementFinder);
124
125                 if (statementFinder.hasFoundReturnOrThrowStatement()) {
126                         Statement elseStatement = node.getElseStatement();
127
128                         if (elseStatement == null) {
129                                 throw new IllegalStatementFoundException(ReturnStatement.class);
130                         }
131
132                         statementFinder.reset();
133                         elseStatement.accept(statementFinder);
134
135                         if (!statementFinder.hasFoundReturnOrThrowStatement()) {
136                                 throw new IllegalStatementFoundException(ReturnStatement.class);
137                         }
138                 } else {
139                         throw new IllegalStatementFoundException(ReturnStatement.class);
140                 }
141
142                 return true;
143         }
144
145         @Override
146         public boolean visit(TryStatement node) {
147                 if (!nodeIsLastStatementOfParentInSelection(node))
148                         return false;
149
150                 ReturnOrThrowStatementFinder statementFinder = new ReturnOrThrowStatementFinder();
151                 node.getBody().accept(statementFinder);
152                 if (!statementFinder.hasFoundReturnOrThrowStatement())
153                         throw new IllegalStatementFoundException(ReturnStatement.class);
154
155                 for (Object obj: node.catchClauses()) {
156                         assert obj instanceof CatchClause;
157                         CatchClause catchClause = (CatchClause) obj;
158                         statementFinder.reset();
159                         catchClause.accept(statementFinder);
160
161                         if (!statementFinder.hasFoundReturnOrThrowStatement())
162                                 throw new IllegalStatementFoundException(ReturnStatement.class);
163                 }
164                 
165                 if (node.getFinally() != null) {
166                         statementFinder.reset();
167                         node.getFinally().accept(statementFinder);
168
169                         if (!statementFinder.hasFoundReturnOrThrowStatement())
170                                 throw new IllegalStatementFoundException(ReturnStatement.class);
171                 }
172                 
173                 return true;
174         }
175
176         @Override
177         public void check() throws IllegalStatementFoundException, IllegalExpressionFoundException {
178                 selection.getLastStatement().accept(this);
179         }
180 }