blob: 48a5480142eec39aa83de3214104239837f4b0b5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.gsf.codecoverage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.SwingUtilities;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.editor.EditorRegistry;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.modules.csl.api.DataLoadersBridge;
import org.netbeans.modules.csl.spi.GsfUtilities;
import org.netbeans.modules.gsf.codecoverage.api.CoverageManager;
import org.netbeans.modules.gsf.codecoverage.api.CoverageProvider;
import org.netbeans.modules.gsf.codecoverage.api.FileCoverageDetails;
import org.netbeans.modules.gsf.codecoverage.api.FileCoverageSummary;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
import org.openide.util.NbPreferences;
/**
* Manage code coverage collection; delegate to providers, etc.
*
* @author Tor Norbye
*/
public class CoverageManagerImpl implements CoverageManager {
public static final String COVERAGE_INSTANCE_FILE = "coverage.instance"; // NOI18N
private static final String MIME_TYPE = "mimeType"; // NOI18N
private static final String COVERAGE_DOC_PROPERTY = "coverage"; // NOI18N
private static final String PREF_EDITOR_BAR = "editorBar"; // NOI18N
private final Set<String> enabledMimeTypes = new HashSet<>();
private final Map<Project, CoverageReportTopComponent> showingReports = new HashMap<>();
private Boolean showEditorBar;
static CoverageManagerImpl getInstance() {
return (CoverageManagerImpl) CoverageManager.INSTANCE;
}
@Override
public void setEnabled(final Project project, final boolean enabled) {
final CoverageProvider provider = getProvider(project);
if (provider == null) {
return;
}
final Set<String> mimeTypes = provider.getMimeTypes();
if (enabled) {
enabledMimeTypes.addAll(mimeTypes);
} else {
enabledMimeTypes.removeAll(mimeTypes);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (JTextComponent target : EditorRegistry.componentList()) {
Document document = target.getDocument();
FileObject fileForDocument = GsfUtilities.findFileObject(document);
// show/hide code coverage toolbar in all open file editors belonging only to this project
if (fileForDocument != null && project.equals(FileOwnerQuery.getOwner(fileForDocument))) {
CoverageSideBar sb = CoverageSideBar.getSideBar(target);
if (sb != null) {
sb.showCoveragePanel(enabled);
}
}
}
// code coverage is being disabled, so close the report window for this project
if (!enabled) {
CoverageReportTopComponent report = showingReports.get(project);
if (report != null) {
report.close();
}
}
}
});
}
provider.setEnabled(enabled);
}
@Override
public boolean isAggregating(Project project) {
CoverageProvider provider = getProvider(project);
if (provider != null) {
return provider.isAggregating();
}
return false;
}
public void setAggregating(Project project, boolean aggregating) {
CoverageProvider provider = getProvider(project);
if (provider == null) {
return;
}
provider.setAggregating(aggregating);
}
void focused(FileObject fo, JTextComponent target) {
Project project = FileOwnerQuery.getOwner(fo);
if (project != null) {
CoverageProvider provider = getProvider(project);
if (provider != null && provider.isEnabled()) {
try {
EditorCookie ec = DataLoadersBridge.getDefault().getCookie(fo, EditorCookie.class);
if (ec != null) {
Document doc = ec.getDocument();
if (doc == null) {
return;
}
doc.putProperty(COVERAGE_DOC_PROPERTY, null);
CoverageHighlightsContainer container = CoverageHighlightsLayerFactory.getContainer(target);
if (container != null) {
container.refresh();
}
}
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}
}
void showFile(Project project, FileCoverageSummary result) {
FileObject fo = result.getFile();
if (fo == null) {
String display = result.getDisplayName();
File file = new File(display);
if (file.exists()) {
fo = FileUtil.toFileObject(file);
} else {
fo = project.getProjectDirectory().getFileObject(display.replace('\\', '/'));
}
}
if (fo != null) {
GsfUtilities.open(fo, -1, null);
}
}
static CoverageProvider getProvider(Project project) {
if (project != null) {
return project.getLookup().lookup(CoverageProvider.class);
} else {
return null;
}
}
@Override
public boolean isEnabled(Project project) {
CoverageProvider provider = getProvider(project);
if (provider != null) {
return provider.isEnabled();
}
return false;
}
public boolean isEnabled(String mimeType) {
return enabledMimeTypes.contains(mimeType);
}
FileCoverageDetails getDetails(Project project, FileObject fileObject, JTextComponent component) {
if (project != null) {
CoverageProvider provider = getProvider(project);
if (provider != null && provider.isEnabled()) {
Document doc = component.getDocument();
FileCoverageDetails hitCounts = (FileCoverageDetails) doc.getProperty(COVERAGE_DOC_PROPERTY);
if (hitCounts == null) {
hitCounts = provider.getDetails(fileObject, doc);
doc.putProperty(COVERAGE_DOC_PROPERTY, hitCounts);
if (getShowEditorBar()) {
CoverageSideBar sb = CoverageSideBar.getSideBar(component);
if (sb != null) {
sb.showCoveragePanel(true);
sb.setCoverage(hitCounts);
}
}
return hitCounts;
}
return hitCounts;
}
}
return null;
}
@Override
public void resultsUpdated(Project project, CoverageProvider provider) {
Set<String> mimeTypes = provider.getMimeTypes();
for (JTextComponent target : EditorRegistry.componentList()) {
Document document = target.getDocument();
String mimeType = (String) document.getProperty(MIME_TYPE);
if (mimeType != null && mimeTypes.contains(mimeType)) {
FileObject fo = GsfUtilities.findFileObject(document);
if (fo != null && FileOwnerQuery.getOwner(fo) == project) {
FileCoverageDetails hitCounts = (FileCoverageDetails) document.getProperty(COVERAGE_DOC_PROPERTY);
if (hitCounts == null) {
document.putProperty(COVERAGE_DOC_PROPERTY, null); // ehh... what?
}
if (isEnabled(project)) {
focused(fo, target);
} else {
CoverageHighlightsContainer container = CoverageHighlightsLayerFactory.getContainer(target);
if (container != null) {
container.refresh();
}
}
}
}
}
final CoverageReportTopComponent report = showingReports.get(project);
if (report != null) {
final List<FileCoverageSummary> coverage = provider.getResults();
Mutex.EVENT.readAccess(new Runnable() {
public @Override
void run() {
report.updateData(coverage);
}
});
}
}
public void clear(Project project) {
CoverageProvider provider = getProvider(project);
if (provider != null) {
provider.clear();
resultsUpdated(project, provider);
}
}
void closedReport(Project project) {
showingReports.remove(project);
}
public void showReport(Project project) {
// TODO - keep references to one per project and when open just show
// the existing one?
CoverageProvider provider = getProvider(project);
if (provider != null) {
List<FileCoverageSummary> results = provider.getResults();
CoverageReportTopComponent report = showingReports.get(project);
if (report == null) {
report = new CoverageReportTopComponent(project, results);
showingReports.put(project, report);
report.open();
}
report.toFront();
report.requestVisible();
}
}
public boolean getShowEditorBar() {
if (showEditorBar == null) {
showEditorBar = NbPreferences.forModule(CoverageManager.class).getBoolean(PREF_EDITOR_BAR, true);
}
return showEditorBar == Boolean.TRUE;
}
public void setShowEditorBar(boolean on) {
this.showEditorBar = on;
NbPreferences.forModule(CoverageManager.class).putBoolean(PREF_EDITOR_BAR, on);
// Update existing editors
for (JTextComponent target : EditorRegistry.componentList()) {
Document document = target.getDocument();
CoverageSideBar sb = CoverageSideBar.getSideBar(target);
if (sb != null) {
sb.showCoveragePanel(on);
}
}
}
}