1 11 package org.eclipse.jdt.internal.corext.refactoring.rename; 12 13 import java.util.StringTokenizer ; 14 15 import org.eclipse.text.edits.MultiTextEdit; 16 import org.eclipse.text.edits.ReplaceEdit; 17 import org.eclipse.text.edits.TextEdit; 18 import org.eclipse.text.edits.TextEditGroup; 19 20 import org.eclipse.core.runtime.Assert; 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.OperationCanceledException; 24 25 import org.eclipse.core.resources.IFile; 26 27 import org.eclipse.ltk.core.refactoring.Change; 28 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 29 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; 30 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 31 import org.eclipse.ltk.core.refactoring.TextChange; 32 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; 33 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 34 import org.eclipse.ltk.core.refactoring.participants.RenameArguments; 35 36 import org.eclipse.jdt.core.ICompilationUnit; 37 import org.eclipse.jdt.core.IJavaElement; 38 import org.eclipse.jdt.core.IJavaProject; 39 import org.eclipse.jdt.core.ILocalVariable; 40 import org.eclipse.jdt.core.IMethod; 41 import org.eclipse.jdt.core.ISourceRange; 42 import org.eclipse.jdt.core.JavaModelException; 43 import org.eclipse.jdt.core.dom.ASTNode; 44 import org.eclipse.jdt.core.dom.CompilationUnit; 45 import org.eclipse.jdt.core.dom.Initializer; 46 import org.eclipse.jdt.core.dom.MethodDeclaration; 47 import org.eclipse.jdt.core.dom.VariableDeclaration; 48 import org.eclipse.jdt.core.refactoring.IJavaRefactorings; 49 import org.eclipse.jdt.core.refactoring.descriptors.RenameLocalVariableDescriptor; 50 51 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 52 import org.eclipse.jdt.internal.corext.refactoring.Checks; 53 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptor; 54 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; 55 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; 56 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; 57 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 58 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; 59 import org.eclipse.jdt.internal.corext.refactoring.changes.RefactoringDescriptorChange; 60 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility; 61 import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; 62 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors; 63 import org.eclipse.jdt.internal.corext.refactoring.rename.RenameAnalyzeUtil.LocalAnalyzePackage; 64 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating; 65 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 66 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 67 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 68 import org.eclipse.jdt.internal.corext.util.Messages; 69 70 import org.eclipse.jdt.ui.JavaElementLabels; 71 72 import org.eclipse.jdt.internal.ui.JavaPlugin; 73 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper; 74 75 public class RenameLocalVariableProcessor extends JavaRenameProcessor implements IReferenceUpdating { 76 77 private ILocalVariable fLocalVariable; 78 private ICompilationUnit fCu; 79 80 private boolean fUpdateReferences; 82 private String fCurrentName; 83 private String fNewName; 84 private CompilationUnit fCompilationUnitNode; 85 private VariableDeclaration fTempDeclarationNode; 86 private TextChange fChange; 87 88 private boolean fIsComposite; 89 private GroupCategorySet fCategorySet; 90 private TextChangeManager fChangeManager; 91 private RenameAnalyzeUtil.LocalAnalyzePackage fLocalAnalyzePackage; 92 93 public static final String IDENTIFIER= "org.eclipse.jdt.ui.renameLocalVariableProcessor"; 95 99 public RenameLocalVariableProcessor(ILocalVariable localVariable) { 100 fLocalVariable= localVariable; 101 fUpdateReferences= true; 102 if (localVariable != null) 103 fCu= (ICompilationUnit) localVariable.getAncestor(IJavaElement.COMPILATION_UNIT); 104 fNewName= ""; fIsComposite= false; 106 } 107 108 119 RenameLocalVariableProcessor(ILocalVariable localVariable, TextChangeManager manager, CompilationUnit node, GroupCategorySet categorySet) { 120 this(localVariable); 121 fChangeManager= manager; 122 fCategorySet= categorySet; 123 fCompilationUnitNode= node; 124 fIsComposite= true; 125 } 126 127 130 protected final String [] getAffectedProjectNatures() throws CoreException { 131 return JavaProcessors.computeAffectedNatures(fLocalVariable); 132 } 133 134 137 public Object [] getElements() { 138 return new Object [] { fLocalVariable }; 139 } 140 141 144 public String getIdentifier() { 145 return IDENTIFIER; 146 } 147 148 151 public String getProcessorName() { 152 return RefactoringCoreMessages.RenameTempRefactoring_rename; 153 } 154 155 158 public boolean isApplicable() throws CoreException { 159 return RefactoringAvailabilityTester.isRenameAvailable(fLocalVariable); 160 } 161 162 165 public boolean canEnableUpdateReferences() { 166 return true; 167 } 168 169 172 public boolean getUpdateReferences() { 173 return fUpdateReferences; 174 } 175 176 179 public void setUpdateReferences(boolean updateReferences) { 180 fUpdateReferences= updateReferences; 181 } 182 183 186 public String getCurrentElementName() { 187 return fCurrentName; 188 } 189 190 193 public String getNewElementName() { 194 return fNewName; 195 } 196 197 200 public void setNewElementName(String newName) { 201 Assert.isNotNull(newName); 202 fNewName= newName; 203 } 204 205 208 public Object getNewElement() { 209 return null; } 211 212 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { 213 initAST(); 214 if (fTempDeclarationNode == null || fTempDeclarationNode.resolveBinding() == null) 215 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenameTempRefactoring_must_select_local); 216 if (! Checks.isDeclaredIn(fTempDeclarationNode, MethodDeclaration.class) 217 && ! Checks.isDeclaredIn(fTempDeclarationNode, Initializer.class)) 218 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenameTempRefactoring_only_in_methods_and_initializers); 219 220 initNames(); 221 return new RefactoringStatus(); 222 } 223 224 private void initAST() throws JavaModelException { 225 if (!fIsComposite) 226 fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, null); 227 ISourceRange sourceRange= fLocalVariable.getNameRange(); 228 ASTNode name= NodeFinder.perform(fCompilationUnitNode, sourceRange); 229 if (name == null) 230 return; 231 if (name.getParent() instanceof VariableDeclaration) 232 fTempDeclarationNode= (VariableDeclaration) name.getParent(); 233 } 234 235 private void initNames(){ 236 fCurrentName= fTempDeclarationNode.getName().getIdentifier(); 237 } 238 239 protected RenameModifications computeRenameModifications() throws CoreException { 240 RenameModifications result= new RenameModifications(); 241 result.rename(fLocalVariable, new RenameArguments(getNewElementName(), getUpdateReferences())); 242 return result; 243 } 244 245 protected IFile[] getChangedFiles() throws CoreException { 246 return new IFile[] {ResourceUtil.getFile(fCu)}; 247 } 248 249 public int getSaveMode() { 250 return RefactoringSaveHelper.SAVE_NOTHING; 251 } 252 253 protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) 254 throws CoreException, OperationCanceledException { 255 try { 256 pm.beginTask("", 1); 258 RefactoringStatus result= checkNewElementName(fNewName); 259 if (result.hasFatalError()) 260 return result; 261 createEdits(); 262 if (!fIsComposite) { 263 LocalAnalyzePackage[] localAnalyzePackages= new RenameAnalyzeUtil.LocalAnalyzePackage[] { fLocalAnalyzePackage }; 264 result.merge(RenameAnalyzeUtil.analyzeLocalRenames(localAnalyzePackages, fChange, fCompilationUnitNode, true)); 265 } 266 return result; 267 } finally { 268 pm.done(); 269 if (fIsComposite) { 270 fChange= null; 272 fCompilationUnitNode= null; 273 fTempDeclarationNode= null; 274 } 275 } 276 } 277 278 281 public RefactoringStatus checkNewElementName(String newName) throws JavaModelException { 282 RefactoringStatus result= Checks.checkFieldName(newName); 283 if (! Checks.startsWithLowerCase(newName)) 284 if (fIsComposite) { 285 final String nameOfParent= (fLocalVariable.getParent() instanceof IMethod) ? fLocalVariable.getParent().getElementName() : RefactoringCoreMessages.JavaElementUtil_initializer; 286 final String nameOfType= fLocalVariable.getAncestor(IJavaElement.TYPE).getElementName(); 287 result.addWarning(Messages.format(RefactoringCoreMessages.RenameTempRefactoring_lowercase2, new String [] { newName, nameOfParent, nameOfType })); 288 } else { 289 result.addWarning(RefactoringCoreMessages.RenameTempRefactoring_lowercase); 290 } 291 return result; 292 } 293 294 private void createEdits() { 295 TextEdit declarationEdit= createRenameEdit(fTempDeclarationNode.getName().getStartPosition()); 296 TextEdit[] allRenameEdits= getAllRenameEdits(declarationEdit); 297 298 TextEdit[] allUnparentedRenameEdits= new TextEdit[allRenameEdits.length]; 299 TextEdit unparentedDeclarationEdit= null; 300 301 fChange= new CompilationUnitChange(RefactoringCoreMessages.RenameTempRefactoring_rename, fCu); 302 MultiTextEdit rootEdit= new MultiTextEdit(); 303 fChange.setEdit(rootEdit); 304 fChange.setKeepPreviewEdits(true); 305 306 for (int i= 0; i < allRenameEdits.length; i++) { 307 if (fIsComposite) { 308 TextChangeCompatibility.addTextEdit(fChangeManager.get(fCu), RefactoringCoreMessages.RenameTempRefactoring_changeName, allRenameEdits[i].copy(), fCategorySet); 311 312 allUnparentedRenameEdits[i]= allRenameEdits[i].copy(); 314 if (allRenameEdits[i].equals(declarationEdit)) 315 unparentedDeclarationEdit= allUnparentedRenameEdits[i]; 316 } 317 rootEdit.addChild(allRenameEdits[i]); 318 fChange.addTextEditGroup(new TextEditGroup(RefactoringCoreMessages.RenameTempRefactoring_changeName, allRenameEdits[i])); 319 } 320 321 if (fIsComposite) { 323 fLocalAnalyzePackage= new RenameAnalyzeUtil.LocalAnalyzePackage(unparentedDeclarationEdit, allUnparentedRenameEdits); 324 } else 325 fLocalAnalyzePackage= new RenameAnalyzeUtil.LocalAnalyzePackage(declarationEdit, allRenameEdits); 326 } 327 328 private TextEdit[] getAllRenameEdits(TextEdit declarationEdit) { 329 if (! fUpdateReferences) 330 return new TextEdit[] { declarationEdit }; 331 332 TempOccurrenceAnalyzer fTempAnalyzer= new TempOccurrenceAnalyzer(fTempDeclarationNode, true); 333 fTempAnalyzer.perform(); 334 int[] referenceOffsets= fTempAnalyzer.getReferenceAndJavadocOffsets(); 335 336 TextEdit[] allRenameEdits= new TextEdit[referenceOffsets.length + 1]; 337 for (int i= 0; i < referenceOffsets.length; i++) 338 allRenameEdits[i]= createRenameEdit(referenceOffsets[i]); 339 allRenameEdits[referenceOffsets.length]= declarationEdit; 340 return allRenameEdits; 341 } 342 343 private TextEdit createRenameEdit(int offset) { 344 return new ReplaceEdit(offset, fCurrentName.length(), fNewName); 345 } 346 347 public Change createChange(IProgressMonitor monitor) throws CoreException { 348 try { 349 monitor.beginTask(RefactoringCoreMessages.RenameTypeProcessor_creating_changes, 1); 350 Change change= fChange; 351 if (change != null) { 352 final ISourceRange range= fLocalVariable.getNameRange(); 353 String project= null; 354 IJavaProject javaProject= fCu.getJavaProject(); 355 if (javaProject != null) 356 project= javaProject.getElementName(); 357 final String header= Messages.format(RefactoringCoreMessages.RenameLocalVariableProcessor_descriptor_description, new String [] { fCurrentName, JavaElementLabels.getElementLabel(fLocalVariable.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED), fNewName}); 358 final String description= Messages.format(RefactoringCoreMessages.RenameLocalVariableProcessor_descriptor_description_short, fCurrentName); 359 final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString(); 360 final RenameLocalVariableDescriptor descriptor= new RenameLocalVariableDescriptor(); 361 descriptor.setProject(project); 362 descriptor.setDescription(description); 363 descriptor.setComment(comment); 364 descriptor.setFlags(RefactoringDescriptor.NONE); 365 descriptor.setCompilationUnit(fCu); 366 descriptor.setNewName(getNewElementName()); 367 descriptor.setSelection(range); 368 descriptor.setUpdateReferences(fUpdateReferences); 369 final RefactoringDescriptorChange result= new RefactoringDescriptorChange(descriptor, RefactoringCoreMessages.RenameTempRefactoring_rename, new Change[] { change}); 370 result.markAsSynthetic(); 371 change= result; 372 } 373 return change; 374 } finally { 375 monitor.done(); 376 } 377 } 378 379 public RefactoringStatus initialize(RefactoringArguments arguments) { 380 if (arguments instanceof JavaRefactoringArguments) { 381 final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; 382 final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT); 383 if (handle != null) { 384 final IJavaElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); 385 if (element != null && element.exists()) { 386 if (element.getElementType() == IJavaElement.COMPILATION_UNIT) { 387 fCu= (ICompilationUnit) element; 388 } else if (element.getElementType() == IJavaElement.LOCAL_VARIABLE) { 389 fLocalVariable= (ILocalVariable) element; 390 fCu= (ICompilationUnit) fLocalVariable.getAncestor(IJavaElement.COMPILATION_UNIT); 391 if (fCu == null) 392 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_LOCAL_VARIABLE); 393 } else 394 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_LOCAL_VARIABLE); 395 } else 396 return ScriptableRefactoring.createInputFatalStatus(element, getRefactoring().getName(), IJavaRefactorings.RENAME_LOCAL_VARIABLE); 397 } else 398 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT)); 399 final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME); 400 if (name != null && !"".equals(name)) setNewElementName(name); 402 else 403 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME)); 404 if (fCu != null && fLocalVariable == null) { 405 final String selection= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION); 406 if (selection != null) { 407 int offset= -1; 408 int length= -1; 409 final StringTokenizer tokenizer= new StringTokenizer (selection); 410 if (tokenizer.hasMoreTokens()) 411 offset= Integer.valueOf(tokenizer.nextToken()).intValue(); 412 if (tokenizer.hasMoreTokens()) 413 length= Integer.valueOf(tokenizer.nextToken()).intValue(); 414 if (offset >= 0 && length >= 0) { 415 try { 416 final IJavaElement[] elements= fCu.codeSelect(offset, length); 417 if (elements != null) { 418 for (int index= 0; index < elements.length; index++) { 419 final IJavaElement element= elements[index]; 420 if (element instanceof ILocalVariable) 421 fLocalVariable= (ILocalVariable) element; 422 } 423 } 424 if (fLocalVariable == null) 425 return ScriptableRefactoring.createInputFatalStatus(null, getRefactoring().getName(), IJavaRefactorings.RENAME_LOCAL_VARIABLE); 426 } catch (JavaModelException exception) { 427 JavaPlugin.log(exception); 428 } 429 } else 430 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object [] { selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION})); 431 } else 432 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION)); 433 } 434 final String references= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES); 435 if (references != null) { 436 fUpdateReferences= Boolean.valueOf(references).booleanValue(); 437 } else 438 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_REFERENCES)); 439 } else 440 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); 441 return new RefactoringStatus(); 442 } 443 444 public RenameAnalyzeUtil.LocalAnalyzePackage getLocalAnalyzePackage() { 445 return fLocalAnalyzePackage; 446 } 447 } 448 | Popular Tags |