remove unnecessary extension.
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / text / JavaReconciler.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.internal.ui.text;
13
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;
19 import net.sourceforge.phpeclipse.ui.WebUI;
20
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;
43
44 /**
45  * A reconciler that is also activated on editor activation.
46  */
47 public class JavaReconciler extends MonoReconciler {
48
49         /**
50          * Internal part listener for activating the reconciler.
51          */
52         private class PartListener implements IPartListener {
53
54                 /*
55                  * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
56                  */
57                 public void partActivated(IWorkbenchPart part) {
58                         if (part == fTextEditor && hasJavaModelChanged())
59                                 JavaReconciler.this.forceReconciling();
60                 }
61
62                 /*
63                  * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
64                  */
65                 public void partBroughtToTop(IWorkbenchPart part) {
66                 }
67
68                 /*
69                  * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
70                  */
71                 public void partClosed(IWorkbenchPart part) {
72                 }
73
74                 /*
75                  * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
76                  */
77                 public void partDeactivated(IWorkbenchPart part) {
78                         if (part == fTextEditor)
79                                 setJavaModelChanged(false);
80                 }
81
82                 /*
83                  * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
84                  */
85                 public void partOpened(IWorkbenchPart part) {
86                 }
87         }
88
89         /**
90          * Internal Shell activation listener for activating the reconciler.
91          */
92         private class ActivationListener extends ShellAdapter {
93
94                 private Control fControl;
95
96                 public ActivationListener(Control control) {
97                         fControl = control;
98                 }
99
100                 /*
101                  * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
102                  */
103                 public void shellActivated(ShellEvent e) {
104                         if (!fControl.isDisposed() && fControl.isVisible()
105                                         && hasJavaModelChanged())
106                                 JavaReconciler.this.forceReconciling();
107                 }
108
109                 /*
110                  * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
111                  */
112                 public void shellDeactivated(ShellEvent e) {
113                         setJavaModelChanged(false);
114                 }
115         }
116
117         /**
118          * Internal Java element changed listener
119          * 
120          * @since 3.0
121          */
122         private class ElementChangedListener implements IElementChangedListener {
123                 /*
124                  * @see net.sourceforge.phpdt.core.IElementChangedListener#elementChanged(net.sourceforge.phpdt.core.ElementChangedEvent)
125                  */
126                 public void elementChanged(ElementChangedEvent event) {
127                         setJavaModelChanged(true);
128                 }
129         }
130
131         /**
132          * Internal resource change listener.
133          * 
134          * @since 3.0
135          */
136         class ResourceChangeListener implements IResourceChangeListener {
137
138                 private IResource getResource() {
139                         IEditorInput input = fTextEditor.getEditorInput();
140                         if (input instanceof IFileEditorInput) {
141                                 IFileEditorInput fileInput = (IFileEditorInput) input;
142                                 return fileInput.getFile();
143                         }
144                         return null;
145                 }
146
147                 /*
148                  * @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
149                  */
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());
155                                 if (child != null) {
156                                         IMarkerDelta[] deltas = child.getMarkerDeltas();
157                                         if (deltas.length > 0)
158                                                 forceReconciling();
159                                 }
160                         }
161                 }
162         }
163
164         /** The reconciler's editor */
165         private ITextEditor fTextEditor;
166
167         /** The part listener */
168         private IPartListener fPartListener;
169
170         /** The shell listener */
171         private ShellListener fActivationListener;
172
173         /**
174          * The mutex that keeps us from running multiple reconcilers on one editor.
175          * TODO remove once we have ensured that there is only one reconciler per
176          * editor.
177          */
178         private Object fMutex;
179
180         /**
181          * The Java element changed listener.
182          * 
183          * @since 3.0
184          */
185         private IElementChangedListener fJavaElementChangedListener;
186
187         /**
188          * Tells whether the Java model sent out a changed event.
189          * 
190          * @since 3.0
191          */
192         private volatile boolean fHasJavaModelChanged = true;
193
194         /**
195          * The resource change listener.
196          * 
197          * @since 3.0
198          */
199         private IResourceChangeListener fResourceChangeListener;
200
201         private boolean fIninitalProcessDone = false;
202
203         /**
204          * Creates a new reconciler.
205          */
206         public JavaReconciler(ITextEditor editor,
207                         JavaCompositeReconcilingStrategy strategy, boolean isIncremental) {
208                 super(strategy, isIncremental);
209                 fTextEditor = editor;
210
211                 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
212                 // when re-using editors, a new reconciler is set up by the source
213                 // viewer
214                 // and the old one uninstalled. However, the old reconciler may still be
215                 // running.
216                 // To avoid having to reconcilers calling
217                 // CompilationUnitEditor.reconciled,
218                 // we synchronized on a lock object provided by the editor.
219                 // The critical section is really the entire run() method of the
220                 // reconciler
221                 // thread, but synchronizing process() only will keep
222                 // JavaReconcilingStrategy
223                 // from running concurrently on the same editor.
224                 // TODO remove once we have ensured that there is only one reconciler
225                 // per editor.
226                 if (editor instanceof PHPUnitEditor)
227                         fMutex = ((PHPUnitEditor) editor).getReconcilerLock();
228                 else
229                         fMutex = new Object(); // Null Object
230         }
231
232         /*
233          * @see org.eclipse.jface.text.reconciler.IReconciler#install(org.eclipse.jface.text.ITextViewer)
234          */
235         public void install(ITextViewer textViewer) {
236                 super.install(textViewer);
237
238                 fPartListener = new PartListener();
239                 IWorkbenchPartSite site = fTextEditor.getSite();
240                 IWorkbenchWindow window = site.getWorkbenchWindow();
241                 window.getPartService().addPartListener(fPartListener);
242
243                 fActivationListener = new ActivationListener(textViewer.getTextWidget());
244                 Shell shell = window.getShell();
245                 shell.addShellListener(fActivationListener);
246
247                 fJavaElementChangedListener = new ElementChangedListener();
248                 JavaCore.addElementChangedListener(fJavaElementChangedListener);
249
250                 fResourceChangeListener = new ResourceChangeListener();
251                 IWorkspace workspace = WebUI.getWorkspace();
252                 workspace.addResourceChangeListener(fResourceChangeListener);
253         }
254
255         /*
256          * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
257          */
258         public void uninstall() {
259
260                 IWorkbenchPartSite site = fTextEditor.getSite();
261                 IWorkbenchWindow window = site.getWorkbenchWindow();
262                 window.getPartService().removePartListener(fPartListener);
263                 fPartListener = null;
264
265                 Shell shell = window.getShell();
266                 if (shell != null && !shell.isDisposed())
267                         shell.removeShellListener(fActivationListener);
268                 fActivationListener = null;
269
270                 JavaCore.removeElementChangedListener(fJavaElementChangedListener);
271                 fJavaElementChangedListener = null;
272
273                 IWorkspace workspace = WebUI.getWorkspace();
274                 workspace.removeResourceChangeListener(fResourceChangeListener);
275                 fResourceChangeListener = null;
276
277                 super.uninstall();
278         }
279
280         /*
281          * @see org.eclipse.jface.text.reconciler.AbstractReconciler#forceReconciling()
282          */
283         protected void forceReconciling() {
284                 if (!fIninitalProcessDone)
285                         return;
286
287                 super.forceReconciling();
288                 JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
289                 strategy.notifyListeners(false);
290         }
291
292         /*
293          * @see org.eclipse.jface.text.reconciler.AbstractReconciler#aboutToReconcile()
294          * @since 3.0
295          */
296         protected void aboutToBeReconciled() {
297                 JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
298                 strategy.aboutToBeReconciled();
299         }
300
301         /*
302          * @see org.eclipse.jface.text.reconciler.AbstractReconciler#reconcilerReset()
303          */
304         protected void reconcilerReset() {
305                 super.reconcilerReset();
306                 JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
307                 strategy.notifyListeners(true);
308         }
309
310         /*
311          * @see org.eclipse.jface.text.reconciler.MonoReconciler#initialProcess()
312          */
313         protected void initialProcess() {
314                 // TODO remove once we have ensured that there is only one reconciler
315                 // per editor.
316                 synchronized (fMutex) {
317                         super.initialProcess();
318                 }
319                 fIninitalProcessDone = true;
320         }
321
322         /*
323          * @see org.eclipse.jface.text.reconciler.MonoReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion)
324          */
325         protected void process(DirtyRegion dirtyRegion) {
326                 // TODO remove once we have ensured that there is only one reconciler
327                 // per editor.
328                 synchronized (fMutex) {
329                         super.process(dirtyRegion);
330                 }
331         }
332
333         /**
334          * Tells whether the Java Model has changed or not.
335          * 
336          * @return <code>true</code> iff the Java Model has changed
337          * @since 3.0
338          */
339         private synchronized boolean hasJavaModelChanged() {
340                 return fHasJavaModelChanged;
341         }
342
343         /**
344          * Sets whether the Java Model has changed or not.
345          * 
346          * @param state
347          *            <code>true</code> iff the java model has changed
348          * @since 3.0
349          */
350         private synchronized void setJavaModelChanged(boolean state) {
351                 fHasJavaModelChanged = state;
352         }
353 }
354 // /**
355 // * A reconciler that is also activated on editor activation.
356 // */
357 // public class JavaReconciler extends MonoReconciler {
358 //      
359 // /**
360 // * Internal part listener for activating the reconciler.
361 // */
362 // class PartListener implements IPartListener {
363 //              
364 // /*
365 // * @see IPartListener#partActivated(IWorkbenchPart)
366 // */
367 // public void partActivated(IWorkbenchPart part) {
368 // if (part == fTextEditor)
369 // JavaReconciler.this.forceReconciling();
370 // }
371 //
372 // /*
373 // * @see IPartListener#partBroughtToTop(IWorkbenchPart)
374 // */
375 // public void partBroughtToTop(IWorkbenchPart part) {
376 // }
377 //
378 // /*
379 // * @see IPartListener#partClosed(IWorkbenchPart)
380 // */
381 // public void partClosed(IWorkbenchPart part) {
382 // }
383 //
384 // /*
385 // * @see IPartListener#partDeactivated(IWorkbenchPart)
386 // */
387 // public void partDeactivated(IWorkbenchPart part) {
388 // }
389 //
390 // /*
391 // * @see IPartListener#partOpened(IWorkbenchPart)
392 // */
393 // public void partOpened(IWorkbenchPart part) {
394 // }
395 // };
396 //      
397 //      
398 // /** The reconciler's editor */
399 // private ITextEditor fTextEditor;
400 // /** The part listener */
401 // private IPartListener fPartListener;
402 //      
403 //      
404 // /**
405 // * Creates a new reconciler.
406 // */
407 // public JavaReconciler(ITextEditor editor, IReconcilingStrategy strategy,
408 // boolean isIncremental) {
409 // super(strategy, isIncremental);
410 // fTextEditor= editor;
411 // }
412 //      
413 // /*
414 // * @see IReconciler#install(ITextViewer)
415 // */
416 // public void install(ITextViewer textViewer) {
417 // super.install(textViewer);
418 //              
419 // fPartListener= new PartListener();
420 // IWorkbenchPartSite site= fTextEditor.getSite();
421 // IWorkbenchWindow window= site.getWorkbenchWindow();
422 // window.getPartService().addPartListener(fPartListener);
423 // }
424 //
425 // /*
426 // * @see IReconciler#uninstall()
427 // */
428 // public void uninstall() {
429 //              
430 // IWorkbenchPartSite site= fTextEditor.getSite();
431 // IWorkbenchWindow window= site.getWorkbenchWindow();
432 // window.getPartService().removePartListener(fPartListener);
433 // fPartListener= null;
434 //              
435 // super.uninstall();
436 // }
437 //      
438 // /*
439 // * @see AbstractReconciler#forceReconciling()
440 // */
441 // protected void forceReconciling() {
442 // super.forceReconciling();
443 // IReconcilingStrategy strategy=
444 // getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
445 // if (strategy instanceof JavaReconcilingStrategy) {
446 // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
447 // java.notifyParticipants(false);
448 // }
449 // }
450 //    
451 // /*
452 // * @see AbstractReconciler#reconcilerReset()
453 // */
454 // protected void reconcilerReset() {
455 // super.reconcilerReset();
456 // IReconcilingStrategy strategy=
457 // getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
458 // if (strategy instanceof JavaReconcilingStrategy) {
459 // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
460 // java.notifyParticipants(true);
461 // }
462 // }
463 // }