1 11 package org.eclipse.jdt.internal.corext.refactoring.surround; 12 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 import java.util.List ; 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 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 138 public String 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 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 164 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { 165 return Checks.validateModifiesFiles( 166 ResourceUtil.getFiles(new ICompilationUnit[]{fCUnit}), 167 getValidationContext()); 168 } 169 170 173 public Change createChange(IProgressMonitor pm) throws CoreException { 174 final String NN= ""; if (pm == null) pm= new NullProgressMonitor(); 176 pm.beginTask(NN, 2); 177 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 lineDelimiter= document.getLineDelimiter(0); 225 List result= new ArrayList (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 type= fImportRewrite.addImport(exception); 231 CatchClause catchClause= getAST().newCatchClause(); 232 tryStatement.catchClauses().add(catchClause); 233 SingleVariableDeclaration decl= getAST().newSingleVariableDeclaration(); 234 String varName= StubUtility.getExceptionVariableName(fCUnit.getJavaProject()); 235 236 String 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 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 VariableDeclarationStatement copy= (VariableDeclarationStatement)ASTNode.copySubtree(ast, statement); 256 List modifiers= copy.modifiers(); 257 for (Iterator 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 fragments= copy.fragments(); 264 for (Iterator iter= fragments.iterator(), original= statement.fragments().iterator(); iter.hasNext();) { 265 VariableDeclarationFragment fragment= (VariableDeclarationFragment)iter.next(); 266 IVariableBinding binding= ((VariableDeclarationFragment)original.next()).resolveBinding(); 267 if (true ) { 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 if (extendedStart != statement.getStartPosition() && extendedStart >= fSelection.getOffset()) { 279 String commentToken= document.get(extendedStart, statement.getStartPosition() - extendedStart); 280 commentToken= Strings.trimTrailingTabsAndSpaces(commentToken); 281 Type type= statement.getType(); 282 String typeName= document.get(type.getStartPosition(), type.getLength()); 283 copy.setType((Type)fRewriter.createStringPlaceholder(commentToken + typeName, type.getNodeType())); 284 } 285 result.add(copy); 286 fragments= statement.fragments(); 288 if (!fragments.isEmpty()) { 289 List newExpressionStatements= new ArrayList (); 290 for (Iterator 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 getSpecialVariableDeclarationStatements() { 346 List result= new ArrayList (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 type, String name, String lineSeparator) throws CoreException { 358 String 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 |