1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.internal.ui.text;
14 import net.sourceforge.phpdt.core.ElementChangedEvent;
15 import net.sourceforge.phpdt.core.IElementChangedListener;
16 import net.sourceforge.phpdt.core.JavaCore;
17 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
18 import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
20 import org.eclipse.core.resources.IMarkerDelta;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.resources.IResourceChangeEvent;
23 import org.eclipse.core.resources.IResourceChangeListener;
24 import org.eclipse.core.resources.IResourceDelta;
25 import org.eclipse.core.resources.IWorkspace;
26 import org.eclipse.jface.text.IDocument;
27 import org.eclipse.jface.text.ITextViewer;
28 import org.eclipse.jface.text.reconciler.DirtyRegion;
29 import org.eclipse.jface.text.reconciler.MonoReconciler;
30 import org.eclipse.swt.events.ShellAdapter;
31 import org.eclipse.swt.events.ShellEvent;
32 import org.eclipse.swt.events.ShellListener;
33 import org.eclipse.swt.widgets.Control;
34 import org.eclipse.swt.widgets.Shell;
35 import org.eclipse.ui.IEditorInput;
36 import org.eclipse.ui.IFileEditorInput;
37 import org.eclipse.ui.IPartListener;
38 import org.eclipse.ui.IWorkbenchPart;
39 import org.eclipse.ui.IWorkbenchPartSite;
40 import org.eclipse.ui.IWorkbenchWindow;
41 import org.eclipse.ui.texteditor.ITextEditor;
44 * A reconciler that is also activated on editor activation.
46 public class JavaReconciler extends MonoReconciler {
49 * Internal part listener for activating the reconciler.
51 private class PartListener implements IPartListener {
54 * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
56 public void partActivated(IWorkbenchPart part) {
57 if (part == fTextEditor && hasJavaModelChanged())
58 JavaReconciler.this.forceReconciling();
62 * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
64 public void partBroughtToTop(IWorkbenchPart part) {
68 * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
70 public void partClosed(IWorkbenchPart part) {
74 * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
76 public void partDeactivated(IWorkbenchPart part) {
77 if (part == fTextEditor)
78 setJavaModelChanged(false);
82 * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
84 public void partOpened(IWorkbenchPart part) {
89 * Internal Shell activation listener for activating the reconciler.
91 private class ActivationListener extends ShellAdapter {
93 private Control fControl;
95 public ActivationListener(Control control) {
100 * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
102 public void shellActivated(ShellEvent e) {
103 if (!fControl.isDisposed() && fControl.isVisible()
104 && hasJavaModelChanged())
105 JavaReconciler.this.forceReconciling();
109 * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
111 public void shellDeactivated(ShellEvent e) {
112 setJavaModelChanged(false);
117 * Internal Java element changed listener
121 private class ElementChangedListener implements IElementChangedListener {
123 * @see net.sourceforge.phpdt.core.IElementChangedListener#elementChanged(net.sourceforge.phpdt.core.ElementChangedEvent)
125 public void elementChanged(ElementChangedEvent event) {
126 setJavaModelChanged(true);
131 * Internal resource change listener.
135 class ResourceChangeListener implements IResourceChangeListener {
137 private IResource getResource() {
138 IEditorInput input = fTextEditor.getEditorInput();
139 if (input instanceof IFileEditorInput) {
140 IFileEditorInput fileInput = (IFileEditorInput) input;
141 return fileInput.getFile();
147 * @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
149 public void resourceChanged(IResourceChangeEvent e) {
150 IResourceDelta delta = e.getDelta();
151 IResource resource = getResource();
152 if (delta != null && resource != null) {
153 IResourceDelta child = delta.findMember(resource.getFullPath());
155 IMarkerDelta[] deltas = child.getMarkerDeltas();
156 if (deltas.length > 0)
163 /** The reconciler's editor */
164 private ITextEditor fTextEditor;
166 /** The part listener */
167 private IPartListener fPartListener;
169 /** The shell listener */
170 private ShellListener fActivationListener;
173 * The mutex that keeps us from running multiple reconcilers on one editor.
174 * TODO remove once we have ensured that there is only one reconciler per
177 private Object fMutex;
180 * The Java element changed listener.
184 private IElementChangedListener fJavaElementChangedListener;
187 * Tells whether the Java model sent out a changed event.
191 private volatile boolean fHasJavaModelChanged = true;
194 * The resource change listener.
198 private IResourceChangeListener fResourceChangeListener;
200 private boolean fIninitalProcessDone = false;
203 * Creates a new reconciler.
205 public JavaReconciler(ITextEditor editor,
206 JavaCompositeReconcilingStrategy strategy, boolean isIncremental) {
207 super(strategy, isIncremental);
208 fTextEditor = editor;
210 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
211 // when re-using editors, a new reconciler is set up by the source
213 // and the old one uninstalled. However, the old reconciler may still be
215 // To avoid having to reconcilers calling
216 // CompilationUnitEditor.reconciled,
217 // we synchronized on a lock object provided by the editor.
218 // The critical section is really the entire run() method of the
220 // thread, but synchronizing process() only will keep
221 // JavaReconcilingStrategy
222 // from running concurrently on the same editor.
223 // TODO remove once we have ensured that there is only one reconciler
225 if (editor instanceof PHPUnitEditor)
226 fMutex = ((PHPUnitEditor) editor).getReconcilerLock();
228 fMutex = new Object(); // Null Object
232 * @see org.eclipse.jface.text.reconciler.IReconciler#install(org.eclipse.jface.text.ITextViewer)
234 public void install(ITextViewer textViewer) {
235 super.install(textViewer);
237 fPartListener = new PartListener();
238 IWorkbenchPartSite site = fTextEditor.getSite();
239 IWorkbenchWindow window = site.getWorkbenchWindow();
240 window.getPartService().addPartListener(fPartListener);
242 fActivationListener = new ActivationListener(textViewer.getTextWidget());
243 Shell shell = window.getShell();
244 shell.addShellListener(fActivationListener);
246 fJavaElementChangedListener = new ElementChangedListener();
247 JavaCore.addElementChangedListener(fJavaElementChangedListener);
249 fResourceChangeListener = new ResourceChangeListener();
250 IWorkspace workspace = PHPeclipsePlugin.getWorkspace();
251 workspace.addResourceChangeListener(fResourceChangeListener);
255 * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
257 public void uninstall() {
259 IWorkbenchPartSite site = fTextEditor.getSite();
260 IWorkbenchWindow window = site.getWorkbenchWindow();
261 window.getPartService().removePartListener(fPartListener);
262 fPartListener = null;
264 Shell shell = window.getShell();
265 if (shell != null && !shell.isDisposed())
266 shell.removeShellListener(fActivationListener);
267 fActivationListener = null;
269 JavaCore.removeElementChangedListener(fJavaElementChangedListener);
270 fJavaElementChangedListener = null;
272 IWorkspace workspace = PHPeclipsePlugin.getWorkspace();
273 workspace.removeResourceChangeListener(fResourceChangeListener);
274 fResourceChangeListener = null;
280 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#forceReconciling()
282 protected void forceReconciling() {
283 if (!fIninitalProcessDone)
286 super.forceReconciling();
287 JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
288 strategy.notifyListeners(false);
292 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#aboutToReconcile()
295 protected void aboutToBeReconciled() {
296 JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
297 strategy.aboutToBeReconciled();
301 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#reconcilerReset()
303 protected void reconcilerReset() {
304 super.reconcilerReset();
305 JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
306 strategy.notifyListeners(true);
310 * @see org.eclipse.jface.text.reconciler.MonoReconciler#initialProcess()
312 protected void initialProcess() {
313 // TODO remove once we have ensured that there is only one reconciler
315 synchronized (fMutex) {
316 super.initialProcess();
318 fIninitalProcessDone = true;
322 * @see org.eclipse.jface.text.reconciler.MonoReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion)
324 protected void process(DirtyRegion dirtyRegion) {
325 // TODO remove once we have ensured that there is only one reconciler
327 synchronized (fMutex) {
328 super.process(dirtyRegion);
333 * Tells whether the Java Model has changed or not.
335 * @return <code>true</code> iff the Java Model has changed
338 private synchronized boolean hasJavaModelChanged() {
339 return fHasJavaModelChanged;
343 * Sets whether the Java Model has changed or not.
346 * <code>true</code> iff the java model has changed
349 private synchronized void setJavaModelChanged(boolean state) {
350 fHasJavaModelChanged = state;
354 // * A reconciler that is also activated on editor activation.
356 // public class JavaReconciler extends MonoReconciler {
359 // * Internal part listener for activating the reconciler.
361 // class PartListener implements IPartListener {
364 // * @see IPartListener#partActivated(IWorkbenchPart)
366 // public void partActivated(IWorkbenchPart part) {
367 // if (part == fTextEditor)
368 // JavaReconciler.this.forceReconciling();
372 // * @see IPartListener#partBroughtToTop(IWorkbenchPart)
374 // public void partBroughtToTop(IWorkbenchPart part) {
378 // * @see IPartListener#partClosed(IWorkbenchPart)
380 // public void partClosed(IWorkbenchPart part) {
384 // * @see IPartListener#partDeactivated(IWorkbenchPart)
386 // public void partDeactivated(IWorkbenchPart part) {
390 // * @see IPartListener#partOpened(IWorkbenchPart)
392 // public void partOpened(IWorkbenchPart part) {
397 // /** The reconciler's editor */
398 // private ITextEditor fTextEditor;
399 // /** The part listener */
400 // private IPartListener fPartListener;
404 // * Creates a new reconciler.
406 // public JavaReconciler(ITextEditor editor, IReconcilingStrategy strategy,
407 // boolean isIncremental) {
408 // super(strategy, isIncremental);
409 // fTextEditor= editor;
413 // * @see IReconciler#install(ITextViewer)
415 // public void install(ITextViewer textViewer) {
416 // super.install(textViewer);
418 // fPartListener= new PartListener();
419 // IWorkbenchPartSite site= fTextEditor.getSite();
420 // IWorkbenchWindow window= site.getWorkbenchWindow();
421 // window.getPartService().addPartListener(fPartListener);
425 // * @see IReconciler#uninstall()
427 // public void uninstall() {
429 // IWorkbenchPartSite site= fTextEditor.getSite();
430 // IWorkbenchWindow window= site.getWorkbenchWindow();
431 // window.getPartService().removePartListener(fPartListener);
432 // fPartListener= null;
434 // super.uninstall();
438 // * @see AbstractReconciler#forceReconciling()
440 // protected void forceReconciling() {
441 // super.forceReconciling();
442 // IReconcilingStrategy strategy=
443 // getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
444 // if (strategy instanceof JavaReconcilingStrategy) {
445 // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
446 // java.notifyParticipants(false);
451 // * @see AbstractReconciler#reconcilerReset()
453 // protected void reconcilerReset() {
454 // super.reconcilerReset();
455 // IReconcilingStrategy strategy=
456 // getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
457 // if (strategy instanceof JavaReconcilingStrategy) {
458 // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
459 // java.notifyParticipants(true);