/******************************************************************************* * 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; } }