]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/util/StatementAnalyzer.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / util / StatementAnalyzer.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.jdt.internal.corext.refactoring.util;
12
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.util.List;
16
17import org.eclipse.core.runtime.Assert;
18import org.eclipse.core.runtime.CoreException;
19
20import org.eclipse.ltk.core.refactoring.RefactoringStatus;
21import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
22
23import org.eclipse.jdt.core.ICompilationUnit;
24import org.eclipse.jdt.core.ISourceRange;
25import org.eclipse.jdt.core.SourceRange;
26import org.eclipse.jdt.core.compiler.IScanner;
27import org.eclipse.jdt.core.dom.ASTNode;
28import org.eclipse.jdt.core.dom.CatchClause;
29import org.eclipse.jdt.core.dom.CompilationUnit;
30import org.eclipse.jdt.core.dom.DoStatement;
31import org.eclipse.jdt.core.dom.Expression;
32import org.eclipse.jdt.core.dom.ForStatement;
33import org.eclipse.jdt.core.dom.Statement;
34import org.eclipse.jdt.core.dom.SwitchCase;
35import org.eclipse.jdt.core.dom.SwitchStatement;
36import org.eclipse.jdt.core.dom.SynchronizedStatement;
37import org.eclipse.jdt.core.dom.TryStatement;
38import org.eclipse.jdt.core.dom.WhileStatement;
39
40import org.eclipse.jdt.internal.corext.dom.ASTNodes;
41import org.eclipse.jdt.internal.corext.dom.Selection;
42import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
43import org.eclipse.jdt.internal.corext.dom.TokenScanner;
44import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
45import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
46
47/**
48 * Analyzer to check if a selection covers a valid set of statements of an abstract syntax
49 * tree. The selection is valid iff
50 * <ul>
51 * <li>it does not start or end in the middle of a comment.</li>
52 * <li>no extract characters except the empty statement ";" is included in the selection.</li>
53 * </ul>
54 */
55public class StatementAnalyzer extends SelectionAnalyzer {
56
57 protected ICompilationUnit fCUnit;
58 private TokenScanner fScanner;
59 private RefactoringStatus fStatus;
60
61 public StatementAnalyzer(ICompilationUnit cunit, Selection selection, boolean traverseSelectedNode) throws CoreException {
62 super(selection, traverseSelectedNode);
63 Assert.isNotNull(cunit);
64 fCUnit= cunit;
65 fStatus= new RefactoringStatus();
66 fScanner= new TokenScanner(fCUnit);
67 }
68
69 protected void checkSelectedNodes() {
70 ASTNode[] nodes= getSelectedNodes();
71 if (nodes.length == 0)
72 return;
73
74 ASTNode node= nodes[0];
75 int selectionOffset= getSelection().getOffset();
76 try {
77 int start= fScanner.getNextStartOffset(selectionOffset, true);
78 if (start == node.getStartPosition()) {
79 int lastNodeEnd= ASTNodes.getExclusiveEnd(nodes[nodes.length - 1]);
80 int pos= fScanner.getNextStartOffset(lastNodeEnd, true);
81 int selectionEnd= getSelection().getInclusiveEnd();
82 if (pos <= selectionEnd) {
83 IScanner scanner= fScanner.getScanner();
84 char[] token= scanner.getCurrentTokenSource(); //see https://bugs.eclipse.org/324237
85 if (start < lastNodeEnd && token.length == 1 && (token[0] == ';' || token[0] == ',')) {
86 setSelection(Selection.createFromStartEnd(start, lastNodeEnd - 1));
87 } else {
88 ISourceRange range= new SourceRange(lastNodeEnd, pos - lastNodeEnd);
89 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_end_of_selection, JavaStatusContext.create(fCUnit, range));
90 }
91 }
92 return; // success
93 }
94 } catch (CoreException e) {
95 // fall through
96 }
97 ISourceRange range= new SourceRange(selectionOffset, node.getStartPosition() - selectionOffset + 1);
98 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_beginning_of_selection, JavaStatusContext.create(fCUnit, range));
99 }
100
101 public RefactoringStatus getStatus() {
102 return fStatus;
103 }
104
105 protected ICompilationUnit getCompilationUnit() {
106 return fCUnit;
107 }
108
109 protected TokenScanner getTokenScanner() {
110 return fScanner;
111 }
112
113 /* (non-Javadoc)
114 * Method declared in ASTVisitor
115 */
116 @Override
117 public void endVisit(CompilationUnit node) {
118 if (!hasSelectedNodes()) {
119 super.endVisit(node);
120 return;
121 }
122 ASTNode selectedNode= getFirstSelectedNode();
123 Selection selection= getSelection();
124 if (node != selectedNode) {
125 ASTNode parent= selectedNode.getParent();
126 fStatus.merge(CommentAnalyzer.perform(selection, fScanner.getScanner(), parent.getStartPosition(), parent.getLength()));
127 }
128 if (!fStatus.hasFatalError())
129 checkSelectedNodes();
130 super.endVisit(node);
131 }
132
133 /* (non-Javadoc)
134 * Method declared in ASTVisitor
135 */
136 @Override
137 public void endVisit(DoStatement node) {
138 ASTNode[] selectedNodes= getSelectedNodes();
139 if (doAfterValidation(node, selectedNodes)) {
140 if (contains(selectedNodes, node.getBody()) && contains(selectedNodes, node.getExpression())) {
141 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_do_body_expression);
142 }
143 }
144 super.endVisit(node);
145 }
146
147 /* (non-Javadoc)
148 * Method declared in ASTVisitor
149 */
150 @Override
151 public void endVisit(ForStatement node) {
152 ASTNode[] selectedNodes= getSelectedNodes();
153 if (doAfterValidation(node, selectedNodes)) {
154 boolean containsExpression= contains(selectedNodes, node.getExpression());
155 boolean containsUpdaters= contains(selectedNodes, node.updaters());
156 if (contains(selectedNodes, node.initializers()) && containsExpression) {
157 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_for_initializer_expression);
158 } else if (containsExpression && containsUpdaters) {
159 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_for_expression_updater);
160 } else if (containsUpdaters && contains(selectedNodes, node.getBody())) {
161 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_for_updater_body);
162 }
163 }
164 super.endVisit(node);
165 }
166
167 /* (non-Javadoc)
168 * Method declared in ASTVisitor
169 */
170 @Override
171 public void endVisit(SwitchStatement node) {
172 ASTNode[] selectedNodes= getSelectedNodes();
173 if (doAfterValidation(node, selectedNodes)) {
174 List<SwitchCase> cases= getSwitchCases(node);
175 for (int i= 0; i < selectedNodes.length; i++) {
176 ASTNode topNode= selectedNodes[i];
177 if (cases.contains(topNode)) {
178 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_switch_statement);
179 break;
180 }
181 }
182 }
183 super.endVisit(node);
184 }
185
186 /* (non-Javadoc)
187 * Method declared in ASTVisitor
188 */
189 @Override
190 public void endVisit(SynchronizedStatement node) {
191 ASTNode firstSelectedNode= getFirstSelectedNode();
192 if (getSelection().getEndVisitSelectionMode(node) == Selection.SELECTED) {
193 if (firstSelectedNode == node.getBody()) {
194 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_synchronized_statement);
195 }
196 }
197 super.endVisit(node);
198 }
199
200 /* (non-Javadoc)
201 * Method declared in ASTVisitor
202 */
203 @Override
204 public void endVisit(TryStatement node) {
205 ASTNode firstSelectedNode= getFirstSelectedNode();
206 if (getSelection().getEndVisitSelectionMode(node) == Selection.AFTER) {
207 if (firstSelectedNode == node.getBody() || firstSelectedNode == node.getFinally()) {
208 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_try_statement);
209 } else {
210 List<CatchClause> catchClauses= node.catchClauses();
211 for (Iterator<CatchClause> iterator= catchClauses.iterator(); iterator.hasNext();) {
212 CatchClause element= iterator.next();
213 if (element == firstSelectedNode || element.getBody() == firstSelectedNode) {
214 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_try_statement);
215 } else if (element.getException() == firstSelectedNode) {
216 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_catch_argument);
217 }
218 }
219 }
220 }
221 super.endVisit(node);
222 }
223
224 /* (non-Javadoc)
225 * Method declared in ASTVisitor
226 */
227 @Override
228 public void endVisit(WhileStatement node) {
229 ASTNode[] selectedNodes= getSelectedNodes();
230 if (doAfterValidation(node, selectedNodes)) {
231 if (contains(selectedNodes, node.getExpression()) && contains(selectedNodes, node.getBody())) {
232 invalidSelection(RefactoringCoreMessages.StatementAnalyzer_while_expression_body);
233 }
234 }
235 super.endVisit(node);
236 }
237
238 private boolean doAfterValidation(ASTNode node, ASTNode[] selectedNodes) {
239 return selectedNodes.length > 0 && node == selectedNodes[0].getParent() && getSelection().getEndVisitSelectionMode(node) == Selection.AFTER;
240 }
241
242 protected void invalidSelection(String message) {
243 fStatus.addFatalError(message);
244 reset();
245 }
246
247 protected void invalidSelection(String message, RefactoringStatusContext context) {
248 fStatus.addFatalError(message, context);
249 reset();
250 }
251
252 private static List<SwitchCase> getSwitchCases(SwitchStatement node) {
253 List<SwitchCase> result= new ArrayList<SwitchCase>();
254 for (Iterator<Statement> iter= node.statements().iterator(); iter.hasNext(); ) {
255 Object element= iter.next();
256 if (element instanceof SwitchCase)
257 result.add((SwitchCase) element);
258 }
259 return result;
260 }
261
262 protected static boolean contains(ASTNode[] nodes, ASTNode node) {
263 for (int i = 0; i < nodes.length; i++) {
264 if (nodes[i] == node)
265 return true;
266 }
267 return false;
268 }
269
270 protected static boolean contains(ASTNode[] nodes, List<Expression> list) {
271 for (int i = 0; i < nodes.length; i++) {
272 if (list.contains(nodes[i]))
273 return true;
274 }
275 return false;
276 }
277}