diff options
Diffstat (limited to 'gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModelTracker.java')
-rw-r--r-- | gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModelTracker.java | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModelTracker.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModelTracker.java new file mode 100644 index 0000000000..0eed8fdad5 --- /dev/null +++ b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModelTracker.java @@ -0,0 +1,232 @@ +/******************************************************************************* + * Copyright (c) 2014 Red Hat, Inc. + * 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: + * Red Hat initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.internal.gcov.view.annotatedsource; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.ui.CDTUITools; +import org.eclipse.cdt.ui.ICEditor; +import org.eclipse.core.resources.IProject; +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.IncrementalProjectBuilder; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IPartListener2; +import org.eclipse.ui.IWindowListener; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartReference; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Keep track of windows/parts and listen for opened editors to add + * the annotation model. + */ +public class GcovAnnotationModelTracker { + + private static GcovAnnotationModelTracker single; + private final IWorkbench workbench; + private final Map<IProject, IPath> trackedProjects = new HashMap<>(); + + /** + * Add/Remove a part listener to every window open/closed. + */ + private IWindowListener windowListener = new IWindowListener() { + @Override + public void windowOpened(IWorkbenchWindow window) { + window.getPartService().addPartListener(partListener); + } + + @Override + public void windowClosed(IWorkbenchWindow window) { + window.getPartService().removePartListener(partListener); + } + + @Override + public void windowActivated(IWorkbenchWindow window) {} + + @Override + public void windowDeactivated(IWorkbenchWindow window) {} + }; + + /** + * Add the GcovAnnotationModel to any part that contains an + * instance of ICEditor. + */ + private IPartListener2 partListener = new IPartListener2() { + @Override + public void partOpened(IWorkbenchPartReference partref) { + annotateCEditor(partref); + } + + @Override + public void partActivated(IWorkbenchPartReference partRef) {} + + @Override + public void partBroughtToTop(IWorkbenchPartReference partRef) {} + + @Override + public void partClosed(IWorkbenchPartReference partRef) {} + + @Override + public void partDeactivated(IWorkbenchPartReference partRef) {} + + @Override + public void partHidden(IWorkbenchPartReference partRef) {} + + @Override + public void partVisible(IWorkbenchPartReference partRef) {} + + @Override + public void partInputChanged(IWorkbenchPartReference partRef) {} + }; + + private GcovAnnotationModelTracker (IWorkbench workbench) { + this.workbench = workbench; + + // Add part listener for current windows + for (IWorkbenchWindow w : workbench.getWorkbenchWindows()) { + w.getPartService().addPartListener(partListener); + } + + // Add window listener to workbench for future windows + workbench.addWindowListener(windowListener); + } + + public static GcovAnnotationModelTracker getInstance () { + if (single == null) { + single = new GcovAnnotationModelTracker(PlatformUI.getWorkbench()); + } + return single; + } + + public IPath getBinaryPath (IProject project) { + return trackedProjects.get(project); + } + + public boolean containsProject (IProject project) { + return trackedProjects.containsKey(project); + } + + public void addProject (IProject project, IPath binary) { + trackedProjects.put(project, binary); + } + + public void dispose() { + workbench.removeWindowListener(windowListener); + for (IWorkbenchWindow w : workbench.getWorkbenchWindows()) { + w.getPartService().removePartListener(partListener); + } + } + + public void annotateAllCEditors() { + for (IWorkbenchWindow w : workbench.getWorkbenchWindows()) { + for (IWorkbenchPage p : w.getPages()) { + for (IEditorReference e : p.getEditorReferences()) { + annotateCEditor(e); + } + } + } + } + + private void annotateCEditor(IWorkbenchPartReference partref) { + IWorkbenchPart part = partref.getPart(false); + if (part instanceof ICEditor) { + ICEditor editor = (ICEditor) part; + ICElement element = CDTUITools.getEditorInputCElement(editor.getEditorInput()); + IProject project = element.getCProject().getProject(); + + // Attach our annotation model to any compatible editor. (ICEditor) + GcovAnnotationModel.attach((ITextEditor) part); + // If a user triggers a build we will not render annotations. + ResourcesPlugin.getWorkspace().addResourceChangeListener( + new ProjectBuildListener(project, editor), + IResourceChangeEvent.POST_BUILD); + } + } + + + private class ProjectBuildListener implements IResourceChangeListener { + + // project to keep track of + private IProject project; + private ICEditor editor; + + public ProjectBuildListener(IProject targetProject, ICEditor editor) { + this.editor = editor; + this.project = targetProject; + } + + @Override + public void resourceChanged(IResourceChangeEvent event) { + if (project != null && isPostBuildEvent(event)) { + + // find the project from event delta and delete its markers + IResourceDelta delta = event.getDelta(); + IResourceDelta[] childrenDelta = delta.getAffectedChildren(IResourceDelta.CHANGED); + for (IResourceDelta childDelta : childrenDelta) { + if (isProjectDelta(childDelta, project)) { + + // do not track this project and de-register this listener + GcovAnnotationModel.clear(editor); + ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); + trackedProjects.remove(project); + } + } + } + } + + /** + * Check if {@link IResourceDelta} represents a change in the specified {@link IProject}.. + * + * @param delta IResourceDelta resource delta to check + * @param project IProject project to compare against + * @return boolean true if IResourceDelta is a project and equals the + */ + public boolean isProjectDelta(IResourceDelta delta, IProject project){ + if(delta != null){ + IResource resource = delta.getResource(); + return delta.getKind() == IResourceDelta.CHANGED + && resource != null + && resource.getType() == IResource.PROJECT + && resource.equals(project); + } + return false; + } + + /** + * Check if {@link IResourceChangeEvent} is a post-build event. + * + * @param event IResourceChangeEvent event to check + * @return boolean true if IResourceChangeEvent is a post-build event, false + * otherwise + */ + public boolean isPostBuildEvent(IResourceChangeEvent event) { + if(event != null){ + int buildKind = event.getBuildKind(); + return event.getType() == IResourceChangeEvent.POST_BUILD + && (buildKind == IncrementalProjectBuilder.FULL_BUILD + || buildKind == IncrementalProjectBuilder.INCREMENTAL_BUILD + || buildKind == IncrementalProjectBuilder.CLEAN_BUILD); + } + return false; + } + } +} |