KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > surround > SurroundWithTryCatchRefactoring


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.surround;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.text.edits.MultiTextEdit;
18 import org.eclipse.text.edits.TextEdit;
19 import org.eclipse.text.edits.TextEditGroup;
20
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IPath;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.NullProgressMonitor;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.core.runtime.SubProgressMonitor;
28
29 import org.eclipse.core.filebuffers.FileBuffers;
30 import org.eclipse.core.filebuffers.ITextFileBufferManager;
31 import org.eclipse.core.filebuffers.LocationKind;
32
33 import org.eclipse.core.resources.IFile;
34
35 import org.eclipse.jface.text.BadLocationException;
36 import org.eclipse.jface.text.IDocument;
37 import org.eclipse.jface.text.ITextSelection;
38
39 import org.eclipse.ltk.core.refactoring.Change;
40 import org.eclipse.ltk.core.refactoring.Refactoring;
41 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
42 import org.eclipse.ltk.core.refactoring.TextFileChange;
43
44 import org.eclipse.jdt.core.ICompilationUnit;
45 import org.eclipse.jdt.core.JavaModelException;
46 import org.eclipse.jdt.core.dom.AST;
47 import org.eclipse.jdt.core.dom.ASTNode;
48 import org.eclipse.jdt.core.dom.Assignment;
49 import org.eclipse.jdt.core.dom.Block;
50 import org.eclipse.jdt.core.dom.CatchClause;
51 import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
52 import org.eclipse.jdt.core.dom.CompilationUnit;
53 import org.eclipse.jdt.core.dom.Expression;
54 import org.eclipse.jdt.core.dom.IExtendedModifier;
55 import org.eclipse.jdt.core.dom.ITypeBinding;
56 import org.eclipse.jdt.core.dom.IVariableBinding;
57 import org.eclipse.jdt.core.dom.Modifier;
58 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
59 import org.eclipse.jdt.core.dom.Statement;
60 import org.eclipse.jdt.core.dom.TryStatement;
61 import org.eclipse.jdt.core.dom.Type;
62 import org.eclipse.jdt.core.dom.VariableDeclaration;
63 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
64 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
65 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
66 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
67 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
68
69 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
70 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
71 import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder;
72 import org.eclipse.jdt.internal.corext.dom.Selection;
73 import org.eclipse.jdt.internal.corext.refactoring.Checks;
74 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
75 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
76 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
77 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
78 import org.eclipse.jdt.internal.corext.refactoring.util.SelectionAwareSourceRangeComputer;
79 import org.eclipse.jdt.internal.corext.util.Strings;
80
81 import org.eclipse.jdt.internal.ui.JavaPlugin;
82
83 /**
84  * Surround a set of statements with a try/catch block.
85  *
86  * Special case:
87  *
88  * URL url= file.toURL();
89  *
90  * In this case the variable declaration statement gets convert into a
91  * declaration without initializer. So the body of the try/catch block
92  * only consists of new assignments. In this case we can't move the
93  * selected nodes (e.g. the declaration) into the try block.
94  */

95 public class SurroundWithTryCatchRefactoring extends Refactoring {
96
97     private Selection fSelection;
98     private ISurroundWithTryCatchQuery fQuery;
99     private SurroundWithTryCatchAnalyzer fAnalyzer;
100     private boolean fLeaveDirty;
101
102     private ICompilationUnit fCUnit;
103     private CompilationUnit fRootNode;
104     private ASTRewrite fRewriter;
105     private ImportRewrite fImportRewrite;
106     private CodeScopeBuilder.Scope fScope;
107     private ASTNode[] fSelectedNodes;
108
109     private SurroundWithTryCatchRefactoring(ICompilationUnit cu, Selection selection, ISurroundWithTryCatchQuery query) {
110         fCUnit= cu;
111         fSelection= selection;
112         fQuery= query;
113         fLeaveDirty= false;
114     }
115
116     public static SurroundWithTryCatchRefactoring create(ICompilationUnit cu, ITextSelection selection, ISurroundWithTryCatchQuery query) {
117         return new SurroundWithTryCatchRefactoring(cu, Selection.createFromStartLength(selection.getOffset(), selection.getLength()), query);
118     }
119         
120     public static SurroundWithTryCatchRefactoring create(ICompilationUnit cu, int offset, int length, ISurroundWithTryCatchQuery query) {
121         return new SurroundWithTryCatchRefactoring(cu, Selection.createFromStartLength(offset, length), query);
122     }
123
124     public void setLeaveDirty(boolean leaveDirty) {
125         fLeaveDirty= leaveDirty;
126     }
127     
128     public boolean stopExecution() {
129         if (fAnalyzer == null)
130             return true;
131         ITypeBinding[] exceptions= fAnalyzer.getExceptions();
132         return exceptions == null || exceptions.length == 0;
133     }
134     
135     /* non Java-doc
136      * @see IRefactoring#getName()
137      */

138     public String JavaDoc getName() {
139         return RefactoringCoreMessages.SurroundWithTryCatchRefactoring_name;
140     }
141
142     public RefactoringStatus checkActivationBasics(CompilationUnit rootNode) throws JavaModelException {
143         RefactoringStatus result= new RefactoringStatus();
144         fRootNode= rootNode;
145             
146         fAnalyzer= new SurroundWithTryCatchAnalyzer(fCUnit, fSelection, fQuery);
147         fRootNode.accept(fAnalyzer);
148         result.merge(fAnalyzer.getStatus());
149         return result;
150     }
151
152
153     /*
154      * @see Refactoring#checkActivation(IProgressMonitor)
155      */

156     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
157         CompilationUnit rootNode= new RefactoringASTParser(AST.JLS3).parse(fCUnit, true, pm);
158         return checkActivationBasics(rootNode);
159     }
160
161     /*
162      * @see Refactoring#checkInput(IProgressMonitor)
163      */

164     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
165         return Checks.validateModifiesFiles(
166             ResourceUtil.getFiles(new ICompilationUnit[]{fCUnit}),
167             getValidationContext());
168     }
169
170     /* non Java-doc
171      * @see IRefactoring#createChange(IProgressMonitor)
172      */

173     public Change createChange(IProgressMonitor pm) throws CoreException {
174         final String JavaDoc NN= ""; //$NON-NLS-1$
175
if (pm == null) pm= new NullProgressMonitor();
176         pm.beginTask(NN, 2);
177         // This is cheap since the compilation unit is already open in a editor.
178
IPath path= getFile().getFullPath();
179         ITextFileBufferManager bufferManager= FileBuffers.getTextFileBufferManager();
180         try {
181             bufferManager.connect(path, LocationKind.IFILE, new SubProgressMonitor(pm, 1));
182             IDocument document= bufferManager.getTextFileBuffer(path, LocationKind.IFILE).getDocument();
183             final CompilationUnitChange result= new CompilationUnitChange(getName(), fCUnit);
184             if (fLeaveDirty)
185                 result.setSaveMode(TextFileChange.LEAVE_DIRTY);
186             MultiTextEdit root= new MultiTextEdit();
187             result.setEdit(root);
188             fRewriter= ASTRewrite.create(fAnalyzer.getEnclosingBodyDeclaration().getAST());
189             fRewriter.setTargetSourceRangeComputer(new SelectionAwareSourceRangeComputer(
190                 fAnalyzer.getSelectedNodes(), document, fSelection.getOffset(), fSelection.getLength()));
191             fImportRewrite= StubUtility.createImportRewrite(fRootNode, true);
192             
193             fScope= CodeScopeBuilder.perform(fAnalyzer.getEnclosingBodyDeclaration(), fSelection).
194                 findScope(fSelection.getOffset(), fSelection.getLength());
195             fScope.setCursor(fSelection.getOffset());
196             
197             fSelectedNodes= fAnalyzer.getSelectedNodes();
198             
199             createTryCatchStatement(document);
200             
201             if (fImportRewrite.hasRecordedChanges()) {
202                 TextEdit edit= fImportRewrite.rewriteImports(null);
203                 root.addChild(edit);
204                 result.addTextEditGroup(new TextEditGroup(NN, new TextEdit[] {edit} ));
205             }
206             TextEdit change= fRewriter.rewriteAST(document, fCUnit.getJavaProject().getOptions(true));
207             root.addChild(change);
208             result.addTextEditGroup(new TextEditGroup(NN, new TextEdit[] {change} ));
209             return result;
210         } catch (BadLocationException e) {
211             throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR,
212                 e.getMessage(), e));
213         } finally {
214             bufferManager.disconnect(path, LocationKind.IFILE, new SubProgressMonitor(pm, 1));
215             pm.done();
216         }
217     }
218     
219     private AST getAST() {
220         return fRootNode.getAST();
221     }
222     
223     private void createTryCatchStatement(IDocument document) throws CoreException, BadLocationException {
224         String JavaDoc lineDelimiter= document.getLineDelimiter(0);
225         List JavaDoc result= new ArrayList JavaDoc(1);
226         TryStatement tryStatement= getAST().newTryStatement();
227         ITypeBinding[] exceptions= fAnalyzer.getExceptions();
228         for (int i= 0; i < exceptions.length; i++) {
229             ITypeBinding exception= exceptions[i];
230             String JavaDoc type= fImportRewrite.addImport(exception);
231             CatchClause catchClause= getAST().newCatchClause();
232             tryStatement.catchClauses().add(catchClause);
233             SingleVariableDeclaration decl= getAST().newSingleVariableDeclaration();
234             String JavaDoc varName= StubUtility.getExceptionVariableName(fCUnit.getJavaProject());
235             
236             String JavaDoc name= fScope.createName(varName, false);
237             decl.setName(getAST().newSimpleName(name));
238             decl.setType(ASTNodeFactory.newType(getAST(), type));
239             catchClause.setException(decl);
240             Statement st= getCatchBody(type, name, lineDelimiter);
241             if (st != null) {
242                 catchClause.getBody().statements().add(st);
243             }
244         }
245         List JavaDoc variableDeclarations= getSpecialVariableDeclarationStatements();
246         ListRewrite statements= fRewriter.getListRewrite(tryStatement.getBody(), Block.STATEMENTS_PROPERTY);
247         boolean selectedNodeRemoved= false;
248         ASTNode expressionStatement= null;
249         for (int i= 0; i < fSelectedNodes.length; i++) {
250             ASTNode node= fSelectedNodes[i];
251             if (node instanceof VariableDeclarationStatement && variableDeclarations.contains(node)) {
252                 AST ast= getAST();
253                 VariableDeclarationStatement statement= (VariableDeclarationStatement)node;
254                 // Create a copy and remove the initializer
255
VariableDeclarationStatement copy= (VariableDeclarationStatement)ASTNode.copySubtree(ast, statement);
256                 List JavaDoc modifiers= copy.modifiers();
257                 for (Iterator JavaDoc iter= modifiers.iterator(); iter.hasNext();) {
258                     IExtendedModifier modifier= (IExtendedModifier) iter.next();
259                     if (modifier.isModifier() && Modifier.isFinal(((Modifier)modifier).getKeyword().toFlagValue())) {
260                         iter.remove();
261                     }
262                 }
263                 List JavaDoc fragments= copy.fragments();
264                 for (Iterator JavaDoc iter= fragments.iterator(), original= statement.fragments().iterator(); iter.hasNext();) {
265                     VariableDeclarationFragment fragment= (VariableDeclarationFragment)iter.next();
266                     IVariableBinding binding= ((VariableDeclarationFragment)original.next()).resolveBinding();
267                     // If we want to initialize the new local then we should do a flow analysis upfront
268
// to decide if the first access is a read or write.
269
if (true /* binding == null */) {
270                         fragment.setInitializer(null);
271                     } else {
272                         fragment.setInitializer(ASTNodeFactory.newDefaultExpression(ast, binding.getType()));
273                     }
274                 }
275                 CompilationUnit root= (CompilationUnit)statement.getRoot();
276                 int extendedStart= root.getExtendedStartPosition(statement);
277                 // we have a leading comment and the comment is covered by the selection
278
if (extendedStart != statement.getStartPosition() && extendedStart >= fSelection.getOffset()) {
279                     String JavaDoc commentToken= document.get(extendedStart, statement.getStartPosition() - extendedStart);
280                     commentToken= Strings.trimTrailingTabsAndSpaces(commentToken);
281                     Type type= statement.getType();
282                     String JavaDoc typeName= document.get(type.getStartPosition(), type.getLength());
283                     copy.setType((Type)fRewriter.createStringPlaceholder(commentToken + typeName, type.getNodeType()));
284                 }
285                 result.add(copy);
286                 // convert the fragments into expression statements
287
fragments= statement.fragments();
288                 if (!fragments.isEmpty()) {
289                     List JavaDoc newExpressionStatements= new ArrayList JavaDoc();
290                     for (Iterator JavaDoc iter= fragments.iterator(); iter.hasNext();) {
291                         VariableDeclarationFragment fragment= (VariableDeclarationFragment)iter.next();
292                         Expression initializer= fragment.getInitializer();
293                         if (initializer != null) {
294                             Assignment assignment= ast.newAssignment();
295                             assignment.setLeftHandSide((Expression)fRewriter.createCopyTarget(fragment.getName()));
296                             assignment.setRightHandSide((Expression)fRewriter.createCopyTarget(initializer));
297                             newExpressionStatements.add(ast.newExpressionStatement(assignment));
298                         }
299                     }
300                     if (!newExpressionStatements.isEmpty()) {
301                         if (fSelectedNodes.length == 1) {
302                             expressionStatement= fRewriter.createGroupNode((ASTNode[])newExpressionStatements.toArray(new ASTNode[newExpressionStatements.size()]));
303                         } else {
304                             fRewriter.replace(
305                                 statement,
306                                 fRewriter.createGroupNode((ASTNode[])newExpressionStatements.toArray(new ASTNode[newExpressionStatements.size()])),
307                                 null);
308                         }
309                     } else {
310                         fRewriter.remove(statement, null);
311                         selectedNodeRemoved= true;
312                     }
313                 } else {
314                     fRewriter.remove(statement, null);
315                     selectedNodeRemoved= true;
316                 }
317             }
318         }
319         result.add(tryStatement);
320         ASTNode replacementNode;
321         if (result.size() == 1) {
322             replacementNode= (ASTNode)result.get(0);
323         } else {
324             replacementNode= fRewriter.createGroupNode((ASTNode[])result.toArray(new ASTNode[result.size()]));
325         }
326         if (fSelectedNodes.length == 1) {
327             if (expressionStatement != null) {
328                 statements.insertLast(expressionStatement, null);
329             } else {
330                 if (!selectedNodeRemoved)
331                     statements.insertLast(fRewriter.createMoveTarget(fSelectedNodes[0]), null);
332             }
333             fRewriter.replace(fSelectedNodes[0], replacementNode, null);
334         } else {
335             ListRewrite source= fRewriter.getListRewrite(
336                 fSelectedNodes[0].getParent(),
337                 (ChildListPropertyDescriptor)fSelectedNodes[0].getLocationInParent());
338             ASTNode toMove= source.createMoveTarget(
339                 fSelectedNodes[0], fSelectedNodes[fSelectedNodes.length - 1],
340                 replacementNode, null);
341             statements.insertLast(toMove, null);
342         }
343     }
344     
345     private List JavaDoc getSpecialVariableDeclarationStatements() {
346         List JavaDoc result= new ArrayList JavaDoc(3);
347         VariableDeclaration[] locals= fAnalyzer.getAffectedLocals();
348         for (int i= 0; i < locals.length; i++) {
349             ASTNode parent= locals[i].getParent();
350             if (parent instanceof VariableDeclarationStatement && !result.contains(parent))
351                 result.add(parent);
352         }
353         return result;
354         
355     }
356     
357     private Statement getCatchBody(String JavaDoc type, String JavaDoc name, String JavaDoc lineSeparator) throws CoreException {
358         String JavaDoc s= StubUtility.getCatchBodyContent(fCUnit, type, name, fSelectedNodes[0], lineSeparator);
359         if (s == null) {
360             return null;
361         } else {
362             return (Statement)fRewriter.createStringPlaceholder(s, ASTNode.RETURN_STATEMENT);
363         }
364     }
365     
366     private IFile getFile() {
367         return (IFile) fCUnit.getPrimary().getResource();
368     }
369 }
370
Popular Tags