/*
* Contributions to FindBugs
* Copyright (C) 2008, Andrei Loskutov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.tobject.findbugs.view.properties;
import java.util.Iterator;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import de.tobject.findbugs.FindbugsPlugin;
import de.tobject.findbugs.reporter.MarkerUtil;
import de.tobject.findbugs.util.EditorUtil;
import de.tobject.findbugs.util.Util;
import edu.umd.cs.findbugs.BugAnnotation;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugPattern;
import edu.umd.cs.findbugs.DetectorFactoryCollection;
import edu.umd.cs.findbugs.SourceLineAnnotation;
import edu.umd.cs.findbugs.findbugsmarker.FindBugsMarker;
/**
* @author Andrei
*/
public class BugInstanceSection extends AbstractPropertySection {
private Composite rootComposite;
private List annotationList;
private BugInstance bug;
private IMarker marker;
private IFile file;
private String title;
private IJavaElement javaElt;
public BugInstanceSection() {
super();
}
@Override
public void createControls(Composite parent, final TabbedPropertySheetPage tabbedPropertySheetPage) {
super.createControls(parent, tabbedPropertySheetPage);
Color background = tabbedPropertySheetPage.getWidgetFactory().getColors().getBackground();
rootComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, true);
layout.marginLeft = 5;
layout.marginTop = 5;
rootComposite.setLayout(layout);
rootComposite.setSize(SWT.DEFAULT, SWT.DEFAULT);
Group group = new Group(rootComposite, SWT.NONE);
group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
group.setLayout(new GridLayout(1, false));
group.setText("Bug annotations:");
rootComposite.setBackground(background);
group.setBackground(background);
annotationList = new List(group, SWT.NONE);
GridData data = new GridData(GridData.FILL_BOTH);
data.horizontalIndent = 0;
data.verticalIndent = 0;
annotationList.setLayoutData(data);
annotationList.setFont(JFaceResources.getDialogFont());
annotationList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evnt) {
selectInEditor(false);
}
});
annotationList.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
selectInEditor(true);
}
});
final Menu menu = new Menu(annotationList);
final MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_COPY));
item.setText("Copy To Clipboard");
item.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
copyInfoToClipboard();
}
});
menu.addListener(SWT.Show, new Listener() {
public void handleEvent(Event event) {
item.setEnabled(bug != null);
}
});
annotationList.setMenu(menu);
}
@Override
public void setInput(IWorkbenchPart part, ISelection selection) {
super.setInput(part, selection);
marker = MarkerUtil.getMarkerFromSingleSelection(selection);
if (marker == null) {
bug = null;
file = null;
title = null;
javaElt = null;
} else {
bug = MarkerUtil.findBugInstanceForMarker(marker);
file = (IFile) (marker.getResource() instanceof IFile ? marker.getResource() : null);
javaElt = MarkerUtil.findJavaElementForMarker(marker);
if (file == null && javaElt == null) {
FindbugsPlugin.getDefault().logError("Could not find file for " + bug.getMessage());
}
refreshTitle();
}
refreshAnnotations();
}
@Override
public void refresh() {
super.refresh();
}
@Override
public void dispose() {
if (rootComposite != null) {
rootComposite.dispose();
}
super.dispose();
}
@Override
public boolean shouldUseExtraSpace() {
return true;
}
private void selectInEditor(boolean openEditor) {
if (bug == null || (file == null && javaElt == null)) {
return;
}
IWorkbenchPage page = getPart().getSite().getPage();
IEditorPart activeEditor = page.getActiveEditor();
IEditorInput input = activeEditor != null ? activeEditor.getEditorInput() : null;
if (openEditor && !matchInput(input)) {
try {
if (file != null) {
activeEditor = IDE.openEditor(page, file);
} else if (javaElt != null) {
activeEditor = JavaUI.openInEditor(javaElt, true, true);
}
if (activeEditor != null) {
input = activeEditor.getEditorInput();
}
} catch (PartInitException e) {
FindbugsPlugin.getDefault().logException(e, "Could not open editor for " + bug.getMessage());
} catch (CoreException e) {
FindbugsPlugin.getDefault().logException(e, "Could not open editor for " + bug.getMessage());
}
}
if (matchInput(input)) {
int startLine = getLineToSelect();
EditorUtil.goToLine(activeEditor, startLine);
}
}
private boolean matchInput(IEditorInput input) {
if (file != null && (input instanceof IFileEditorInput)) {
return file.equals(((IFileEditorInput) input).getFile());
}
if (javaElt != null && input != null) {
IJavaElement javaElement = JavaUI.getEditorInputJavaElement(input);
if (javaElt.equals(javaElement)) {
return true;
}
IJavaElement parent = javaElt.getParent();
while (parent != null && !parent.equals(javaElement)) {
parent = parent.getParent();
}
if (parent != null && parent.equals(javaElement)) {
return true;
}
}
return false;
}
private void refreshTitle() {
String bugType = marker.getAttribute(FindBugsMarker.BUG_TYPE, "");
BugPattern pattern = DetectorFactoryCollection.instance().lookupBugPattern(bugType);
if (pattern == null || bug == null) {
title = "";
return;
}
String shortDescription = bug.getAbridgedMessage();
String abbrev = "[" + bug.getPriorityAbbreviation() + " " + bug.getCategoryAbbrev() + " " + pattern.getAbbrev() + "] ";
if (shortDescription == null) {
title = abbrev;
} else {
title = abbrev + shortDescription.trim() + " [" + pattern.getType() + "]";
}
}
private void refreshAnnotations() {
annotationList.removeAll();
// bug may be null, but if so then the error has already been logged.
if (bug != null) {
Iterator<BugAnnotation> it = bug.annotationIterator();
while (it.hasNext()) {
BugAnnotation ba = it.next();
annotationList.add(ba.toString());
}
}
}
private int getLineToSelect() {
int index = annotationList.getSelectionIndex();
Iterator<BugAnnotation> theIterator = bug.annotationIterator();
BugAnnotation theAnnotation = theIterator.next();
for (int i = 0; i < index; i++) {
theAnnotation = theIterator.next();
}
if (!(theAnnotation instanceof SourceLineAnnotation)) {
// return the line from our initial marker
return marker.getAttribute(IMarker.LINE_NUMBER, EditorUtil.DEFAULT_LINE_IN_EDITOR);
}
SourceLineAnnotation sla = (SourceLineAnnotation) theAnnotation;
int startLine = sla.getStartLine();
return startLine <= 0 ? EditorUtil.DEFAULT_LINE_IN_EDITOR : startLine;
}
private void copyInfoToClipboard() {
StringBuffer sb = new StringBuffer();
sb.append(title);
sb.append("\n");
sb.append(bug.getPriorityTypeString()).append(" ");
sb.append("\n");
Iterator<BugAnnotation> iterator = bug.annotationIterator();
while (iterator.hasNext()) {
BugAnnotation bugAnnotation = iterator.next();
sb.append(bugAnnotation.toString()).append("\n");
}
if (file != null) {
sb.append(file.getLocation()).append("\n");
}
Util.copyToClipboard(sb.toString());
}
}