/*
* Copyright (c) 2011, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.internal.text.editor;
import com.google.dart.tools.ui.DartToolsPlugin;
import com.google.dart.tools.ui.DartUI;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
/**
* Provides a shared AST for clients. The shared AST is the AST of the active Dart editor's input
* element.
*/
public final class ASTProvider {
/**
* Wait flag.
*/
public static final class WAIT_FLAG {
String fName;
private WAIT_FLAG(String name) {
fName = name;
}
/*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return fName;
}
}
/**
* Internal activation listener.
*/
private class ActivationListener implements IPartListener2, IWindowListener {
/*
* @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partActivated(IWorkbenchPartReference ref) {
if (isJavaEditor(ref) && !isActiveEditor(ref)) {
activeJavaEditorChanged(ref.getPart(true));
}
}
/*
* @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partBroughtToTop(IWorkbenchPartReference ref) {
if (isJavaEditor(ref) && !isActiveEditor(ref)) {
activeJavaEditorChanged(ref.getPart(true));
}
}
/*
* @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partClosed(IWorkbenchPartReference ref) {
if (isActiveEditor(ref)) {
if (DEBUG) {
System.out.println(getThreadName()
+ " - " + DEBUG_PREFIX + "closed active editor: " + ref.getTitle()); //$NON-NLS-1$ //$NON-NLS-2$
}
activeJavaEditorChanged(null);
}
}
/*
* @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partDeactivated(IWorkbenchPartReference ref) {
}
/*
* @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partHidden(IWorkbenchPartReference ref) {
}
/*
* @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partInputChanged(IWorkbenchPartReference ref) {
if (isJavaEditor(ref) && isActiveEditor(ref)) {
activeJavaEditorChanged(ref.getPart(true));
}
}
/*
* @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partOpened(IWorkbenchPartReference ref) {
if (isJavaEditor(ref) && !isActiveEditor(ref)) {
activeJavaEditorChanged(ref.getPart(true));
}
}
/*
* @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui. IWorkbenchPartReference)
*/
@Override
public void partVisible(IWorkbenchPartReference ref) {
if (isJavaEditor(ref) && !isActiveEditor(ref)) {
activeJavaEditorChanged(ref.getPart(true));
}
}
/*
* @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui. IWorkbenchWindow)
*/
@Override
public void windowActivated(IWorkbenchWindow window) {
IWorkbenchPartReference ref = window.getPartService().getActivePartReference();
if (isJavaEditor(ref) && !isActiveEditor(ref)) {
activeJavaEditorChanged(ref.getPart(true));
}
}
/*
* @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow )
*/
@Override
public void windowClosed(IWorkbenchWindow window) {
if (fActiveEditor != null && fActiveEditor.getSite() != null
&& window == fActiveEditor.getSite().getWorkbenchWindow()) {
if (DEBUG) {
System.out.println(getThreadName()
+ " - " + DEBUG_PREFIX + "closed active editor: " + fActiveEditor.getTitle()); //$NON-NLS-1$ //$NON-NLS-2$
}
activeJavaEditorChanged(null);
}
window.getPartService().removePartListener(this);
}
/*
* @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui. IWorkbenchWindow)
*/
@Override
public void windowDeactivated(IWorkbenchWindow window) {
}
/*
* @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow )
*/
@Override
public void windowOpened(IWorkbenchWindow window) {
window.getPartService().addPartListener(this);
}
private boolean isActiveEditor(IWorkbenchPart part) {
return part != null && (part == fActiveEditor);
}
private boolean isActiveEditor(IWorkbenchPartReference ref) {
return ref != null && isActiveEditor(ref.getPart(false));
}
private boolean isJavaEditor(IWorkbenchPartReference ref) {
if (ref == null) {
return false;
}
String id = ref.getId();
// The instanceof check is not need but helps clients, see
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=84862
return DartUI.ID_CF_EDITOR.equals(id) || DartUI.ID_CU_EDITOR.equals(id)
|| ref.getPart(false) instanceof DartEditor;
}
}
/**
* Wait flag indicating that a client requesting an AST wants to wait until an AST is ready.
* <p>
* An AST will be created by this AST provider if the shared AST is not for the given java
* element.
*/
public static final WAIT_FLAG WAIT_YES = new WAIT_FLAG("wait yes"); //$NON-NLS-1$
/**
* Wait flag indicating that a client requesting an AST only wants to wait for the shared AST of
* the active editor.
* <p>
* No AST will be created by the AST provider.
*/
public static final WAIT_FLAG WAIT_ACTIVE_ONLY = new WAIT_FLAG("wait active only"); //$NON-NLS-1$
/**
* Wait flag indicating that a client requesting an AST only wants the already available shared
* AST.
* <p>
* No AST will be created by the AST provider.
*/
public static final WAIT_FLAG WAIT_NO = new WAIT_FLAG("don't wait"); //$NON-NLS-1$
/**
* Tells whether this class is in debug mode.
*/
private static final boolean DEBUG = "true".equalsIgnoreCase(Platform.getDebugOption("com.google.dart.tools.ui/debug/ASTProvider")); //$NON-NLS-1$//$NON-NLS-2$
public static final int SHARED_AST_LEVEL = 0;
public static final boolean SHARED_AST_STATEMENT_RECOVERY = true;
public static final boolean SHARED_BINDING_RECOVERY = true;
private static final String DEBUG_PREFIX = "ASTProvider > "; //$NON-NLS-1$
/**
* Returns the Java plug-in's AST provider.
*
* @return the AST provider
*/
public static ASTProvider getASTProvider() {
return DartToolsPlugin.getDefault().getASTProvider();
}
private ActivationListener fActivationListener;
private Object fReconcileLock = new Object();
private Object fWaitLock = new Object();
private boolean fIsReconciling;
private IWorkbenchPart fActiveEditor;
/**
* Creates a new AST provider.
*/
public ASTProvider() {
install();
}
/**
* Disposes this AST provider.
*/
public void dispose() {
// Dispose activation listener
PlatformUI.getWorkbench().removeWindowListener(fActivationListener);
fActivationListener = null;
synchronized (fWaitLock) {
fWaitLock.notifyAll();
}
}
/**
* Installs this AST provider.
*/
void install() {
// Create and register activation listener
fActivationListener = new ActivationListener();
PlatformUI.getWorkbench().addWindowListener(fActivationListener);
// Ensure existing windows get connected
IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
for (int i = 0, length = windows.length; i < length; i++) {
windows[i].getPartService().addPartListener(fActivationListener);
}
}
void reconciled(IProgressMonitor progressMonitor) {
if (DEBUG) {
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "reconciled: null"); //$NON-NLS-1$ //$NON-NLS-2$
}
synchronized (fReconcileLock) {
fIsReconciling = progressMonitor != null && progressMonitor.isCanceled();
if (DEBUG) {
System.out.println(getThreadName()
+ " - " + DEBUG_PREFIX + " ignoring AST of out-dated editor"); //$NON-NLS-1$ //$NON-NLS-2$
}
// Signal - threads might wait for wrong element
synchronized (fWaitLock) {
fWaitLock.notifyAll();
}
return;
}
}
private void activeJavaEditorChanged(IWorkbenchPart editor) {
synchronized (this) {
fActiveEditor = editor;
}
if (DEBUG) {
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "active editor is: null"); //$NON-NLS-1$ //$NON-NLS-2$
}
synchronized (fReconcileLock) {
fIsReconciling = false;
}
}
private String getThreadName() {
String name = Thread.currentThread().getName();
if (name != null) {
return name;
} else {
return Thread.currentThread().toString();
}
}
}