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;
15 import net.sourceforge.phpdt.core.ElementChangedEvent;
16 import net.sourceforge.phpdt.core.IElementChangedListener;
17 import net.sourceforge.phpdt.core.JavaCore;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19 import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
21 import org.eclipse.core.resources.IMarkerDelta;
22 import org.eclipse.core.resources.IResource;
23 import org.eclipse.core.resources.IResourceChangeEvent;
24 import org.eclipse.core.resources.IResourceChangeListener;
25 import org.eclipse.core.resources.IResourceDelta;
26 import org.eclipse.core.resources.IWorkspace;
27 import org.eclipse.jface.text.IDocument;
28 import org.eclipse.jface.text.ITextViewer;
29 import org.eclipse.jface.text.reconciler.DirtyRegion;
30 import org.eclipse.jface.text.reconciler.MonoReconciler;
31 import org.eclipse.swt.events.ShellAdapter;
32 import org.eclipse.swt.events.ShellEvent;
33 import org.eclipse.swt.events.ShellListener;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.ui.IEditorInput;
37 import org.eclipse.ui.IFileEditorInput;
38 import org.eclipse.ui.IPartListener;
39 import org.eclipse.ui.IWorkbenchPart;
40 import org.eclipse.ui.IWorkbenchPartSite;
41 import org.eclipse.ui.IWorkbenchWindow;
42 import org.eclipse.ui.texteditor.ITextEditor;
46 * A reconciler that is also activated on editor activation.
48 public class JavaReconciler extends MonoReconciler {
51 * Internal part listener for activating the reconciler.
53 private class PartListener implements IPartListener {
56 * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
58 public void partActivated(IWorkbenchPart part) {
59 if (part == fTextEditor && hasJavaModelChanged())
60 JavaReconciler.this.forceReconciling();
64 * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
66 public void partBroughtToTop(IWorkbenchPart part) {
70 * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
72 public void partClosed(IWorkbenchPart part) {
76 * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
78 public void partDeactivated(IWorkbenchPart part) {
79 if (part == fTextEditor)
80 setJavaModelChanged(false);
84 * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
86 public void partOpened(IWorkbenchPart part) {
91 * Internal Shell activation listener for activating the reconciler.
93 private class ActivationListener extends ShellAdapter {
95 private Control fControl;
97 public ActivationListener(Control control) {
102 * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
104 public void shellActivated(ShellEvent e) {
105 if (!fControl.isDisposed() && fControl.isVisible() && hasJavaModelChanged())
106 JavaReconciler.this.forceReconciling();
110 * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
112 public void shellDeactivated(ShellEvent e) {
113 setJavaModelChanged(false);
118 * Internal Java element changed listener
122 private class ElementChangedListener implements IElementChangedListener {
124 * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
126 public void elementChanged(ElementChangedEvent event) {
127 setJavaModelChanged(true);
132 * Internal resource change listener.
136 class ResourceChangeListener implements IResourceChangeListener {
138 private IResource getResource() {
139 IEditorInput input= fTextEditor.getEditorInput();
140 if (input instanceof IFileEditorInput) {
141 IFileEditorInput fileInput= (IFileEditorInput) input;
142 return fileInput.getFile();
148 * @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
150 public void resourceChanged(IResourceChangeEvent e) {
151 IResourceDelta delta= e.getDelta();
152 IResource resource= getResource();
153 if (delta != null && resource != null) {
154 IResourceDelta child= delta.findMember(resource.getFullPath());
156 IMarkerDelta[] deltas= child.getMarkerDeltas();
157 if (deltas.length > 0)
165 /** The reconciler's editor */
166 private ITextEditor fTextEditor;
167 /** The part listener */
168 private IPartListener fPartListener;
169 /** The shell listener */
170 private ShellListener fActivationListener;
172 * The mutex that keeps us from running multiple reconcilers on one editor.
173 * TODO remove once we have ensured that there is only one reconciler per editor.
175 private Object fMutex;
177 * The Java element changed listener.
180 private IElementChangedListener fJavaElementChangedListener;
182 * Tells whether the Java model sent out a changed event.
185 private volatile boolean fHasJavaModelChanged= true;
187 * The resource change listener.
190 private IResourceChangeListener fResourceChangeListener;
191 private boolean fIninitalProcessDone= false;
194 * Creates a new reconciler.
196 public JavaReconciler(ITextEditor editor, JavaCompositeReconcilingStrategy strategy, boolean isIncremental) {
197 super(strategy, isIncremental);
200 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
201 // when re-using editors, a new reconciler is set up by the source viewer
202 // and the old one uninstalled. However, the old reconciler may still be
204 // To avoid having to reconcilers calling CompilationUnitEditor.reconciled,
205 // we synchronized on a lock object provided by the editor.
206 // The critical section is really the entire run() method of the reconciler
207 // thread, but synchronizing process() only will keep JavaReconcilingStrategy
208 // from running concurrently on the same editor.
209 // TODO remove once we have ensured that there is only one reconciler per editor.
210 if (editor instanceof PHPUnitEditor)
211 fMutex= ((PHPUnitEditor) editor).getReconcilerLock();
213 fMutex= new Object(); // Null Object
217 * @see org.eclipse.jface.text.reconciler.IReconciler#install(org.eclipse.jface.text.ITextViewer)
219 public void install(ITextViewer textViewer) {
220 super.install(textViewer);
222 fPartListener= new PartListener();
223 IWorkbenchPartSite site= fTextEditor.getSite();
224 IWorkbenchWindow window= site.getWorkbenchWindow();
225 window.getPartService().addPartListener(fPartListener);
227 fActivationListener= new ActivationListener(textViewer.getTextWidget());
228 Shell shell= window.getShell();
229 shell.addShellListener(fActivationListener);
231 fJavaElementChangedListener= new ElementChangedListener();
232 JavaCore.addElementChangedListener(fJavaElementChangedListener);
234 fResourceChangeListener= new ResourceChangeListener();
235 IWorkspace workspace= PHPeclipsePlugin.getWorkspace();
236 workspace.addResourceChangeListener(fResourceChangeListener);
240 * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
242 public void uninstall() {
244 IWorkbenchPartSite site= fTextEditor.getSite();
245 IWorkbenchWindow window= site.getWorkbenchWindow();
246 window.getPartService().removePartListener(fPartListener);
249 Shell shell= window.getShell();
250 if (shell != null && !shell.isDisposed())
251 shell.removeShellListener(fActivationListener);
252 fActivationListener= null;
254 JavaCore.removeElementChangedListener(fJavaElementChangedListener);
255 fJavaElementChangedListener= null;
257 IWorkspace workspace= PHPeclipsePlugin.getWorkspace();
258 workspace.removeResourceChangeListener(fResourceChangeListener);
259 fResourceChangeListener= null;
265 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#forceReconciling()
267 protected void forceReconciling() {
268 if (!fIninitalProcessDone)
271 super.forceReconciling();
272 JavaCompositeReconcilingStrategy strategy= (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
273 strategy.notifyListeners(false);
277 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#aboutToReconcile()
280 protected void aboutToBeReconciled() {
281 JavaCompositeReconcilingStrategy strategy= (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
282 strategy.aboutToBeReconciled();
286 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#reconcilerReset()
288 protected void reconcilerReset() {
289 super.reconcilerReset();
290 JavaCompositeReconcilingStrategy strategy= (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
291 strategy.notifyListeners(true);
295 * @see org.eclipse.jface.text.reconciler.MonoReconciler#initialProcess()
297 protected void initialProcess() {
298 // TODO remove once we have ensured that there is only one reconciler per editor.
299 synchronized (fMutex) {
300 super.initialProcess();
302 fIninitalProcessDone= true;
306 * @see org.eclipse.jface.text.reconciler.MonoReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion)
308 protected void process(DirtyRegion dirtyRegion) {
309 // TODO remove once we have ensured that there is only one reconciler per editor.
310 synchronized (fMutex) {
311 super.process(dirtyRegion);
316 * Tells whether the Java Model has changed or not.
318 * @return <code>true</code> iff the Java Model has changed
321 private synchronized boolean hasJavaModelChanged() {
322 return fHasJavaModelChanged;
326 * Sets whether the Java Model has changed or not.
328 * @param state <code>true</code> iff the java model has changed
331 private synchronized void setJavaModelChanged(boolean state) {
332 fHasJavaModelChanged= state;
336 // * A reconciler that is also activated on editor activation.
338 //public class JavaReconciler extends MonoReconciler {
341 // * Internal part listener for activating the reconciler.
343 // class PartListener implements IPartListener {
346 // * @see IPartListener#partActivated(IWorkbenchPart)
348 // public void partActivated(IWorkbenchPart part) {
349 // if (part == fTextEditor)
350 // JavaReconciler.this.forceReconciling();
354 // * @see IPartListener#partBroughtToTop(IWorkbenchPart)
356 // public void partBroughtToTop(IWorkbenchPart part) {
360 // * @see IPartListener#partClosed(IWorkbenchPart)
362 // public void partClosed(IWorkbenchPart part) {
366 // * @see IPartListener#partDeactivated(IWorkbenchPart)
368 // public void partDeactivated(IWorkbenchPart part) {
372 // * @see IPartListener#partOpened(IWorkbenchPart)
374 // public void partOpened(IWorkbenchPart part) {
379 // /** The reconciler's editor */
380 // private ITextEditor fTextEditor;
381 // /** The part listener */
382 // private IPartListener fPartListener;
386 // * Creates a new reconciler.
388 // public JavaReconciler(ITextEditor editor, IReconcilingStrategy strategy, boolean isIncremental) {
389 // super(strategy, isIncremental);
390 // fTextEditor= editor;
394 // * @see IReconciler#install(ITextViewer)
396 // public void install(ITextViewer textViewer) {
397 // super.install(textViewer);
399 // fPartListener= new PartListener();
400 // IWorkbenchPartSite site= fTextEditor.getSite();
401 // IWorkbenchWindow window= site.getWorkbenchWindow();
402 // window.getPartService().addPartListener(fPartListener);
406 // * @see IReconciler#uninstall()
408 // public void uninstall() {
410 // IWorkbenchPartSite site= fTextEditor.getSite();
411 // IWorkbenchWindow window= site.getWorkbenchWindow();
412 // window.getPartService().removePartListener(fPartListener);
413 // fPartListener= null;
415 // super.uninstall();
419 // * @see AbstractReconciler#forceReconciling()
421 // protected void forceReconciling() {
422 // super.forceReconciling();
423 // IReconcilingStrategy strategy= getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
424 // if (strategy instanceof JavaReconcilingStrategy) {
425 // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
426 // java.notifyParticipants(false);
431 // * @see AbstractReconciler#reconcilerReset()
433 // protected void reconcilerReset() {
434 // super.reconcilerReset();
435 // IReconcilingStrategy strategy= getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
436 // if (strategy instanceof JavaReconcilingStrategy) {
437 // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
438 // java.notifyParticipants(true);