1 11 package org.eclipse.jdt.internal.ui.text.correction; 12 13 14 import java.util.ArrayList ; 15 import java.util.Collections ; 16 import java.util.Hashtable ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Set ; 20 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.IStatus; 24 import org.eclipse.core.runtime.MultiStatus; 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.resources.IFile; 30 import org.eclipse.core.resources.IMarker; 31 import org.eclipse.core.resources.IResource; 32 33 import org.eclipse.swt.graphics.Image; 34 35 import org.eclipse.jface.dialogs.ErrorDialog; 36 37 import org.eclipse.jface.text.IDocument; 38 import org.eclipse.jface.text.Position; 39 import org.eclipse.jface.text.source.IAnnotationModel; 40 41 import org.eclipse.ui.IEditorInput; 42 import org.eclipse.ui.IEditorPart; 43 import org.eclipse.ui.IMarkerResolution; 44 import org.eclipse.ui.IMarkerResolutionGenerator; 45 import org.eclipse.ui.IMarkerResolutionGenerator2; 46 import org.eclipse.ui.texteditor.ITextEditor; 47 import org.eclipse.ui.texteditor.MarkerUtilities; 48 49 import org.eclipse.ui.views.markers.WorkbenchMarkerResolution; 50 51 import org.eclipse.ltk.core.refactoring.Change; 52 import org.eclipse.ltk.core.refactoring.CompositeChange; 53 import org.eclipse.ltk.core.refactoring.PerformChangeOperation; 54 import org.eclipse.ltk.core.refactoring.RefactoringCore; 55 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 56 import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; 57 import org.eclipse.ltk.core.refactoring.TextChange; 58 59 import org.eclipse.jdt.core.CorrectionEngine; 60 import org.eclipse.jdt.core.ICompilationUnit; 61 import org.eclipse.jdt.core.IJavaElement; 62 import org.eclipse.jdt.core.IJavaModelMarker; 63 import org.eclipse.jdt.core.IJavaProject; 64 import org.eclipse.jdt.core.JavaCore; 65 import org.eclipse.jdt.core.JavaModelException; 66 import org.eclipse.jdt.core.compiler.IProblem; 67 import org.eclipse.jdt.core.dom.ASTParser; 68 import org.eclipse.jdt.core.dom.ASTRequestor; 69 import org.eclipse.jdt.core.dom.CompilationUnit; 70 71 import org.eclipse.jdt.internal.corext.fix.IFix; 72 import org.eclipse.jdt.internal.corext.refactoring.Checks; 73 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; 74 import org.eclipse.jdt.internal.corext.refactoring.changes.MultiStateCompilationUnitChange; 75 76 import org.eclipse.jdt.ui.JavaUI; 77 import org.eclipse.jdt.ui.text.java.CompletionProposalComparator; 78 import org.eclipse.jdt.ui.text.java.IInvocationContext; 79 import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; 80 import org.eclipse.jdt.ui.text.java.IProblemLocation; 81 82 import org.eclipse.jdt.internal.ui.JavaPlugin; 83 import org.eclipse.jdt.internal.ui.fix.ICleanUp; 84 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; 85 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; 86 import org.eclipse.jdt.internal.ui.javaeditor.JavaMarkerAnnotation; 87 88 90 public class CorrectionMarkerResolutionGenerator implements IMarkerResolutionGenerator, IMarkerResolutionGenerator2 { 91 92 public static class CorrectionMarkerResolution extends WorkbenchMarkerResolution { 93 94 private static final IMarker[] NO_MARKERS= new IMarker[0]; 95 private static final int BATCH_SIZE= 40; 96 97 private ICompilationUnit fCompilationUnit; 98 private int fOffset; 99 private int fLength; 100 private IJavaCompletionProposal fProposal; 101 private final IMarker fMarker; 102 103 107 public CorrectionMarkerResolution(ICompilationUnit cu, int offset, int length, IJavaCompletionProposal proposal, IMarker marker) { 108 fCompilationUnit= cu; 109 fOffset= offset; 110 fLength= length; 111 fProposal= proposal; 112 fMarker= marker; 113 } 114 115 118 public String getLabel() { 119 return fProposal.getDisplayString(); 120 } 121 122 125 public void run(IMarker marker) { 126 try { 127 IEditorPart part= EditorUtility.isOpenInEditor(fCompilationUnit); 128 if (part == null) { 129 part= JavaUI.openInEditor(fCompilationUnit, true, false); 130 if (part instanceof ITextEditor) { 131 ((ITextEditor) part).selectAndReveal(fOffset, fLength); 132 } 133 } 134 if (part != null) { 135 IEditorInput input= part.getEditorInput(); 136 IDocument doc= JavaPlugin.getDefault().getCompilationUnitDocumentProvider().getDocument(input); 137 fProposal.apply(doc); 138 } 139 } catch (CoreException e) { 140 JavaPlugin.log(e); 141 } 142 } 143 144 public void run(IMarker[] markers, IProgressMonitor monitor) { 145 if (markers.length == 1) { 146 run(markers[0]); 147 return; 148 } 149 IProgressMonitor pm= monitor; 150 if (pm == null) 151 pm= new NullProgressMonitor(); 152 153 try { 154 if (fProposal instanceof FixCorrectionProposal) { 155 ICleanUp cleanUp= ((FixCorrectionProposal)fProposal).getCleanUp(); 156 if (cleanUp != null) { 157 Hashtable problemLocations= new Hashtable (); 158 for (int i= 0; i < markers.length; i++) { 159 IMarker marker= markers[i]; 160 ICompilationUnit cu= getCompilationUnit(marker); 161 162 if (cu != null) { 163 try { 164 IEditorInput input= EditorUtility.getEditorInput(cu); 165 IProblemLocation location= findProblemLocation(input, marker); 166 if (location != null) { 167 if (!problemLocations.containsKey(cu.getPrimary())) { 168 problemLocations.put(cu.getPrimary(), new ArrayList ()); 169 } 170 List l= (List )problemLocations.get(cu.getPrimary()); 171 l.add(location); 172 } 173 } catch (JavaModelException e) { 174 JavaPlugin.log(e); 175 } 176 } 177 } 178 if (problemLocations.size() > 0) { 179 180 Set cus= problemLocations.keySet(); 181 Hashtable projects= new Hashtable (); 182 for (Iterator iter= cus.iterator(); iter.hasNext();) { 183 ICompilationUnit cu= (ICompilationUnit)iter.next(); 184 IJavaProject project= cu.getJavaProject(); 185 if (!projects.containsKey(project)) { 186 projects.put(project, new ArrayList ()); 187 } 188 ((List )projects.get(project)).add(cu); 189 } 190 191 pm.beginTask("", problemLocations.size() * 2 + 2 + projects.keySet().size()); 193 String name= ""; String [] descriptions= cleanUp.getDescriptions(); 195 if (descriptions != null && descriptions.length == 1) { 196 name= descriptions[0]; 197 } 198 CompositeChange allChanges= new CompositeChange(name); 199 200 for (Iterator projectIter= projects.keySet().iterator(); projectIter.hasNext();) { 201 IJavaProject project= (IJavaProject)projectIter.next(); 202 List compilationUnitsList= (List )projects.get(project); 203 ICompilationUnit[] compilationUnits= (ICompilationUnit[])compilationUnitsList.toArray(new ICompilationUnit[compilationUnitsList.size()]); 204 205 try { 206 cleanUpProject(project, compilationUnits, cleanUp, problemLocations, allChanges, pm); 207 } catch (CoreException e) { 208 JavaPlugin.log(e); 209 } finally { 210 pm.worked(1); 211 } 212 } 213 214 if (pm.isCanceled()) 215 return; 216 217 allChanges.initializeValidationData(new SubProgressMonitor(pm, 1)); 218 219 if (!validChanges(allChanges)) 220 return; 221 222 PerformChangeOperation op= new PerformChangeOperation(allChanges); 223 op.setUndoManager(RefactoringCore.getUndoManager(), allChanges.getName()); 224 try { 225 op.run(new SubProgressMonitor(pm, 1)); 226 } catch (CoreException e1) { 227 JavaPlugin.log(e1); 228 } finally { 229 pm.worked(1); 230 } 231 IEditorPart part= EditorUtility.isOpenInEditor(fCompilationUnit); 232 if (part instanceof ITextEditor) { 233 ((ITextEditor) part).selectAndReveal(fOffset, fLength); 234 part.setFocus(); 235 } 236 } 237 } 238 } 239 } finally { 240 pm.done(); 241 } 242 } 243 244 private boolean validChanges(CompositeChange change) { 245 RefactoringStatus result= new RefactoringStatus(); 246 List files= new ArrayList (); 247 try { 248 findFilesToBeModified(change, files); 249 } catch (JavaModelException e) { 250 JavaPlugin.log(e); 251 return false; 252 } 253 result.merge(Checks.validateModifiesFiles((IFile[])files.toArray(new IFile[files.size()]), JavaPlugin.getActiveWorkbenchShell().getShell())); 254 if (result.hasFatalError()) { 255 RefactoringStatusEntry[] entries= result.getEntries(); 256 IStatus status; 257 if (entries.length > 1) { 258 status= new MultiStatus(JavaUI.ID_PLUGIN, 0, result.getMessageMatchingSeverity(RefactoringStatus.ERROR), null); 259 for (int i= 0; i < entries.length; i++) { 260 ((MultiStatus)status).add(new Status(entries[i].getSeverity(), JavaUI.ID_PLUGIN, 0, entries[i].getMessage(), null)); 261 } 262 } else { 263 RefactoringStatusEntry entry= entries[0]; 264 status= new Status(entry.getSeverity(), JavaUI.ID_PLUGIN, 0, entry.getMessage(), null); 265 } 266 ErrorDialog.openError(JavaPlugin.getActiveWorkbenchShell().getShell(), CorrectionMessages.CorrectionMarkerResolutionGenerator__multiFixErrorDialog_Titel, CorrectionMessages.CorrectionMarkerResolutionGenerator_multiFixErrorDialog_description, status); 267 return false; 268 } 269 return true; 270 } 271 272 private void findFilesToBeModified(CompositeChange change, List result) throws JavaModelException { 273 Change[] children= change.getChildren(); 274 for (int i=0;i < children.length;i++) { 275 Change child= children[i]; 276 if (child instanceof CompositeChange) { 277 findFilesToBeModified((CompositeChange)child, result); 278 } else if (child instanceof MultiStateCompilationUnitChange) { 279 result.add(((MultiStateCompilationUnitChange)child).getCompilationUnit().getCorrespondingResource()); 280 } else if (child instanceof CompilationUnitChange) { 281 result.add(((CompilationUnitChange)child).getCompilationUnit().getCorrespondingResource()); 282 } 283 } 284 } 285 286 private void cleanUpProject(IJavaProject project, ICompilationUnit[] compilationUnits, ICleanUp cleanUp, Hashtable problemLocations, CompositeChange result, IProgressMonitor monitor) throws CoreException { 287 cleanUp.checkPreConditions(project, compilationUnits, new SubProgressMonitor(monitor, 1)); 288 for (int i= 0; i < compilationUnits.length; i++) { 289 ICompilationUnit cu= compilationUnits[i]; 290 CompilationUnit root= getASTRoot(cu, new SubProgressMonitor(monitor, 1)); 291 List locationList= (List )problemLocations.get(cu); 292 IProblemLocation[] locations= (IProblemLocation[])locationList.toArray(new IProblemLocation[locationList.size()]); 293 294 IFix fix= cleanUp.createFix(root, locations); 295 296 if (monitor.isCanceled()) 297 return; 298 299 if (fix != null) { 300 TextChange change= fix.createChange(); 301 302 if (monitor.isCanceled()) 303 return; 304 305 result.add(change); 306 monitor.worked(1); 307 } 308 309 } 310 cleanUp.checkPostConditions(null); 311 } 312 313 316 public String getDescription() { 317 return fProposal.getAdditionalProposalInfo(); 318 } 319 320 323 public Image getImage() { 324 return fProposal.getImage(); 325 } 326 327 330 public IMarker[] findOtherMarkers(IMarker[] markers) { 331 if (!(fProposal instanceof FixCorrectionProposal)) 332 return NO_MARKERS; 333 334 FixCorrectionProposal fix= (FixCorrectionProposal)fProposal; 335 final ICleanUp cleanUp= fix.getCleanUp(); 336 if (cleanUp == null) 337 return NO_MARKERS; 338 339 final Hashtable fileMarkerTable= getMarkersForFiles(markers); 340 if (fileMarkerTable.isEmpty()) 341 return NO_MARKERS; 342 343 Hashtable projectICUTable= getCompilationUnitsForProjects(fileMarkerTable); 344 if (projectICUTable.size() == 0) 345 return NO_MARKERS; 346 347 final List result= new ArrayList (); 348 349 for (Iterator iter= projectICUTable.keySet().iterator(); iter.hasNext();) { 350 IJavaProject project= (IJavaProject)iter.next(); 351 List cus= (List )projectICUTable.get(project); 352 ASTParser parser= getParser(project); 353 354 int start= 0; 355 int end= 0; 356 while (end < cus.size()) { 357 end= Math.min(start + BATCH_SIZE, cus.size()); 358 359 List toParse= cus.subList(start, end); 360 ICompilationUnit[] units= (ICompilationUnit[])toParse.toArray(new ICompilationUnit[toParse.size()]); 361 parser.createASTs(units, new String [0], new ASTRequestor() { 362 365 public void acceptAST(ICompilationUnit cu, CompilationUnit root) { 366 try { 367 IEditorInput input= EditorUtility.getEditorInput(cu); 368 369 List fileMarkers= (List )fileMarkerTable.get(cu.getResource()); 370 371 for (Iterator iterator= fileMarkers.iterator(); iterator.hasNext();) { 372 IMarker marker= (IMarker)iterator.next(); 373 IProblemLocation location= findProblemLocation(input, marker); 374 if (location != null) { 375 if (cleanUp.canFix(root, location)) { 376 result.add(marker); 377 } 378 } 379 } 380 } catch (CoreException e) { 381 JavaPlugin.log(e); 382 } 383 } 384 }, new NullProgressMonitor()); 385 386 start= end; 387 } 388 } 389 if (result.size() == 0) 390 return NO_MARKERS; 391 392 return (IMarker[])result.toArray(new IMarker[result.size()]); 393 } 394 395 398 private Hashtable getMarkersForFiles(IMarker[] markers) { 399 final Hashtable result= new Hashtable (); 400 401 String markerType; 402 try { 403 markerType= fMarker.getType(); 404 } catch (CoreException e1) { 405 JavaPlugin.log(e1); 406 return result; 407 } 408 409 for (int i= 0; i < markers.length; i++) { 410 IMarker marker= markers[i]; 411 if (!marker.equals(fMarker)) { 412 String currMarkerType= null; 413 try { 414 currMarkerType= marker.getType(); 415 } catch (CoreException e1) { 416 JavaPlugin.log(e1); 417 } 418 419 if (currMarkerType != null && currMarkerType.equals(markerType)) { 420 IResource res= marker.getResource(); 421 if (res instanceof IFile && res.isAccessible()) { 422 List markerList= (List )result.get(res); 423 if (markerList == null) { 424 markerList= new ArrayList (); 425 result.put(res, markerList); 426 } 427 markerList.add(marker); 428 } 429 } 430 } 431 } 432 return result; 433 } 434 435 438 private Hashtable getCompilationUnitsForProjects(final Hashtable fileMarkerTable) { 439 Hashtable result= new Hashtable (); 440 for (Iterator iter= fileMarkerTable.keySet().iterator(); iter.hasNext();) { 441 IFile res= (IFile)iter.next(); 442 IJavaElement element= JavaCore.create(res); 443 444 if (element instanceof ICompilationUnit) { 445 ICompilationUnit cu= (ICompilationUnit)element; 446 List cus= (List )result.get(cu.getJavaProject()); 447 if (cus == null) { 448 cus= new ArrayList (); 449 result.put(cu.getJavaProject(), cus); 450 } 451 cus.add(cu); 452 } 453 } 454 return result; 455 } 456 457 private static ASTParser getParser(IJavaProject javaProject) { 458 ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); 459 parser.setResolveBindings(true); 460 parser.setProject(javaProject); 461 return parser; 462 } 463 464 private static CompilationUnit getASTRoot(ICompilationUnit compilationUnit, IProgressMonitor monitor) { 465 CompilationUnit result= ASTProvider.getASTProvider().getAST(compilationUnit, ASTProvider.WAIT_YES, monitor); 466 if (result == null) { 467 result= ASTResolving.createQuickFixAST(compilationUnit, monitor); 469 } 470 return result; 471 } 472 } 473 474 private static final IMarkerResolution[] NO_RESOLUTIONS= new IMarkerResolution[0]; 475 476 477 480 public CorrectionMarkerResolutionGenerator() { 481 super(); 482 } 483 484 487 public boolean hasResolutions(IMarker marker) { 488 return internalHasResolutions(marker); 489 } 490 491 494 public IMarkerResolution[] getResolutions(IMarker marker) { 495 return internalGetResolutions(marker); 496 } 497 498 private static boolean internalHasResolutions(IMarker marker) { 499 int id= marker.getAttribute(IJavaModelMarker.ID, -1); 500 ICompilationUnit cu= getCompilationUnit(marker); 501 return cu != null && JavaCorrectionProcessor.hasCorrections(cu, id, MarkerUtilities.getMarkerType(marker)); 502 } 503 504 private static IMarkerResolution[] internalGetResolutions(IMarker marker) { 505 if (!internalHasResolutions(marker)) { 506 return NO_RESOLUTIONS; 507 } 508 509 try { 510 ICompilationUnit cu= getCompilationUnit(marker); 511 if (cu != null) { 512 IEditorInput input= EditorUtility.getEditorInput(cu); 513 if (input != null) { 514 IProblemLocation location= findProblemLocation(input, marker); 515 if (location != null) { 516 517 IInvocationContext context= new AssistContext(cu, location.getOffset(), location.getLength()); 518 if (!hasProblem (context.getASTRoot().getProblems(), location)) 519 return NO_RESOLUTIONS; 520 521 ArrayList proposals= new ArrayList (); 522 JavaCorrectionProcessor.collectCorrections(context, new IProblemLocation[] { location }, proposals); 523 Collections.sort(proposals, new CompletionProposalComparator()); 524 525 int nProposals= proposals.size(); 526 IMarkerResolution[] resolutions= new IMarkerResolution[nProposals]; 527 for (int i= 0; i < nProposals; i++) { 528 resolutions[i]= new CorrectionMarkerResolution(context.getCompilationUnit(), location.getOffset(), location.getLength(), (IJavaCompletionProposal) proposals.get(i), marker); 529 } 530 return resolutions; 531 } 532 } 533 } 534 } catch (JavaModelException e) { 535 JavaPlugin.log(e); 536 } 537 return NO_RESOLUTIONS; 538 } 539 540 private static boolean hasProblem(IProblem[] problems, IProblemLocation location) { 541 for (int i= 0; i < problems.length; i++) { 542 IProblem problem= problems[i]; 543 if (problem.getID() == location.getProblemId() && problem.getSourceStart() == location.getOffset()) 544 return true; 545 } 546 return false; 547 } 548 549 private static ICompilationUnit getCompilationUnit(IMarker marker) { 550 IResource res= marker.getResource(); 551 if (res instanceof IFile && res.isAccessible()) { 552 IJavaElement element= JavaCore.create((IFile) res); 553 if (element instanceof ICompilationUnit) 554 return (ICompilationUnit) element; 555 } 556 return null; 557 } 558 559 private static IProblemLocation findProblemLocation(IEditorInput input, IMarker marker) { 560 IAnnotationModel model= JavaPlugin.getDefault().getCompilationUnitDocumentProvider().getAnnotationModel(input); 561 if (model != null) { Iterator iter= model.getAnnotationIterator(); 563 while (iter.hasNext()) { 564 Object curr= iter.next(); 565 if (curr instanceof JavaMarkerAnnotation) { 566 JavaMarkerAnnotation annot= (JavaMarkerAnnotation) curr; 567 if (marker.equals(annot.getMarker())) { 568 Position pos= model.getPosition(annot); 569 if (pos != null) { 570 return new ProblemLocation(pos.getOffset(), pos.getLength(), annot); 571 } 572 } 573 } 574 } 575 } else { ICompilationUnit cu= getCompilationUnit(marker); 577 return createFromMarker(marker, cu); 578 } 579 return null; 580 } 581 582 private static IProblemLocation createFromMarker(IMarker marker, ICompilationUnit cu) { 583 try { 584 int id= marker.getAttribute(IJavaModelMarker.ID, -1); 585 int start= marker.getAttribute(IMarker.CHAR_START, -1); 586 int end= marker.getAttribute(IMarker.CHAR_END, -1); 587 int severity= marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO); 588 String [] arguments= CorrectionEngine.getProblemArguments(marker); 589 String markerType= marker.getType(); 590 if (cu != null && id != -1 && start != -1 && end != -1 && arguments != null) { 591 boolean isError= (severity == IMarker.SEVERITY_ERROR); 592 return new ProblemLocation(start, end - start, id, arguments, isError, markerType); 593 } 594 } catch (CoreException e) { 595 JavaPlugin.log(e); 596 } 597 return null; 598 } 599 600 601 } 602 | Popular Tags |