/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.ui.text; import net.sourceforge.phpdt.core.ElementChangedEvent; import net.sourceforge.phpdt.core.IElementChangedListener; import net.sourceforge.phpdt.core.JavaCore; //import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor; import net.sourceforge.phpeclipse.ui.WebUI; import org.eclipse.core.resources.IMarkerDelta; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IWorkspace; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.reconciler.DirtyRegion; import org.eclipse.jface.text.reconciler.MonoReconciler; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.ShellListener; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.texteditor.ITextEditor; /** * A reconciler that is also activated on editor activation. */ public class JavaReconciler extends MonoReconciler { /** * Internal part listener for activating the reconciler. */ private class PartListener implements IPartListener { /* * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart) */ public void partActivated(IWorkbenchPart part) { if (part == fTextEditor && hasJavaModelChanged()) JavaReconciler.this.forceReconciling(); } /* * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart) */ public void partBroughtToTop(IWorkbenchPart part) { } /* * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart) */ public void partClosed(IWorkbenchPart part) { } /* * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart) */ public void partDeactivated(IWorkbenchPart part) { if (part == fTextEditor) setJavaModelChanged(false); } /* * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart) */ public void partOpened(IWorkbenchPart part) { } } /** * Internal Shell activation listener for activating the reconciler. */ private class ActivationListener extends ShellAdapter { private Control fControl; public ActivationListener(Control control) { fControl = control; } /* * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent) */ public void shellActivated(ShellEvent e) { if (!fControl.isDisposed() && fControl.isVisible() && hasJavaModelChanged()) JavaReconciler.this.forceReconciling(); } /* * @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent) */ public void shellDeactivated(ShellEvent e) { setJavaModelChanged(false); } } /** * Internal Java element changed listener * * @since 3.0 */ private class ElementChangedListener implements IElementChangedListener { /* * @see net.sourceforge.phpdt.core.IElementChangedListener#elementChanged(net.sourceforge.phpdt.core.ElementChangedEvent) */ public void elementChanged(ElementChangedEvent event) { setJavaModelChanged(true); } } /** * Internal resource change listener. * * @since 3.0 */ class ResourceChangeListener implements IResourceChangeListener { private IResource getResource() { IEditorInput input = fTextEditor.getEditorInput(); if (input instanceof IFileEditorInput) { IFileEditorInput fileInput = (IFileEditorInput) input; return fileInput.getFile(); } return null; } /* * @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ public void resourceChanged(IResourceChangeEvent e) { IResourceDelta delta = e.getDelta(); IResource resource = getResource(); if (delta != null && resource != null) { IResourceDelta child = delta.findMember(resource.getFullPath()); if (child != null) { IMarkerDelta[] deltas = child.getMarkerDeltas(); if (deltas.length > 0) forceReconciling(); } } } } /** The reconciler's editor */ private ITextEditor fTextEditor; /** The part listener */ private IPartListener fPartListener; /** The shell listener */ private ShellListener fActivationListener; /** * The mutex that keeps us from running multiple reconcilers on one editor. * TODO remove once we have ensured that there is only one reconciler per * editor. */ private Object fMutex; /** * The Java element changed listener. * * @since 3.0 */ private IElementChangedListener fJavaElementChangedListener; /** * Tells whether the Java model sent out a changed event. * * @since 3.0 */ private volatile boolean fHasJavaModelChanged = true; /** * The resource change listener. * * @since 3.0 */ private IResourceChangeListener fResourceChangeListener; private boolean fIninitalProcessDone = false; /** * Creates a new reconciler. */ public JavaReconciler(ITextEditor editor, JavaCompositeReconcilingStrategy strategy, boolean isIncremental) { super(strategy, isIncremental); fTextEditor = editor; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898 // when re-using editors, a new reconciler is set up by the source // viewer // and the old one uninstalled. However, the old reconciler may still be // running. // To avoid having to reconcilers calling // CompilationUnitEditor.reconciled, // we synchronized on a lock object provided by the editor. // The critical section is really the entire run() method of the // reconciler // thread, but synchronizing process() only will keep // JavaReconcilingStrategy // from running concurrently on the same editor. // TODO remove once we have ensured that there is only one reconciler // per editor. if (editor instanceof PHPUnitEditor) fMutex = ((PHPUnitEditor) editor).getReconcilerLock(); else fMutex = new Object(); // Null Object } /* * @see org.eclipse.jface.text.reconciler.IReconciler#install(org.eclipse.jface.text.ITextViewer) */ public void install(ITextViewer textViewer) { super.install(textViewer); fPartListener = new PartListener(); IWorkbenchPartSite site = fTextEditor.getSite(); IWorkbenchWindow window = site.getWorkbenchWindow(); window.getPartService().addPartListener(fPartListener); fActivationListener = new ActivationListener(textViewer.getTextWidget()); Shell shell = window.getShell(); shell.addShellListener(fActivationListener); fJavaElementChangedListener = new ElementChangedListener(); JavaCore.addElementChangedListener(fJavaElementChangedListener); fResourceChangeListener = new ResourceChangeListener(); IWorkspace workspace = WebUI.getWorkspace(); workspace.addResourceChangeListener(fResourceChangeListener); } /* * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall() */ public void uninstall() { IWorkbenchPartSite site = fTextEditor.getSite(); IWorkbenchWindow window = site.getWorkbenchWindow(); window.getPartService().removePartListener(fPartListener); fPartListener = null; Shell shell = window.getShell(); if (shell != null && !shell.isDisposed()) shell.removeShellListener(fActivationListener); fActivationListener = null; JavaCore.removeElementChangedListener(fJavaElementChangedListener); fJavaElementChangedListener = null; IWorkspace workspace = WebUI.getWorkspace(); workspace.removeResourceChangeListener(fResourceChangeListener); fResourceChangeListener = null; super.uninstall(); } /* * @see org.eclipse.jface.text.reconciler.AbstractReconciler#forceReconciling() */ protected void forceReconciling() { if (!fIninitalProcessDone) return; super.forceReconciling(); JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE); strategy.notifyListeners(false); } /* * @see org.eclipse.jface.text.reconciler.AbstractReconciler#aboutToReconcile() * @since 3.0 */ protected void aboutToBeReconciled() { JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE); strategy.aboutToBeReconciled(); } /* * @see org.eclipse.jface.text.reconciler.AbstractReconciler#reconcilerReset() */ protected void reconcilerReset() { super.reconcilerReset(); JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE); strategy.notifyListeners(true); } /* * @see org.eclipse.jface.text.reconciler.MonoReconciler#initialProcess() */ protected void initialProcess() { // TODO remove once we have ensured that there is only one reconciler // per editor. synchronized (fMutex) { super.initialProcess(); } fIninitalProcessDone = true; } /* * @see org.eclipse.jface.text.reconciler.MonoReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion) */ protected void process(DirtyRegion dirtyRegion) { // TODO remove once we have ensured that there is only one reconciler // per editor. synchronized (fMutex) { super.process(dirtyRegion); } } /** * Tells whether the Java Model has changed or not. * * @return true iff the Java Model has changed * @since 3.0 */ private synchronized boolean hasJavaModelChanged() { return fHasJavaModelChanged; } /** * Sets whether the Java Model has changed or not. * * @param state * true iff the java model has changed * @since 3.0 */ private synchronized void setJavaModelChanged(boolean state) { fHasJavaModelChanged = state; } } // /** // * A reconciler that is also activated on editor activation. // */ // public class JavaReconciler extends MonoReconciler { // // /** // * Internal part listener for activating the reconciler. // */ // class PartListener implements IPartListener { // // /* // * @see IPartListener#partActivated(IWorkbenchPart) // */ // public void partActivated(IWorkbenchPart part) { // if (part == fTextEditor) // JavaReconciler.this.forceReconciling(); // } // // /* // * @see IPartListener#partBroughtToTop(IWorkbenchPart) // */ // public void partBroughtToTop(IWorkbenchPart part) { // } // // /* // * @see IPartListener#partClosed(IWorkbenchPart) // */ // public void partClosed(IWorkbenchPart part) { // } // // /* // * @see IPartListener#partDeactivated(IWorkbenchPart) // */ // public void partDeactivated(IWorkbenchPart part) { // } // // /* // * @see IPartListener#partOpened(IWorkbenchPart) // */ // public void partOpened(IWorkbenchPart part) { // } // }; // // // /** The reconciler's editor */ // private ITextEditor fTextEditor; // /** The part listener */ // private IPartListener fPartListener; // // // /** // * Creates a new reconciler. // */ // public JavaReconciler(ITextEditor editor, IReconcilingStrategy strategy, // boolean isIncremental) { // super(strategy, isIncremental); // fTextEditor= editor; // } // // /* // * @see IReconciler#install(ITextViewer) // */ // public void install(ITextViewer textViewer) { // super.install(textViewer); // // fPartListener= new PartListener(); // IWorkbenchPartSite site= fTextEditor.getSite(); // IWorkbenchWindow window= site.getWorkbenchWindow(); // window.getPartService().addPartListener(fPartListener); // } // // /* // * @see IReconciler#uninstall() // */ // public void uninstall() { // // IWorkbenchPartSite site= fTextEditor.getSite(); // IWorkbenchWindow window= site.getWorkbenchWindow(); // window.getPartService().removePartListener(fPartListener); // fPartListener= null; // // super.uninstall(); // } // // /* // * @see AbstractReconciler#forceReconciling() // */ // protected void forceReconciling() { // super.forceReconciling(); // IReconcilingStrategy strategy= // getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE); // if (strategy instanceof JavaReconcilingStrategy) { // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy; // java.notifyParticipants(false); // } // } // // /* // * @see AbstractReconciler#reconcilerReset() // */ // protected void reconcilerReset() { // super.reconcilerReset(); // IReconcilingStrategy strategy= // getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE); // if (strategy instanceof JavaReconcilingStrategy) { // JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy; // java.notifyParticipants(true); // } // } // }