/*******************************************************************************
* Copyright (c) 2005, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.DOMAST;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.views.properties.PropertySheet;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ParserUtil;
import org.eclipse.cdt.core.resources.FileStorage;
import org.eclipse.cdt.ui.actions.CustomFiltersActionGroup;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.cdt.internal.core.dom.parser.c.CASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.model.ASTStringUtil;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
/**
* This is a simple DOM AST View used for development testing.
*/
public class DOMAST extends ViewPart {
public static final String VIEW_ID = "org.eclipse.cdt.ui.tests.DOMAST.DOMAST"; //$NON-NLS-1$
private static final String PROPERTIES_VIEW = "org.eclipse.ui.views.PropertySheet"; //$NON-NLS-1$
private static final String ASTUTIL_MENU_LABEL = "ASTUtil#"; //$NON-NLS-1$
private static final String DISPLAY_TYPE = "getNodeType(IASTNode)"; //$NON-NLS-1$
private static final String DISPLAY_SIGNATURE = "getNodeSignature(IASTNode)"; //$NON-NLS-1$
private static final String DISPLAY_EXPRESSION = "getExpressionString(IASTExpression)"; //$NON-NLS-1$
private static final String DISPLAY_INITIALIZER = "getInitializerString(IASTInitializer)"; //$NON-NLS-1$
private static final String NOT_VALID_COMPILATION_UNIT = "The active editor does not contain a valid compilation unit."; //$NON-NLS-1$
private static final String EXTENSION_CXX = "CXX"; //$NON-NLS-1$
private static final String EXTENSION_CPP = "CPP"; //$NON-NLS-1$
private static final String EXTENSION_CC = "CC"; //$NON-NLS-1$
private static final String EXTENSION_C = "C"; //$NON-NLS-1$
private static final String DOM_AST_HAS_NO_CONTENT = "DOM AST has no content"; //$NON-NLS-1$
private static final String SEARCH_FOR_IASTNAME = "Search for IASTName"; //$NON-NLS-1$
private static final String CLEAR = "Clear"; //$NON-NLS-1$
private static final String DOMAST_FILTER_GROUP_ID = "org.eclipse.cdt.ui.tests.DOMAST.DOMASTFilterGroup"; //$NON-NLS-1$
private static final String LOAD_ACTIVE_EDITOR = "Load Active Editor"; //$NON-NLS-1$
private static final String COLLAPSE_ALL = "Collapse ALL"; //$NON-NLS-1$
private static final String EXPAND_ALL = "Expand All"; //$NON-NLS-1$
private static final String REFRESH_DOM_AST = "Refresh DOM AST"; //$NON-NLS-1$
public static final String VIEW_NAME = "DOM View"; //$NON-NLS-1$
private static final String POPUPMENU = "#PopupMenu"; //$NON-NLS-1$
private static final String OPEN_DECLARATIONS = "Open Declarations"; //$NON-NLS-1$
private static final String OPEN_REFERENCES = "Open References"; //$NON-NLS-1$
private static final String DISPLAY_PROBLEMS = "Display Problems"; //$NON-NLS-1$
TreeViewer viewer;
private DrillDownAdapter drillDownAdapter;
private Action displayProblemsAction;
private Action displayNodeTypeAction;
private Action displayNodeSignatureAction;
private Action displayExpressionAction;
private Action displayInitializerAction;
protected Action singleClickAction;
private Action loadActiveEditorAction;
private Action refreshAction;
private Action expandAllAction;
private Action collapseAllAction;
private Action clearAction;
private Action searchNamesAction;
protected ITranslationUnit tu = null;
private IEditorPart part = null;
private CustomFiltersActionGroup customFiltersActionGroup;
protected static ViewContentProvider.StartInitializingASTView initializeASTViewJob = null;
/*
* The content provider class is responsible for providing objects to the
* view. It can wrap existing objects in adapters or simply return objects
* as-is. These objects may be sensitive to the current input of the view, or
* ignore it and always show the same content (like Task List, for example).
*/
public class ViewContentProvider implements IStructuredContentProvider,
ITreeContentProvider {
private static final String POPULATING_AST_VIEW = "Populating AST View"; //$NON-NLS-1$
private DOMASTNodeParent invisibleRoot;
private DOMASTNodeParent tuTreeParent = null;
private IASTTranslationUnit tu = null;
protected IASTProblem[] astProblems = null;
public ViewContentProvider() {
}
public ViewContentProvider(ITranslationUnit tu) {
this(tu, null);
}
public ViewContentProvider(ITranslationUnit tu, Object[] expanded) {
initializeASTViewJob = new StartInitializingASTView(new InitializeView(POPULATING_AST_VIEW, this, viewer, tu), expanded);
initializeASTViewJob.schedule();
}
public DOMASTNodeParent getTUTreeParent() {
if (tuTreeParent == null && invisibleRoot != null) {
for(int i=0; i<invisibleRoot.getChildren().length; i++) {
if (invisibleRoot.getChildren()[i] instanceof DOMASTNodeParent && invisibleRoot.getChildren()[i].getNode() instanceof IASTTranslationUnit){
tuTreeParent = (DOMASTNodeParent)invisibleRoot.getChildren()[i];
return tuTreeParent;
}
}
}
return tuTreeParent;
}
public IASTTranslationUnit getTU() {
if (tu == null && invisibleRoot != null) {
for(int i=0; i<invisibleRoot.getChildren().length; i++) {
if (invisibleRoot.getChildren()[i] instanceof DOMASTNodeParent && invisibleRoot.getChildren()[i].getNode() instanceof IASTTranslationUnit){
tu = (IASTTranslationUnit)invisibleRoot.getChildren()[i].getNode();
}
}
}
return tu;
}
public void dispose() {
}
public Object[] getElements(Object parent) {
if (parent.equals(getViewSite())) {
if (invisibleRoot == null)
initialize();
return getChildren(invisibleRoot);
}
return getChildren(parent);
}
public Object getParent(Object child) {
if (child instanceof DOMASTNodeLeaf) {
return ((DOMASTNodeLeaf) child).getParent();
}
return null;
}
public Object[] getChildren(Object parent) {
if (parent instanceof DOMASTNodeParent) {
return ((DOMASTNodeParent) parent).getChildren();
}
return new Object[0];
}
public boolean hasChildren(Object parent) {
if (parent instanceof DOMASTNodeParent)
return ((DOMASTNodeParent) parent).hasChildren();
return false;
}
private class StartInitializingASTView extends Job {
private static final String INITIALIZE_AST_VIEW = "Initialize AST View"; //$NON-NLS-1$
InitializeView job = null;
Object[] expanded = null;
public StartInitializingASTView(InitializeView job, Object[] expanded) {
super(INITIALIZE_AST_VIEW);
this.job = job;
this.expanded = expanded;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
job.schedule();
try {
job.join();
} catch (InterruptedException ie) {
return Status.CANCEL_STATUS;
}
CTestPlugin.getStandardDisplay().asyncExec(new InitializeRunnable(viewer)); // update the view from the Display thread
// if there are objects to expand then do so now
if (expanded != null) {
CTestPlugin.getStandardDisplay().asyncExec(new Runnable() {
public void run() {
// set the expansion of the view based on the original snapshot (educated guess)
Tree tree = viewer.getTree();
expandTreeIfNecessary(tree.getItems(), expanded);
}
private void expandTreeIfNecessary(TreeItem[] tree, Object[] theExpanded) {
for (TreeItem element : tree) {
for (Object element2 : theExpanded) {
if (element2 instanceof DOMASTNodeLeaf &&
element.getData() instanceof DOMASTNodeLeaf &&
((DOMASTNodeLeaf)element2).toString().equals(((DOMASTNodeLeaf)element.getData()).toString()) &&
((DOMASTNodeLeaf)element2).getOffset() == (((DOMASTNodeLeaf)element.getData()).getOffset())) {
element.setExpanded(true);
viewer.refresh();
expandTreeIfNecessary(element.getItems(), theExpanded);
}
}
}
}});
}
return job.getResult();
}
}
private class InitializeView extends Job {
private static final String COLON_SPACE = ": "; //$NON-NLS-1$
private static final String DOM_AST_VIEW_DONE = "[DOM AST View] done "; //$NON-NLS-1$
private static final String DOM_AST_VIEW_FINISHED = "[DOM AST View] finished: "; //$NON-NLS-1$
private static final String RETRIEVING_PREPROCESSOR_PROBLEMS = "Retrieving all preprocessor problems from TU"; //$NON-NLS-1$
private static final String RETRIEVING_PREPROCESSOR_STATEMENTS = "Retrieving all preprocessor statements from TU"; //$NON-NLS-1$
private static final String _PREPROCESSOR_PROBLEMS_ = " preprocessor problems"; //$NON-NLS-1$
private static final String _PREPROCESSOR_STATEMENTS_ = " preprocessor statements"; //$NON-NLS-1$
private static final String MERGING_ = "Merging "; //$NON-NLS-1$
private static final String GROUPING_AST = "Grouping AST View according to includes"; //$NON-NLS-1$
private static final String GENERATING_INITIAL_TREE = "Generating initial AST Tree for the View"; //$NON-NLS-1$
private static final String PARSING_TRANSLATION_UNIT = "Parsing Translation Unit"; //$NON-NLS-1$
String name = null;
DOMASTNodeParent root = null;
ViewContentProvider provider = null;
TreeViewer view = null;
ITranslationUnit tu = null;
/**
* @param name
*/
public InitializeView(String name, ViewContentProvider provider, TreeViewer view, ITranslationUnit tu) {
super(name);
this.name = name;
setUser(true);
this.provider = provider;
this.view = view;
this.tu = tu;
}
public DOMASTNodeParent getInvisibleRoot() {
return root;
}
/**
* @return Returns the scheduling rule for this operation
*/
public ISchedulingRule getScheduleRule() {
return ResourcesPlugin.getWorkspace().getRoot();
}
/* (non-Javadoc)
* @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
long start=0;
long overallStart=System.currentTimeMillis();
if (tu == null || monitor == null)
return Status.CANCEL_STATUS;
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
monitor.beginTask(name, 100);
start=System.currentTimeMillis();
IPopulateDOMASTAction action = null;
IASTTranslationUnit aTu;
try {
monitor.subTask(PARSING_TRANSLATION_UNIT);
start=System.currentTimeMillis();
aTu = tu.getAST();
monitor.worked(30);
System.out.println(DOM_AST_VIEW_DONE + PARSING_TRANSLATION_UNIT + COLON_SPACE + (System.currentTimeMillis()- start) );
} catch (CoreException e) {
return Status.CANCEL_STATUS;
}
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
monitor.subTask(GENERATING_INITIAL_TREE);
start=System.currentTimeMillis();
if (aTu instanceof CPPASTTranslationUnit ) {
action = new CPPPopulateASTViewAction(aTu, monitor);
aTu.accept( (ASTVisitor) action);
}
else if (aTu instanceof CASTTranslationUnit){
action = new CPopulateASTViewAction(aTu, monitor);
aTu.accept( (ASTVisitor) action);
}
monitor.worked(30);
System.out.println(DOM_AST_VIEW_DONE + GENERATING_INITIAL_TREE + COLON_SPACE + (System.currentTimeMillis()- start) );
// display roots
root = new DOMASTNodeParent(null);
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
monitor.subTask(RETRIEVING_PREPROCESSOR_STATEMENTS);
start=System.currentTimeMillis();
IASTPreprocessorStatement[] statements = aTu.getAllPreprocessorStatements();
monitor.worked(5);
System.out.println(DOM_AST_VIEW_DONE + RETRIEVING_PREPROCESSOR_STATEMENTS + COLON_SPACE + (System.currentTimeMillis()- start) );
monitor.subTask(MERGING_ + statements.length + _PREPROCESSOR_STATEMENTS_);
start=System.currentTimeMillis();
// merge preprocessor statements to the tree
DOMASTNodeLeaf[] includeStatements = action.mergePreprocessorStatements(statements);
monitor.worked(2);
System.out.println(DOM_AST_VIEW_DONE + MERGING_ + statements.length + _PREPROCESSOR_STATEMENTS_ + COLON_SPACE + (System.currentTimeMillis()- start) );
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
monitor.subTask(RETRIEVING_PREPROCESSOR_PROBLEMS);
start=System.currentTimeMillis();
IASTProblem[] problems = aTu.getPreprocessorProblems();
monitor.worked(2);
System.out.println(DOM_AST_VIEW_DONE + RETRIEVING_PREPROCESSOR_PROBLEMS + COLON_SPACE + (System.currentTimeMillis()- start) );
monitor.subTask(MERGING_ + problems.length + _PREPROCESSOR_PROBLEMS_);
start=System.currentTimeMillis();
// merge preprocessor problems to the tree
action.mergePreprocessorProblems(problems);
monitor.worked(1);
System.out.println(DOM_AST_VIEW_DONE + MERGING_ + problems.length + _PREPROCESSOR_PROBLEMS_ + COLON_SPACE + (System.currentTimeMillis()- start) );
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
monitor.subTask(GROUPING_AST);
start=System.currentTimeMillis();
// group #includes
action.groupIncludes(includeStatements);
monitor.worked(30);
System.out.println(DOM_AST_VIEW_DONE + GROUPING_AST + COLON_SPACE + (System.currentTimeMillis()- start) );
root.addChild(action.getTree());
// get the IASTProblems from the action
if (action instanceof CPopulateASTViewAction)
astProblems = ((CPopulateASTViewAction)action).getASTProblems();
else if (action instanceof CPPPopulateASTViewAction)
astProblems = ((CPPPopulateASTViewAction)action).getASTProblems();
provider.setInvisibleRoot(root);
monitor.done();
System.out.println(DOM_AST_VIEW_FINISHED + (System.currentTimeMillis()- overallStart) );
return Status.OK_STATUS;
}
}
public IASTProblem[] getASTProblems() {
return astProblems;
}
private void initialize() {
invisibleRoot = new DOMASTNodeParent(); // blank the AST View, when the job above is complete it will update the AST View with the proper tree
}
protected void setInvisibleRoot(DOMASTNodeParent root) {
invisibleRoot = root;
}
public class InitializeRunnable implements Runnable {
TreeViewer view = null;
public InitializeRunnable(TreeViewer view) {
this.view = view;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
if (view == null) return;
if (view.getTree().isDisposed())
return;
view.refresh();
if (view.getTree().getItems().length > 0) {
TreeItem[] selection = new TreeItem[1];
selection[0] = view.getTree().getItems()[0];
// select the first item to prevent it from being selected accidentally (and possibly switching editors accidentally)
view.getTree().setSelection(selection);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer aViewer, Object oldInput, Object newInput) {
}
private TreeItem expandTreeToTreeObject(TreeItem[] treeItems, DOMASTNodeLeaf treeObj) {
for (TreeItem treeItem : treeItems) {
if (treeItem.getData() == treeObj) {
return treeItem;
}
DOMASTNodeParent parent = treeObj.getParent();
if (parent == null) return null;
while (parent != treeItem.getData()) {
parent = parent.getParent();
if (parent == null) break;
}
if (parent == treeItem.getData()) {
treeItem.setExpanded(true);
viewer.refresh();
return expandTreeToTreeObject(treeItem.getItems(), treeObj);
}
}
return null; // nothing found
}
private TreeItem expandTreeToTreeObject(DOMASTNodeLeaf treeObj) {
return expandTreeToTreeObject(viewer.getTree().getItems(), treeObj);
}
/**
* Find an ASTNode in the tree and expand the tree to that node.
* Returns true if successful, false otherwise.
*
* @param offset
* @param findString
* @param searchForward
* @param caseSensitive
* @param wholeWord
* @param regExSearch
* @return
*/
public boolean findAndSelect(IASTNode node, boolean useOffset) {
// get the DOMASTNodeLeaf from the AST View's model corresponding to the IASTNode
DOMASTNodeLeaf treeNode = null;
TreeItem treeItem = null;
treeNode = getTUTreeParent().findTreeObject(node, useOffset);
if (treeNode != null && treeNode.getParent() != null) {
// found a matching DOMASTNodeLeaf, so expand the tree to that object
treeItem = expandTreeToTreeObject(treeNode);
}
// select the node that was found (and is now displayed)
if (treeItem != null) {
TreeItem[] items = new TreeItem[1];
items[0] = treeItem;
treeItem.getParent().setSelection(items);
return true;
}
return false;
}
}
class ViewLabelProvider extends LabelProvider {
private static final String BLANK_STRING = ""; //$NON-NLS-1$
@Override
public String getText(Object obj) {
if (obj == null) return BLANK_STRING;
return obj.toString();
}
@Override
public Image getImage(Object obj) {
String imageKey = DOMASTPluginImages.IMG_DEFAULT;
IASTNode node = null;
if (obj instanceof DOMASTNodeLeaf) {
node = ((DOMASTNodeLeaf) obj).getNode();
}
if (node instanceof IASTArrayModifier) {
imageKey = DOMASTPluginImages.IMG_IASTArrayModifier;
} else if (node instanceof IASTDeclaration) {
if (node instanceof IASTProblemDeclaration)
imageKey = DOMASTPluginImages.IMG_IASTProblem;
else
imageKey = DOMASTPluginImages.IMG_IASTDeclaration;
} else if (node instanceof IASTDeclarator) {
imageKey = DOMASTPluginImages.IMG_IASTDeclarator;
} else if (node instanceof IASTDeclSpecifier) {
imageKey = DOMASTPluginImages.IMG_IASTDeclSpecifier;
} else if (node instanceof IASTEnumerator) {
imageKey = DOMASTPluginImages.IMG_IASTEnumerator;
} else if (node instanceof IASTExpression) {
if (node instanceof IASTProblemExpression)
imageKey = DOMASTPluginImages.IMG_IASTProblem;
else
imageKey = DOMASTPluginImages.IMG_IASTExpression;
} else if (node instanceof IASTInitializer) {
imageKey = DOMASTPluginImages.IMG_IASTInitializer;
} else if (node instanceof IASTName) {
imageKey = DOMASTPluginImages.IMG_IASTName;
} else if (node instanceof IASTParameterDeclaration) {
imageKey = DOMASTPluginImages.IMG_IASTParameterDeclaration;
} else if (node instanceof IASTPointerOperator) {
imageKey = DOMASTPluginImages.IMG_IASTPointerOperator;
} else if (node instanceof IASTPreprocessorStatement) {
imageKey = DOMASTPluginImages.IMG_IASTPreprocessorStatement;
} else if (node instanceof IASTProblem) {
imageKey = DOMASTPluginImages.IMG_IASTProblem;
} else if (node instanceof IASTSimpleDeclaration) {
imageKey = DOMASTPluginImages.IMG_IASTSimpleDeclaration;
} else if (node instanceof IASTStatement) {
if (node instanceof IASTProblemStatement)
imageKey = DOMASTPluginImages.IMG_IASTProblem;
else
imageKey = DOMASTPluginImages.IMG_IASTStatement;
} else if (node instanceof IASTTranslationUnit) {
imageKey = DOMASTPluginImages.IMG_IASTTranslationUnit;
} else if (node instanceof IASTTypeId) {
imageKey = DOMASTPluginImages.IMG_IASTTypeId;
} else if (node instanceof ICASTDesignator) {
imageKey = DOMASTPluginImages.IMG_ICASTDesignator;
} else if (node instanceof ICPPASTConstructorChainInitializer) {
imageKey = DOMASTPluginImages.IMG_ICPPASTConstructorChainInitializer;
} else if (node instanceof ICPPASTTemplateParameter) {
imageKey = DOMASTPluginImages.IMG_ICPPASTTemplateParameter;
}
return DOMASTPluginImages.get(imageKey);
}
}
class NameSorter extends ViewerSorter {
}
public DOMAST() {
}
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
@Override
public void createPartControl(Composite parent) {
if (part == null) {
part = getActiveEditor();
}
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
drillDownAdapter = new DrillDownAdapter(viewer);
if (part instanceof CEditor) {
ICElement inputElement = ((CEditor)part).getInputCElement();
if(inputElement instanceof ITranslationUnit) {
viewer.setContentProvider(new ViewContentProvider((ITranslationUnit)inputElement));
setTranslationUnit((ITranslationUnit)inputElement);
}
else {
viewer.setContentProvider(new ViewContentProvider(null));
}
} else {
viewer.setContentProvider(new ViewContentProvider(null)); // don't attempt to create a view based on old file info
}
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setInput(getViewSite());
makeActions();
hookContextMenu();
hookSingleClickAction();
customFiltersActionGroup = new CustomFiltersActionGroup(DOMAST_FILTER_GROUP_ID, viewer);
contributeToActionBars();
viewer.addSelectionChangedListener(new UpdatePropertiesListener());
}
private class UpdatePropertiesListener implements ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = viewer.getSelection();
IViewPart propertyPart = getSite().getPage().findView(PROPERTIES_VIEW);
if (propertyPart instanceof PropertySheet) {
((PropertySheet)propertyPart).selectionChanged(getSite().getPart(), selection);
}
}
}
public void setContentProvider(ViewContentProvider vcp) {
if (viewer == null) return;
viewer.setContentProvider(vcp);
}
public IContentProvider getContentProvider() {
return viewer.getContentProvider();
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager(POPUPMENU);
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
private void hideMenuItems(IMenuManager manager) {
IContributionItem[] items = manager.getItems();
for (IContributionItem item : items) {
if (item instanceof IMenuManager) {
hideMenuItems((IMenuManager)item);
}
if (item instanceof ActionContributionItem) {
String text = ((ActionContributionItem) item).getAction().getText();
IASTNode selectedNode = null;
if (viewer.getSelection() instanceof StructuredSelection
&& ((StructuredSelection) viewer.getSelection())
.getFirstElement() instanceof DOMASTNodeLeaf) {
selectedNode = ((DOMASTNodeLeaf) ((StructuredSelection) viewer
.getSelection()).getFirstElement()).getNode();
}
if (text.equals(OPEN_REFERENCES) || text.equals(OPEN_DECLARATIONS)) {
if (selectedNode instanceof IASTName) {
item.setVisible(true);
} else {
item.setVisible(false);
}
}
if (text.equals(DISPLAY_SIGNATURE)) {
if (selectedNode instanceof IASTDeclarator ||
selectedNode instanceof IASTDeclSpecifier ||
selectedNode instanceof IASTTypeId) {
item.setVisible(true);
} else {
item.setVisible(false);
}
} else if (text.equals(DISPLAY_TYPE)) {
if (selectedNode instanceof IASTDeclarator ||
selectedNode instanceof IASTTypeId ||
(selectedNode instanceof IASTName && (
((IASTName)selectedNode).resolveBinding() instanceof IVariable ||
((IASTName)selectedNode).resolveBinding() instanceof IFunction ||
((IASTName)selectedNode).resolveBinding() instanceof IType))) {
item.setVisible(true);
} else {
item.setVisible(false);
}
} else if (text.equals(DISPLAY_EXPRESSION)) {
if (selectedNode instanceof IASTExpression) {
item.setVisible(true);
} else {
item.setVisible(false);
}
} else if (text.equals(DISPLAY_INITIALIZER)) {
if (selectedNode instanceof IASTInitializer) {
item.setVisible(true);
} else {
item.setVisible(false);
}
}
}
}
}
public void menuAboutToShow(IMenuManager manager) {
DOMAST.this.fillContextMenu(manager);
hideMenuItems(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
customFiltersActionGroup.fillActionBars(bars);
}
private void fillLocalPullDown(IMenuManager manager) {
}
void fillContextMenu(IMenuManager manager) {
manager.add(new Separator());
// ASTUtil#... menu
MenuManager astMenu = new MenuManager(ASTUTIL_MENU_LABEL);
astMenu.add(displayNodeTypeAction);
astMenu.add(displayNodeSignatureAction);
astMenu.add(displayExpressionAction);
astMenu.add(displayInitializerAction);
manager.add(astMenu);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(expandAllAction);
manager.add(collapseAllAction);
manager.add(new Separator());
manager.add(refreshAction);
manager.add(loadActiveEditorAction);
manager.add(new Separator());
manager.add(clearAction);
manager.add(new Separator());
manager.add(searchNamesAction);
// manager.add(displayProblemsAction);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
}
private void makeActions() {
loadActiveEditorAction = new Action() {
@Override
public void run() {
// first make sure there is an open editor
IEditorPart editor = getActiveEditor();
if (editor != null) {
openDOMASTView(getActiveEditor());
}
}
};
loadActiveEditorAction.setText(LOAD_ACTIVE_EDITOR);
loadActiveEditorAction.setToolTipText(LOAD_ACTIVE_EDITOR);
loadActiveEditorAction.setImageDescriptor(DOMASTPluginImages.DESC_RELOAD_VIEW);
refreshAction = new Action() {
@Override
public void run() {
// take a snapshot of the tree expansion
Object[] expanded = viewer.getExpandedElements();
// set the new content provider
setContentProvider(new ViewContentProvider(tu, expanded));
}
};
refreshAction.setText(REFRESH_DOM_AST);
refreshAction.setToolTipText(REFRESH_DOM_AST);
refreshAction.setImageDescriptor(DOMASTPluginImages.DESC_REFRESH_VIEW);
expandAllAction = new Action() {
@Override
public void run() {
viewer.expandAll();
}
};
expandAllAction.setText(EXPAND_ALL);
expandAllAction.setToolTipText(EXPAND_ALL);
expandAllAction.setImageDescriptor(DOMASTPluginImages.DESC_EXPAND_ALL);
collapseAllAction = new Action() {
@Override
public void run() {
viewer.collapseAll();
}
};
collapseAllAction.setText(COLLAPSE_ALL);
collapseAllAction.setToolTipText(COLLAPSE_ALL);
collapseAllAction.setImageDescriptor(DOMASTPluginImages.DESC_COLLAPSE_ALL);
clearAction = new Action() {
@Override
public void run() {
viewer.setContentProvider(new ViewContentProvider(null));
viewer.refresh();
}
};
clearAction.setText(CLEAR);
clearAction.setToolTipText(CLEAR);
clearAction.setImageDescriptor(DOMASTPluginImages.DESC_CLEAR);
searchNamesAction = new Action() {
private void performSearch() {
if (viewer.getTree().getItems().length == 0) {
showMessage(DOM_AST_HAS_NO_CONTENT);
}
FindIASTNameDialog dialog = new FindIASTNameDialog(getSite().getShell(), new FindIASTNameTarget(viewer));
dialog.open();
}
@Override
public void run() {
performSearch();
}
};
searchNamesAction.setText(SEARCH_FOR_IASTNAME);
searchNamesAction.setToolTipText(SEARCH_FOR_IASTNAME);
searchNamesAction.setImageDescriptor(DOMASTPluginImages.DESC_SEARCH_NAMES);
displayNodeTypeAction = new Action() {
@Override
public void run() {
ISelection selection = viewer.getSelection();
if (selection instanceof IStructuredSelection &&
((IStructuredSelection)selection).getFirstElement() instanceof DOMASTNodeLeaf &&
((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode() != null) {
showMessage("ASTUtil#getNodeType(IASTNode): \"" + ASTTypeUtil.getNodeType(((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode()) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
} };
displayNodeTypeAction.setText(DISPLAY_TYPE);
displayNodeTypeAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
displayNodeSignatureAction = new Action() {
@Override
public void run() {
ISelection selection = viewer.getSelection();
if (selection instanceof IStructuredSelection &&
((IStructuredSelection)selection).getFirstElement() instanceof DOMASTNodeLeaf &&
((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode() != null) {
showMessage("Node Signature: \"" + getNodeSignature(((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode()) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
} };
displayNodeSignatureAction.setText(DISPLAY_SIGNATURE);
displayNodeSignatureAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
displayExpressionAction = new Action() {
@Override
public void run() {
ISelection selection = viewer.getSelection();
if (selection instanceof IStructuredSelection &&
((IStructuredSelection)selection).getFirstElement() instanceof DOMASTNodeLeaf &&
((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode() instanceof IASTExpression) {
showMessage("Expression String: \"" + ASTStringUtil.getExpressionString((IASTExpression)((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode()) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
} };
displayExpressionAction.setText(DISPLAY_EXPRESSION);
displayExpressionAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
displayInitializerAction = new Action() {
@Override
public void run() {
ISelection selection = viewer.getSelection();
if (selection instanceof IStructuredSelection &&
((IStructuredSelection)selection).getFirstElement() instanceof DOMASTNodeLeaf &&
((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode() instanceof IASTInitializer) {
showMessage("Initializer String: \"" + ASTStringUtil.getInitializerString((IASTInitializer)((DOMASTNodeLeaf)((IStructuredSelection)selection).getFirstElement()).getNode()) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
} };
displayInitializerAction.setText(DISPLAY_INITIALIZER);
displayInitializerAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
singleClickAction = new ASTHighlighterAction(part);
}
protected static String getNodeSignature(IASTNode node) {
if (node instanceof IASTDeclarator)
return ASTStringUtil.getSignatureString(null, (IASTDeclarator) node);
if (node instanceof IASTDeclSpecifier)
return ASTStringUtil.getSignatureString((IASTDeclSpecifier) node, null);
if (node instanceof IASTTypeId) {
final IASTTypeId typeId = (IASTTypeId) node;
return ASTStringUtil.getSignatureString(typeId.getDeclSpecifier(), typeId.getAbstractDeclarator());
}
if (node instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration decl = (IASTSimpleDeclaration) node;
StringBuffer buffer = new StringBuffer();
buffer.append(getNodeSignature(decl.getDeclSpecifier()));
IASTDeclarator[] declarators = decl.getDeclarators();
for (int i = 0; i < declarators.length; ++i) {
buffer.append(" ");
buffer.append(getNodeSignature(declarators[i]));
if (declarators[i].getInitializer() != null
&& declarators[i].getInitializer() instanceof ICPPASTConstructorInitializer) {
buffer.append(ASTStringUtil.getInitializerString(declarators[i].getInitializer()));
}
}
buffer.append(";"); //$NON-NLS-1$
return buffer.toString();
}
if (node instanceof IASTExpression) {
return ASTStringUtil.getExpressionString((IASTExpression) node);
}
return "";
}
protected IEditorPart getActiveEditor() {
IEditorPart editor = null;
if (getSite().getPage().isEditorAreaVisible()
&& getSite().getPage().getActiveEditor() != null
&& getSite().getPage().getActiveEditor() instanceof CEditor) {
editor = getSite().getPage().getActiveEditor();
part = editor;
}
return editor;
}
private class ASTHighlighterAction extends Action {
private static final String A_PART_INSTANCEOF = "aPart instanceof "; //$NON-NLS-1$
IEditorPart aPart = null;
public ASTHighlighterAction(IEditorPart part) {
this.aPart = part;
}
public void setPart(IEditorPart part) {
this.aPart = part;
}
protected boolean open(String filename) throws PartInitException,
CModelException {
IPath path = new Path(filename);
IFile f = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
path);
if (f != null) {
EditorUtility.openInEditor(f);
return true;
}
FileStorage storage = new FileStorage(null, path);
EditorUtility.openInEditor(storage);
return true;
}
@Override
public void run() {
ISelection selection = viewer.getSelection();
Object obj = ((IStructuredSelection) selection).getFirstElement();
if (obj instanceof DOMASTNodeLeaf) {
if (((DOMASTNodeLeaf)obj).getNode() instanceof IASTTranslationUnit) // don't do anything for TU
return;
String filename = ((DOMASTNodeLeaf) obj).getFilename();
if (filename.equals(DOMASTNodeLeaf.BLANK_STRING))
return;
IResource r = ParserUtil.getResourceForFilename(filename);
if (r != null) {
try {
aPart = EditorUtility.openInEditor(r);
} catch (PartInitException pie) {
return;
} catch (CModelException e) {
return;
}
} else {
IPath path = new Path( filename );
if (tu != null) {
try {
aPart = EditorUtility.openInEditor(path, tu);
} catch (PartInitException e) {
return;
}
}
}
if( aPart instanceof AbstractTextEditor )
{
((AbstractTextEditor) aPart).selectAndReveal(((DOMASTNodeLeaf) obj).getOffset(),
((DOMASTNodeLeaf) obj).getLength());
}
else
System.out.println( A_PART_INSTANCEOF + aPart.getClass().getName() );
aPart.getSite().getPage().activate(aPart.getSite().getPage().findView(VIEW_ID));
}
}
}
private void hookSingleClickAction() {
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
singleClickAction.run();
}
});
}
void showMessage(String message) {
MessageDialog.openInformation(viewer.getControl().getShell(), VIEW_NAME,
message.replaceAll("&", "&&")); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
if (viewer==null) return;
viewer.getControl().setFocus();
ISelection selection = viewer.getSelection();
IViewPart propertyPart = getSite().getPage().findView(PROPERTIES_VIEW);
if (propertyPart instanceof PropertySheet) {
((PropertySheet)propertyPart).selectionChanged(getSite().getPart(), selection);
}
}
public void setPart(IEditorPart part) {
this.part = part;
if (singleClickAction instanceof ASTHighlighterAction)
((ASTHighlighterAction) singleClickAction).setPart(part);
}
public void setTranslationUnit(ITranslationUnit tu) {
this.tu = tu;
}
private class RunAfterViewOpenJob extends Job {
Runnable runner = null;
/**
*
*/
public RunAfterViewOpenJob(String name, Runnable runner) {
super(name);
this.runner = runner;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
initializeASTViewJob.join();
CTestPlugin.getStandardDisplay().asyncExec(runner);
} catch (InterruptedException ie) {}
return Status.OK_STATUS;
}
}
/**
* Open the DOM AST View and return a reference to it. This helper method can also be used to run an
* Action after the DOM AST View has been fully loaded (like find/select nodes in the view).
*
* Note: The action is not guaranteed to run. An example would be if loading the view is canceled.
*
* @param editor
* @param action
* @return
*/
public static IViewPart openDOMASTViewRunAction(IEditorPart editor, Runnable runnable, String nameOfJob) {
IViewPart view = openDOMASTView(editor);
if (view == null) return null;
RunAfterViewOpenJob job = ((DOMAST)view).new RunAfterViewOpenJob(nameOfJob, runnable);
job.schedule();
return view;
}
/**
* Open the DOM AST View and return a reference to it.
*
* @param editor
* @return
*/
public static IViewPart openDOMASTView(IEditorPart editor) {
IWorkbenchPartSite site = editor.getSite();
Shell shell = site.getShell();
IViewPart tempView = null;
// get the active editor
if (editor instanceof CEditor) {
try {
tempView = site.getPage().showView(VIEW_ID);
} catch (PartInitException pie) {}
if (tempView != null) {
if (tempView instanceof DOMAST) {
ICElement input = ((CEditor)editor).getInputCElement();
if(!(input instanceof ITranslationUnit)) {
MessageDialog.openInformation(shell, DOMAST.VIEW_NAME, NOT_VALID_COMPILATION_UNIT);
return null;
}
((DOMAST)tempView).setTranslationUnit((ITranslationUnit)input);
((DOMAST)tempView).setPart(editor);
((DOMAST)tempView).setContentProvider(((DOMAST)tempView).new ViewContentProvider((ITranslationUnit)input));
}
}
site.getPage().activate(tempView);
}
return tempView;
}
}