diff options
Diffstat (limited to 'gcov')
13 files changed, 665 insertions, 244 deletions
diff --git a/gcov/org.eclipse.linuxtools.gcov.core/META-INF/MANIFEST.MF b/gcov/org.eclipse.linuxtools.gcov.core/META-INF/MANIFEST.MF index 409f6a04f7..fba60d8f95 100644 --- a/gcov/org.eclipse.linuxtools.gcov.core/META-INF/MANIFEST.MF +++ b/gcov/org.eclipse.linuxtools.gcov.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %bundleName Bundle-SymbolicName: org.eclipse.linuxtools.gcov.core;singleton:=true -Bundle-Version: 5.0.0.qualifier +Bundle-Version: 5.1.0.qualifier Bundle-Activator: org.eclipse.linuxtools.internal.gcov.Activator Bundle-Vendor: %bundleProvider Require-Bundle: org.eclipse.ui, @@ -24,4 +24,5 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-Localization: plugin Export-Package: org.eclipse.linuxtools.internal.gcov.parser;x-friends:="org.eclipse.linuxtools.gcov.launch", - org.eclipse.linuxtools.internal.gcov.view;x-friends:="org.eclipse.linuxtools.gcov.launch" + org.eclipse.linuxtools.internal.gcov.view;x-friends:="org.eclipse.linuxtools.gcov.launch", + org.eclipse.linuxtools.internal.gcov.view.annotatedsource;x-friends:="org.eclipse.linuxtools.gcov.launch" diff --git a/gcov/org.eclipse.linuxtools.gcov.core/plugin.xml b/gcov/org.eclipse.linuxtools.gcov.core/plugin.xml index 28dbc0ed5d..9364d2bc2f 100644 --- a/gcov/org.eclipse.linuxtools.gcov.core/plugin.xml +++ b/gcov/org.eclipse.linuxtools.gcov.core/plugin.xml @@ -45,6 +45,67 @@ class="org.eclipse.linuxtools.internal.gcov.preferences.ColorPreferencesInitializer"> </initializer> </extension> + + <extension + point="org.eclipse.ui.editors.markerAnnotationSpecification"> + <specification + annotationType="org.eclipse.gcov.CoverageAnnotation" + colorPreferenceKey="coverage_color" + colorPreferenceValue="192,255,192" + contributesToHeader="false" + highlightPreferenceKey="coverage_highlight" + highlightPreferenceValue="true" + includeOnPreferencePage="true" + isGoToNextNavigationTarget="false" + isGoToNextNavigationTargetKey="coverage_isGoToNextNavigationTargetKey" + isGoToPreviousNavigationTarget="false" + isGoToPreviousNavigationTargetKey="coverage_isGoToPreviousNavigationTargetKey" + label="Coverage" + overviewRulerPreferenceKey="coverage_overviewRuler" + overviewRulerPreferenceValue="false" + presentationLayer="0" + showInNextPrevDropdownToolbarAction="false" + showInNextPrevDropdownToolbarActionKey="coverage_showInNextPrevDropdownToolbarAction" + textPreferenceKey="coverage_text" + textPreferenceValue="true" + textStylePreferenceKey="coverage_stylePreferences" + textStylePreferenceValue="BOX" + verticalRulerPreferenceKey="coverage_verticalRuler" + verticalRulerPreferenceValue="true"/> + <specification + annotationType="org.eclipse.gcov.NoCoverageAnnotation" + colorPreferenceKey="nocoverage_color" + colorPreferenceValue="255,160,160" + contributesToHeader="false" + highlightPreferenceKey="nocoverage_highlight" + highlightPreferenceValue="true" + includeOnPreferencePage="true" + isGoToNextNavigationTarget="false" + isGoToNextNavigationTargetKey="nocoverage_isGoToNextNavigationTargetKey" + isGoToPreviousNavigationTarget="false" + isGoToPreviousNavigationTargetKey="nocoverage_isGoToPreviousNavigationTargetKey" + label="No Coverage" + overviewRulerPreferenceKey="nocoverage_overviewRuler" + overviewRulerPreferenceValue="false" + presentationLayer="0" + showInNextPrevDropdownToolbarAction="false" + showInNextPrevDropdownToolbarActionKey="nocoverage_showInNextPrevDropdownToolbarAction" + textPreferenceKey="nocoverage_text" + textPreferenceValue="true" + textStylePreferenceKey="nocoverage_stylePreferences" + textStylePreferenceValue="BOX" + verticalRulerPreferenceKey="nocoverage_verticalRuler" + verticalRulerPreferenceValue="true"/> + </extension> + <extension + point="org.eclipse.ui.editors.annotationTypes"> + <type + name="org.eclipse.gcov.CoverageAnnotation"> + </type> + <type + name="org.eclipse.gcov.NoCoverageAnnotation"> + </type> + </extension> </plugin> diff --git a/gcov/org.eclipse.linuxtools.gcov.core/pom.xml b/gcov/org.eclipse.linuxtools.gcov.core/pom.xml index 45a7aeed3f..678b4e4c19 100644 --- a/gcov/org.eclipse.linuxtools.gcov.core/pom.xml +++ b/gcov/org.eclipse.linuxtools.gcov.core/pom.xml @@ -18,7 +18,7 @@ </parent> <artifactId>org.eclipse.linuxtools.gcov.core</artifactId> - <version>5.0.0-SNAPSHOT</version> + <version>5.1.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <name>Linux Tools GCov Plug-in</name> diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/action/OpenGCAction.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/action/OpenGCAction.java index dbb5db6795..d1d126598e 100644 --- a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/action/OpenGCAction.java +++ b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/action/OpenGCAction.java @@ -21,10 +21,12 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.linuxtools.internal.gcov.dialog.OpenGCDialog; import org.eclipse.linuxtools.internal.gcov.view.CovView; +import org.eclipse.linuxtools.internal.gcov.view.annotatedsource.GcovAnnotationModelTracker; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorLauncher; @@ -72,6 +74,11 @@ public class OpenGCAction implements IEditorLauncher { return; } String binaryPath = d.getBinaryFile(); + + IProject project = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(file).getProject(); + GcovAnnotationModelTracker.getInstance().addProject(project, new Path(binaryPath)); + GcovAnnotationModelTracker.getInstance().annotateAllCEditors(); + if (d.isCompleteCoverageResultWanted()) { CovView.displayCovResults(binaryPath, gcda.getAbsolutePath()); } else { diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/CoverageAnnotationColumn.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/CoverageAnnotationColumn.java deleted file mode 100644 index 8e159e69b1..0000000000 --- a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/CoverageAnnotationColumn.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009 STMicroelectronics. - * 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: - * Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation - *******************************************************************************/ -package org.eclipse.linuxtools.internal.gcov.view.annotatedsource; - -import java.util.ArrayList; - -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.ISTAnnotationColumn; -import org.eclipse.linuxtools.internal.gcov.parser.Line; -import org.eclipse.linuxtools.internal.gcov.parser.SourceFile; -import org.eclipse.osgi.util.NLS; - -public class CoverageAnnotationColumn implements ISTAnnotationColumn { - - private final ArrayList<Line> lines; - - public CoverageAnnotationColumn(SourceFile sourceFile) { - lines = sourceFile.getLines(); - } - - @Override - public String getAnnotation(int index) { - try { - Line l = lines.get(index + 1); - if (l.exists()) { - return Long.toString(l.getCount()); - } - } catch (IndexOutOfBoundsException _) { - // ignore as empty string will be returned anyway - } - return ""; //$NON-NLS-1$ - } - - @Override - public String getTooltip(int index) { - try { - Line l = lines.get(index + 1); - if (!l.exists()) { - return Messages.CoverageAnnotationColumn_non_exec_line; - } else { - long count = l.getCount(); - if (count == 0) { - return Messages.CoverageAnnotationColumn_line_never_exec; - } else if (count == 1) { - return Messages.CoverageAnnotationColumn_line_exec_once; - } - return NLS.bind(Messages.CoverageAnnotationColumn_line_mulitiple_exec, Long.toString(count)); - } - } catch (IndexOutOfBoundsException _) { - return Messages.CoverageAnnotationColumn_non_exec_line; - } - } - -} diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotation.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotation.java new file mode 100644 index 0000000000..4b3274fcb3 --- /dev/null +++ b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotation.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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 org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.osgi.util.NLS; + +/** + * Representation of a GCov source file annotation. + */ +public class GcovAnnotation extends Annotation { + + private static final String COVERAGE = "org.eclipse.gcov.CoverageAnnotation"; //$NON-NLS-1$ + private static final String NO_COVERAGE = "org.eclipse.gcov.NoCoverageAnnotation"; //$NON-NLS-1$ + + private final Position position; + private final long count; + + public GcovAnnotation(int offset, int length, long count) { + super(getAnnotationType(count), false, null); + this.position = new Position(offset, length); + this.count = count; + } + + public Position getPosition() { + return position; + } + + @Override + public String getText() { + if (count == 0) { + return Messages.CoverageAnnotationColumn_line_never_exec; + } else if (count == 1) { + return Messages.CoverageAnnotationColumn_line_exec_once; + } else if ( count > 0) { + return NLS.bind(Messages.CoverageAnnotationColumn_line_mulitiple_exec, Long.toString(count)); + } else { + return Messages.CoverageAnnotationColumn_non_exec_line; + } + } + + private static String getAnnotationType(long count) { + if (count == 0) { + return NO_COVERAGE; + } + return COVERAGE; + } +} diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModel.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModel.java new file mode 100644 index 0000000000..5bedee6209 --- /dev/null +++ b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationModel.java @@ -0,0 +1,298 @@ +/******************************************************************************* + * 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.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.ui.CDTUITools; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationModelEvent; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IAnnotationModelExtension; +import org.eclipse.jface.text.source.IAnnotationModelListener; +import org.eclipse.jface.text.source.IAnnotationModelListenerExtension; +import org.eclipse.linuxtools.binutils.link2source.STLink2SourceSupport; +import org.eclipse.linuxtools.internal.gcov.parser.CovManager; +import org.eclipse.linuxtools.internal.gcov.parser.Line; +import org.eclipse.linuxtools.internal.gcov.parser.SourceFile; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * Annotation model responsible for management of GcovAnnotation elements. + */ +public final class GcovAnnotationModel implements IAnnotationModel { + + /** Key for identifying our model from other Editor models. */ + private static final Object KEY = new Object(); + + /** List of GcovAnnotation elements */ + private List<GcovAnnotation> annotations = new ArrayList<>(); + + /** List of IAnnotationModelListener */ + private List<IAnnotationModelListener> annotationModelListeners = new ArrayList<>(); + + private final ITextEditor editor; + private final IDocument document; + private int openConnections = 0; + private boolean annotated = false; + + private IDocumentListener documentListener = new IDocumentListener() { + @Override + public void documentChanged(DocumentEvent event) { + updateAnnotations(false); + } + + @Override + public void documentAboutToBeChanged(DocumentEvent event) {} + }; + + private GcovAnnotationModel(ITextEditor editor, IDocument document) { + this.editor = editor; + this.document = document; + updateAnnotations(true); + } + + /** + * Attaches a coverage annotation model for the given editor if the editor + * can be annotated. Does nothing if the model is already attached. + * + * @param editor Editor to which an annotation model should be attached + */ + public static void attach(ITextEditor editor) { + IDocumentProvider provider = editor.getDocumentProvider(); + if (provider == null) { + return; + } + IAnnotationModel model = provider.getAnnotationModel(editor.getEditorInput()); + if (!(model instanceof IAnnotationModelExtension)) { + return; + } + IAnnotationModelExtension modelex = (IAnnotationModelExtension) model; + IDocument document = provider.getDocument(editor.getEditorInput()); + + GcovAnnotationModel coveragemodel = (GcovAnnotationModel) modelex.getAnnotationModel(KEY); + if (coveragemodel == null) { + coveragemodel = new GcovAnnotationModel(editor, document); + modelex.addAnnotationModel(KEY, coveragemodel); + } else { + coveragemodel.updateAnnotations(false); + } + } + + public static void clear (ITextEditor editor) { + IDocumentProvider provider = editor.getDocumentProvider(); + if (provider == null) { + return; + } + IAnnotationModel model = provider.getAnnotationModel(editor.getEditorInput()); + if (!(model instanceof IAnnotationModelExtension)) { + return; + } + IAnnotationModelExtension modelex = (IAnnotationModelExtension) model; + IAnnotationModel coverageModel = modelex.getAnnotationModel(KEY); + if (coverageModel instanceof GcovAnnotationModel) { + ((GcovAnnotationModel) coverageModel).clear(); + } + } + + private void updateAnnotations(boolean force) { + // We do not annotate any editor displaying content of a project not tracked. + ICElement element = CDTUITools.getEditorInputCElement(editor.getEditorInput()); + if (!GcovAnnotationModelTracker.getInstance().containsProject(element.getCProject().getProject())) { + return; + } + + SourceFile coverage = findSourceCoverageForEditor(); + if (coverage != null) { + if (!annotated || force) { + createAnnotations(coverage); + } + } else { + if (annotated) { + clear(); + } + } + } + + private SourceFile findSourceCoverageForEditor() { + if (editor.isDirty()) { + return null; + } + final IEditorInput input = editor.getEditorInput(); + if (input == null) { + return null; + } + ICElement element = CDTUITools.getEditorInputCElement(input); + if (element == null) { + return null; + } + return findSourceCoverageForElement(element); + } + + private SourceFile findSourceCoverageForElement(ICElement element) { + List<SourceFile> sources = new ArrayList<> (); + ICProject cProject = element.getCProject(); + IPath target = GcovAnnotationModelTracker.getInstance().getBinaryPath(cProject.getProject()); + try { + IBinary[] binaries = cProject.getBinaryContainer().getBinaries(); + for (IBinary b : binaries) { + if (b.getResource().getLocation().equals(target)) { + CovManager covManager = new CovManager(b.getResource().getLocation().toOSString()); + covManager.processCovFiles(covManager.getGCDALocations(), null); + sources.addAll(covManager.getAllSrcs()); + } + } + } catch (Exception e) { + } + + for (SourceFile sf : sources) { + IPath sfPath = new Path(sf.getName()); + IFile file = STLink2SourceSupport.sharedInstance.getFileForPath(sfPath, cProject.getProject()); + if (file != null) { + if (element.getLocationURI().getPath().equals(file.getLocation().toOSString())) { + return sf; + } + } + } + + IPath binFolder = target.removeLastSegments(1); + for (SourceFile sf : sources) { + String sfPath = Paths.get(binFolder.toOSString(), sf.getName()).normalize().toString(); + if (sfPath.equals(element.getLocationURI().getPath())) { + return sf; + } + } + + return null; + } + + private void createAnnotations(SourceFile sourceFile) { + AnnotationModelEvent event = new AnnotationModelEvent(this); + clear(event); + List<Line> lines = sourceFile.getLines(); + for (int i = 0; i < lines.size(); i++) { + try { + Line line = lines.get((i+1) % lines.size()); + if (line.exists()) { + GcovAnnotation ca = new GcovAnnotation(document.getLineOffset(i), + document.getLineLength(i), line.getCount()); + annotations.add(ca); + event.annotationAdded(ca); + } + } catch (BadLocationException e) { + } + } + fireModelChanged(event); + annotated = true; + } + + private void clear() { + AnnotationModelEvent event = new AnnotationModelEvent(this); + clear(event); + fireModelChanged(event); + annotated = false; + } + + private void clear(AnnotationModelEvent event) { + for (final GcovAnnotation ca : annotations) { + event.annotationRemoved(ca, ca.getPosition()); + } + annotations.clear(); + } + + @Override + public void addAnnotationModelListener(IAnnotationModelListener listener) { + if (!annotationModelListeners.contains(listener)) { + annotationModelListeners.add(listener); + fireModelChanged(new AnnotationModelEvent(this, true)); + } + } + + @Override + public void removeAnnotationModelListener(IAnnotationModelListener listener) { + annotationModelListeners.remove(listener); + } + + private void fireModelChanged(AnnotationModelEvent event) { + event.markSealed(); + if (!event.isEmpty()) { + for (final IAnnotationModelListener l : annotationModelListeners) { + if (l instanceof IAnnotationModelListenerExtension) { + ((IAnnotationModelListenerExtension) l).modelChanged(event); + } else { + l.modelChanged(this); + } + } + } + } + + @Override + public void connect(IDocument document) { + if (this.document != document) { + throw new IllegalArgumentException("Can't connect to different document."); //$NON-NLS-1$ + } + for (final GcovAnnotation ca : annotations) { + try { + document.addPosition(ca.getPosition()); + } catch (BadLocationException ex) { + } + } + if (openConnections++ == 0) { + document.addDocumentListener(documentListener); + } + } + + @Override + public void disconnect(IDocument document) { + if (this.document != document) { + throw new IllegalArgumentException("Can't disconnect from different document."); //$NON-NLS-1$ + } + for (final GcovAnnotation ca : annotations) { + document.removePosition(ca.getPosition()); + } + if (--openConnections == 0) { + document.removeDocumentListener(documentListener); + } + } + + @Override + public Position getPosition(Annotation annotation) { + return (annotation instanceof GcovAnnotation) ? ((GcovAnnotation) annotation).getPosition() : null; + } + + @Override + public Iterator<?> getAnnotationIterator() { + return annotations.iterator(); + } + + @Override + public void addAnnotation(Annotation annotation, Position position) {} + + @Override + public void removeAnnotation(Annotation annotation) {} + +} 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; + } + } +} diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationProvider.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationProvider.java deleted file mode 100644 index e497f99f97..0000000000 --- a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovAnnotationProvider.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013 Kalray.eu - * 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: - * Xavier Raynaud <xavier.raynaud@kalray.eu> - initial API and implementation - *******************************************************************************/ -package org.eclipse.linuxtools.internal.gcov.view.annotatedsource; - -import java.util.ArrayList; - -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.resource.StringConverter; -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.IAnnotationProvider; -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.ISTAnnotationColumn; -import org.eclipse.linuxtools.internal.gcov.Activator; -import org.eclipse.linuxtools.internal.gcov.parser.Line; -import org.eclipse.linuxtools.internal.gcov.parser.SourceFile; -import org.eclipse.linuxtools.internal.gcov.preferences.ColorPreferencePage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; - -/** - * - * @author Xavier Raynaud <xavier.raynaud@kalray.eu> - */ -public class GcovAnnotationProvider implements IAnnotationProvider { - - private final ISTAnnotationColumn column; - - private final SourceFile sourceFile; - private final int lineCount; - - private boolean initialized = false; - private boolean COLORIZE_CODE; - private boolean USE_GRADIENT; - private Color GREEN_MAX; - private Color GREEN_MIN; - private Color RED; - private final Color[] GREENCOLORS = new Color[129]; - - public GcovAnnotationProvider(SourceFile sourceFile) { - this.sourceFile = sourceFile; - this.lineCount = sourceFile.getLines().size(); - this.column = new CoverageAnnotationColumn(sourceFile); - } - - private void initColors() { - for (int i = 0; i < GREENCOLORS.length; i++) { - GREENCOLORS[i] = null; - } - - Display d = PlatformUI.getWorkbench().getDisplay(); - /* Recover the preferences database. */ - IPreferenceStore prefs_store = Activator.getDefault().getPreferenceStore(); - - COLORIZE_CODE = prefs_store.getBoolean(ColorPreferencePage.PREFKEY_COV_USE_COLORS); - USE_GRADIENT = prefs_store.getBoolean(ColorPreferencePage.PREFKEY_COV_USE_GRADIENT); - - /* Recover and build the colors from the preferences database. */ - GREEN_MAX = new Color(d, - StringConverter.asRGB(prefs_store.getString(ColorPreferencePage.PREFKEY_COV_MAX_COLOR))); - GREEN_MIN = new Color(d, - StringConverter.asRGB(prefs_store.getString(ColorPreferencePage.PREFKEY_COV_MIN_COLOR))); - RED = new Color(d, StringConverter.asRGB(prefs_store.getString(ColorPreferencePage.PREFKEY_COV_0_COLOR))); - - /* Colors are now allocated. */ - initialized = true; - } - - @Override - public Color getColor(int ln) { - if (!initialized) { - initColors(); - } - Display display = PlatformUI.getWorkbench().getDisplay(); - if (COLORIZE_CODE) { - final int index = ln + 1; - if (index < lineCount) { - ArrayList<Line> lines = sourceFile.getLines(); - Line line = lines.get(index); - if (line.exists()) { - long count = line.getCount(); - if (count == 0) { - return RED; - } - if (!USE_GRADIENT || count == sourceFile.getmaxLineCount()) { - return GREEN_MAX; - } - int colorIndex = 128 - (int) ((128 * count) / sourceFile.getmaxLineCount()); - if (GREENCOLORS[colorIndex] == null) { - int r = GREEN_MIN.getRed() + (GREEN_MAX.getRed() - GREEN_MIN.getRed()) / colorIndex; - int v = GREEN_MIN.getGreen() + (GREEN_MAX.getGreen() - GREEN_MIN.getGreen()) / colorIndex; - int b = GREEN_MIN.getBlue() + (GREEN_MAX.getBlue() - GREEN_MIN.getBlue()) / colorIndex; - GREENCOLORS[colorIndex] = new Color(display, r, v, b); - } - return GREENCOLORS[colorIndex]; - } - } - } - return display.getSystemColor(SWT.COLOR_WHITE); - } - - @Override - public ISTAnnotationColumn getColumn() { - return column; - } - - @Override - public void dispose() { - if (GREEN_MAX != null) { - GREEN_MAX.dispose(); - } - if (GREEN_MIN != null) { - GREEN_MIN.dispose(); - } - if (RED != null) { - RED.dispose(); - } - for (Color c : GREENCOLORS) { - if (c != null) { - c.dispose(); - } - } - } - -} diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovSourceEditorInput.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovSourceEditorInput.java deleted file mode 100644 index c650877297..0000000000 --- a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/GcovSourceEditorInput.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009 STMicroelectronics. - * 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: - * Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation - *******************************************************************************/ -package org.eclipse.linuxtools.internal.gcov.view.annotatedsource; - -import org.eclipse.core.filesystem.IFileStore; -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.IAnnotationProvider; -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.IEditorInputWithAnnotations; -import org.eclipse.linuxtools.internal.gcov.parser.SourceFile; -import org.eclipse.ui.ide.FileStoreEditorInput; - -public class GcovSourceEditorInput extends FileStoreEditorInput implements IEditorInputWithAnnotations { - - private final SourceFile sourceFile; - - public GcovSourceEditorInput(IFileStore fileStore, SourceFile sourceFile) { - super(fileStore); - this.sourceFile = sourceFile; - } - - @Override - public IAnnotationProvider createAnnotationProvider() { - return new GcovAnnotationProvider(sourceFile); - } - -} diff --git a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/OpenSourceFileAction.java b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/OpenSourceFileAction.java index 7ed9590e1f..8597604563 100644 --- a/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/OpenSourceFileAction.java +++ b/gcov/org.eclipse.linuxtools.gcov.core/src/org/eclipse/linuxtools/internal/gcov/view/annotatedsource/OpenSourceFileAction.java @@ -25,7 +25,6 @@ import org.eclipse.core.runtime.Status; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.linuxtools.binutils.link2source.STLink2SourceSupport; -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.STAnnotatedSourceEditorActivator; import org.eclipse.linuxtools.internal.gcov.Activator; import org.eclipse.linuxtools.internal.gcov.parser.SourceFile; import org.eclipse.ui.IEditorInput; @@ -33,6 +32,7 @@ import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IURIEditorInput; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; +import org.eclipse.ui.ide.IDE; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; @@ -62,16 +62,6 @@ public class OpenSourceFileAction { return null; } - private GcovSourceEditorInput getInput(SourceFile sourceFile, IFileStore fs) { - GcovSourceEditorInput input = new GcovSourceEditorInput(fs, sourceFile); - IWorkbenchPage p = CUIPlugin.getActivePage(); - IEditorPart editorPart = p.findEditor(input); - if (editorPart != null) { - p.closeEditor(editorPart, false); - } - return input; - } - public void openAnnotatedSourceFile(IProject project, IFile binary, SourceFile sourceFile, int lineNumber) { if (sourceFile == null) { return; @@ -103,9 +93,8 @@ public class OpenSourceFileAction { Activator.getDefault().getLog().log(s); } } else { - IEditorInput input = getInput(sourceFile, fs); try { - IEditorPart editor = page.openEditor(input, STAnnotatedSourceEditorActivator.EDITOR_ID, true); + IEditorPart editor = IDE.openEditorOnFileStore(page, fs); if (lineNumber > 0 && editor instanceof ITextEditor) { IDocumentProvider provider = ((ITextEditor) editor).getDocumentProvider(); IDocument document = provider.getDocument(editor.getEditorInput()); diff --git a/gcov/org.eclipse.linuxtools.gcov.launch/src/org/eclipse/linuxtools/internal/gcov/launch/GcovLaunchConfigurationDelegate.java b/gcov/org.eclipse.linuxtools.gcov.launch/src/org/eclipse/linuxtools/internal/gcov/launch/GcovLaunchConfigurationDelegate.java index 14c4e8771a..010236b5fc 100644 --- a/gcov/org.eclipse.linuxtools.gcov.launch/src/org/eclipse/linuxtools/internal/gcov/launch/GcovLaunchConfigurationDelegate.java +++ b/gcov/org.eclipse.linuxtools.gcov.launch/src/org/eclipse/linuxtools/internal/gcov/launch/GcovLaunchConfigurationDelegate.java @@ -32,6 +32,7 @@ import org.eclipse.debug.core.ILaunchesListener2; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.linuxtools.internal.gcov.parser.CovManager; import org.eclipse.linuxtools.internal.gcov.view.CovView; +import org.eclipse.linuxtools.internal.gcov.view.annotatedsource.GcovAnnotationModelTracker; import org.eclipse.linuxtools.profiling.launch.IRemoteCommandLauncher; import org.eclipse.linuxtools.profiling.launch.ProfileLaunchConfigurationDelegate; import org.eclipse.linuxtools.profiling.launch.RemoteProxyManager; @@ -107,6 +108,8 @@ public class GcovLaunchConfigurationDelegate extends ProfileLaunchConfigurationD MessageDialog.openWarning(parent, title, message); } CovView.displayCovResults(s, null); + GcovAnnotationModelTracker.getInstance().addProject(getProject(), exePath); + GcovAnnotationModelTracker.getInstance().annotateAllCEditors(); } catch (InterruptedException e) { // Do nothing } diff --git a/gcov/org.eclipse.linuxtools.gcov.test/src/org/eclipse/linuxtools/internal/gcov/test/GcovTest.java b/gcov/org.eclipse.linuxtools.gcov.test/src/org/eclipse/linuxtools/internal/gcov/test/GcovTest.java index 8f20fbe1aa..41757266eb 100644 --- a/gcov/org.eclipse.linuxtools.gcov.test/src/org/eclipse/linuxtools/internal/gcov/test/GcovTest.java +++ b/gcov/org.eclipse.linuxtools.gcov.test/src/org/eclipse/linuxtools/internal/gcov/test/GcovTest.java @@ -19,7 +19,6 @@ import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.linuxtools.dataviewers.actions.STExportToCSVAction; -import org.eclipse.linuxtools.dataviewers.annotatedsourceeditor.STAnnotatedSourceEditorActivator; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; @@ -331,7 +330,7 @@ public abstract class GcovTest { bot.button("OK").click(); bot.waitUntil(Conditions.shellCloses(shell)); - SWTBotEditor editor = bot.editorById(STAnnotatedSourceEditorActivator.EDITOR_ID); + SWTBotEditor editor = bot.activeEditor(); SWTBotEclipseEditor edt = editor.toTextEditor(); /* just to verify that the correct file was found */ edt.close(); } |