1 11 12 package org.eclipse.jdt.internal.ui.javaeditor; 13 14 import java.util.ArrayList ; 15 import java.util.List ; 16 17 import org.eclipse.core.runtime.IProgressMonitor; 18 import org.eclipse.core.runtime.IStatus; 19 import org.eclipse.core.runtime.Status; 20 import org.eclipse.core.runtime.jobs.Job; 21 22 import org.eclipse.swt.widgets.Display; 23 import org.eclipse.swt.widgets.Shell; 24 25 import org.eclipse.jface.text.IDocument; 26 import org.eclipse.jface.text.ITextInputListener; 27 import org.eclipse.jface.text.Position; 28 import org.eclipse.jface.text.TextPresentation; 29 import org.eclipse.jface.text.source.ISourceViewer; 30 31 import org.eclipse.ui.IWorkbenchPartSite; 32 33 import org.eclipse.jdt.core.IJavaElement; 34 import org.eclipse.jdt.core.dom.ASTNode; 35 import org.eclipse.jdt.core.dom.BooleanLiteral; 36 import org.eclipse.jdt.core.dom.CharacterLiteral; 37 import org.eclipse.jdt.core.dom.CompilationUnit; 38 import org.eclipse.jdt.core.dom.Expression; 39 import org.eclipse.jdt.core.dom.NumberLiteral; 40 import org.eclipse.jdt.core.dom.SimpleName; 41 42 import org.eclipse.jdt.internal.corext.dom.GenericVisitor; 43 44 import org.eclipse.jdt.internal.ui.JavaPlugin; 45 import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingManager.HighlightedPosition; 46 import org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingManager.Highlighting; 47 import org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener; 48 49 50 55 public class SemanticHighlightingReconciler implements IJavaReconcilingListener, ITextInputListener { 56 57 60 private class PositionCollector extends GenericVisitor { 61 62 63 private SemanticToken fToken= new SemanticToken(); 64 65 68 protected boolean visitNode(ASTNode node) { 69 if ((node.getFlags() & ASTNode.MALFORMED) == ASTNode.MALFORMED) { 70 retainPositions(node.getStartPosition(), node.getLength()); 71 return false; 72 } 73 return true; 74 } 75 76 79 public boolean visit(BooleanLiteral node) { 80 return visitLiteral(node); 81 } 82 83 86 public boolean visit(CharacterLiteral node) { 87 return visitLiteral(node); 88 } 89 90 93 public boolean visit(NumberLiteral node) { 94 return visitLiteral(node); 95 } 96 97 private boolean visitLiteral(Expression node) { 98 fToken.update(node); 99 for (int i= 0, n= fJobSemanticHighlightings.length; i < n; i++) { 100 SemanticHighlighting semanticHighlighting= fJobSemanticHighlightings[i]; 101 if (fJobHighlightings[i].isEnabled() && semanticHighlighting.consumesLiteral(fToken)) { 102 int offset= node.getStartPosition(); 103 int length= node.getLength(); 104 if (offset > -1 && length > 0) 105 addPosition(offset, length, fJobHighlightings[i]); 106 break; 107 } 108 } 109 fToken.clear(); 110 return false; 111 } 112 113 116 public boolean visit(SimpleName node) { 117 fToken.update(node); 118 for (int i= 0, n= fJobSemanticHighlightings.length; i < n; i++) { 119 SemanticHighlighting semanticHighlighting= fJobSemanticHighlightings[i]; 120 if (fJobHighlightings[i].isEnabled() && semanticHighlighting.consumes(fToken)) { 121 int offset= node.getStartPosition(); 122 int length= node.getLength(); 123 if (offset > -1 && length > 0) 124 addPosition(offset, length, fJobHighlightings[i]); 125 break; 126 } 127 } 128 fToken.clear(); 129 return false; 130 } 131 132 138 private void addPosition(int offset, int length, Highlighting highlighting) { 139 boolean isExisting= false; 140 for (int i= 0, n= fRemovedPositions.size(); i < n; i++) { 142 HighlightedPosition position= (HighlightedPosition) fRemovedPositions.get(i); 143 if (position == null) 144 continue; 145 if (position.isEqual(offset, length, highlighting)) { 146 isExisting= true; 147 fRemovedPositions.set(i, null); 148 fNOfRemovedPositions--; 149 break; 150 } 151 } 152 153 if (!isExisting) { 154 Position position= fJobPresenter.createHighlightedPosition(offset, length, highlighting); 155 fAddedPositions.add(position); 156 } 157 } 158 159 164 private void retainPositions(int offset, int length) { 165 for (int i= 0, n= fRemovedPositions.size(); i < n; i++) { 167 HighlightedPosition position= (HighlightedPosition) fRemovedPositions.get(i); 168 if (position != null && position.isContained(offset, length)) { 169 fRemovedPositions.set(i, null); 170 fNOfRemovedPositions--; 171 } 172 } 173 } 174 } 175 176 177 private PositionCollector fCollector= new PositionCollector(); 178 179 180 private JavaEditor fEditor; 181 182 private ISourceViewer fSourceViewer; 183 184 private SemanticHighlightingPresenter fPresenter; 185 186 private SemanticHighlighting[] fSemanticHighlightings; 187 188 private Highlighting[] fHighlightings; 189 190 191 private List fAddedPositions= new ArrayList (); 192 193 private List fRemovedPositions= new ArrayList (); 194 195 private int fNOfRemovedPositions; 196 197 198 private Job fJob; 199 200 private final Object fJobLock= new Object (); 201 205 private final Object fReconcileLock= new Object (); 206 211 private boolean fIsReconciling= false; 212 213 214 private SemanticHighlightingPresenter fJobPresenter; 215 216 private SemanticHighlighting[] fJobSemanticHighlightings; 217 218 private Highlighting[] fJobHighlightings; 219 220 223 public void aboutToBeReconciled() { 224 } 226 227 230 public void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor progressMonitor) { 231 synchronized (fReconcileLock) { 233 if (fIsReconciling) 234 return; 235 else 236 fIsReconciling= true; 237 } 238 fJobPresenter= fPresenter; 239 fJobSemanticHighlightings= fSemanticHighlightings; 240 fJobHighlightings= fHighlightings; 241 242 try { 243 if (fJobPresenter == null || fJobSemanticHighlightings == null || fJobHighlightings == null) 244 return; 245 246 fJobPresenter.setCanceled(progressMonitor.isCanceled()); 247 248 if (ast == null || fJobPresenter.isCanceled()) 249 return; 250 251 ASTNode[] subtrees= getAffectedSubtrees(ast); 252 if (subtrees.length == 0) 253 return; 254 255 startReconcilingPositions(); 256 257 if (!fJobPresenter.isCanceled()) 258 reconcilePositions(subtrees); 259 260 TextPresentation textPresentation= null; 261 if (!fJobPresenter.isCanceled()) 262 textPresentation= fJobPresenter.createPresentation(fAddedPositions, fRemovedPositions); 263 264 if (!fJobPresenter.isCanceled()) 265 updatePresentation(textPresentation, fAddedPositions, fRemovedPositions); 266 267 stopReconcilingPositions(); 268 } finally { 269 fJobPresenter= null; 270 fJobSemanticHighlightings= null; 271 fJobHighlightings= null; 272 synchronized (fReconcileLock) { 273 fIsReconciling= false; 274 } 275 } 276 } 277 278 282 private ASTNode[] getAffectedSubtrees(ASTNode node) { 283 return new ASTNode[] { node }; 285 } 286 287 290 private void startReconcilingPositions() { 291 fJobPresenter.addAllPositions(fRemovedPositions); 292 fNOfRemovedPositions= fRemovedPositions.size(); 293 } 294 295 300 private void reconcilePositions(ASTNode[] subtrees) { 301 for (int i= 0, n= subtrees.length; i < n; i++) 303 subtrees[i].accept(fCollector); 304 List oldPositions= fRemovedPositions; 305 List newPositions= new ArrayList (fNOfRemovedPositions); 306 for (int i= 0, n= oldPositions.size(); i < n; i ++) { 307 Object current= oldPositions.get(i); 308 if (current != null) 309 newPositions.add(current); 310 } 311 fRemovedPositions= newPositions; 312 } 313 314 321 private void updatePresentation(TextPresentation textPresentation, List addedPositions, List removedPositions) { 322 Runnable runnable= fJobPresenter.createUpdateRunnable(textPresentation, addedPositions, removedPositions); 323 if (runnable == null) 324 return; 325 326 JavaEditor editor= fEditor; 327 if (editor == null) 328 return; 329 330 IWorkbenchPartSite site= editor.getSite(); 331 if (site == null) 332 return; 333 334 Shell shell= site.getShell(); 335 if (shell == null || shell.isDisposed()) 336 return; 337 338 Display display= shell.getDisplay(); 339 if (display == null || display.isDisposed()) 340 return; 341 342 display.asyncExec(runnable); 343 } 344 345 348 private void stopReconcilingPositions() { 349 fRemovedPositions.clear(); 350 fNOfRemovedPositions= 0; 351 fAddedPositions.clear(); 352 } 353 354 362 public void install(JavaEditor editor, ISourceViewer sourceViewer, SemanticHighlightingPresenter presenter, SemanticHighlighting[] semanticHighlightings, Highlighting[] highlightings) { 363 fPresenter= presenter; 364 fSemanticHighlightings= semanticHighlightings; 365 fHighlightings= highlightings; 366 367 fEditor= editor; 368 fSourceViewer= sourceViewer; 369 370 if (fEditor instanceof CompilationUnitEditor) { 371 ((CompilationUnitEditor)fEditor).addReconcileListener(this); 372 } else if (fEditor == null) { 373 fSourceViewer.addTextInputListener(this); 374 scheduleJob(); 375 } 376 } 377 378 381 public void uninstall() { 382 if (fPresenter != null) 383 fPresenter.setCanceled(true); 384 385 if (fEditor != null) { 386 if (fEditor instanceof CompilationUnitEditor) 387 ((CompilationUnitEditor)fEditor).removeReconcileListener(this); 388 else 389 fSourceViewer.removeTextInputListener(this); 390 fEditor= null; 391 } 392 393 fSourceViewer= null; 394 fSemanticHighlightings= null; 395 fHighlightings= null; 396 fPresenter= null; 397 } 398 399 402 private void scheduleJob() { 403 final IJavaElement element= fEditor.getInputJavaElement(); 404 405 synchronized (fJobLock) { 406 final Job oldJob= fJob; 407 if (fJob != null) { 408 fJob.cancel(); 409 fJob= null; 410 } 411 412 if (element != null) { 413 fJob= new Job(JavaEditorMessages.SemanticHighlighting_job) { 414 protected IStatus run(IProgressMonitor monitor) { 415 if (oldJob != null) { 416 try { 417 oldJob.join(); 418 } catch (InterruptedException e) { 419 JavaPlugin.log(e); 420 return Status.CANCEL_STATUS; 421 } 422 } 423 if (monitor.isCanceled()) 424 return Status.CANCEL_STATUS; 425 CompilationUnit ast= JavaPlugin.getDefault().getASTProvider().getAST(element, ASTProvider.WAIT_YES, monitor); 426 reconciled(ast, false, monitor); 427 synchronized (fJobLock) { 428 if (fJob == this) 430 fJob= null; 431 } 432 return Status.OK_STATUS; 433 } 434 }; 435 fJob.setSystem(true); 436 fJob.setPriority(Job.DECORATE); 437 fJob.schedule(); 438 } 439 } 440 } 441 442 445 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 446 synchronized (fJobLock) { 447 if (fJob != null) { 448 fJob.cancel(); 449 fJob= null; 450 } 451 } 452 } 453 454 457 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 458 if (newInput != null) 459 scheduleJob(); 460 } 461 462 467 public void refresh() { 468 scheduleJob(); 469 } 470 } 471 | Popular Tags |