package ch.hsr.ifs.pasta; import java.net.URL; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.part.ViewPart; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.service.event.Event; import org.osgi.service.event.EventAdmin; import org.osgi.service.event.EventConstants; import org.osgi.service.event.EventHandler; import ch.hsr.ifs.pasta.events.PastaEventConstants; public class ASTView extends ViewPart { @Override public void createPartControl(final Composite parent) { final ASTWidget treeView = new ASTWidget(parent); getViewSite().getActionBars().getToolBarManager().add(new Action() { @Override public void run() { treeView.drawAST(getAST()); } @Override public ImageDescriptor getImageDescriptor() { final Bundle bundle = FrameworkUtil.getBundle(this.getClass()); final URL url = FileLocator.find(bundle, new Path("icons/refresh.gif"), null); return ImageDescriptor.createFromURL(url); } @Override public String getText() { return "refresh"; } }); treeView.drawAST(getAST()); treeView.setListener(new NodeSelectionListener() { @Override public void nodeSelected(final IASTNode node) { final Map<String, Object> map = new HashMap<>(); map.put(PastaEventConstants.ASTNODE, node); doPostEvent(PastaEventConstants.ASTNODE, map); } }); registerEventHandler(PastaEventConstants.SHOW_SELECTION, new EventHandler() { @Override public void handleEvent(final Event event) { final ISelection selection = (ISelection) event.getProperty(PastaEventConstants.SELECTION); if (selection instanceof ITextSelection) { treeView.drawAST(getAST()); final IASTNodeSelector selector = getAST().getNodeSelector(getAST().getFilePath()); treeView.showSelectedNode(selector.findEnclosingNode(((ITextSelection) selection).getOffset(), ((ITextSelection) selection).getLength())); } } }); } private void registerEventHandler(final String topic, final EventHandler handler) { final BundleContext ctx = FrameworkUtil.getBundle(ASTView.class).getBundleContext(); final Dictionary<String, String> props = new Hashtable<>(); props.put(EventConstants.EVENT_TOPIC, topic); ctx.registerService(EventHandler.class.getName(), handler, props); } private IASTTranslationUnit getAST() { final IEditorInput editorInput = CUIPlugin.getActivePage().getActiveEditor().getEditorInput(); final IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editorInput); IIndex index; try { index = CCorePlugin.getIndexManager().getIndex(workingCopy.getCProject()); } catch (final CoreException e) { throw new RuntimeException(e); } try { index.acquireReadLock(); return workingCopy.getAST(index, ITranslationUnit.AST_SKIP_ALL_HEADERS) .copy(IASTNode.CopyStyle.withoutLocations); } catch (final CoreException | InterruptedException e) { throw new RuntimeException(e); } finally { index.releaseReadLock(); } } private void doPostEvent(final String topic, final Map<String, Object> map) { final Event event = new Event(topic, map); final BundleContext ctx = FrameworkUtil.getBundle(ASTView.class).getBundleContext(); final ServiceReference<?> ref = ctx.getServiceReference(EventAdmin.class.getName()); if (ref != null) { final EventAdmin admin = (EventAdmin) ctx.getService(ref); admin.sendEvent(event); ctx.ungetService(ref); } } @Override public void setFocus() { } }