1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 22:22:11 +02:00

- added extension point to provide problem details in Problem Details view and example of doing so for Flexlint

This commit is contained in:
Alena Laskavaia 2010-04-28 21:39:09 +00:00
parent 97285f3b56
commit db7ec65b72
15 changed files with 472 additions and 57 deletions

View file

@ -10,9 +10,10 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.jface.text;bundle-version="3.5.0",
org.eclipse.ui.editors;bundle-version="3.5.0",
org.eclipse.core.resources;bundle-version="3.5.0",
org.eclipse.cdt.codan.checkers;bundle-version="1.0.0",
org.eclipse.cdt.codan.checkers,
org.eclipse.cdt.ui,
org.eclipse.cdt.core
org.eclipse.cdt.core,
org.eclipse.cdt.codan.ui
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: Eclipse CDT

View file

@ -2,6 +2,7 @@
<?eclipse version="3.4"?>
<plugin>
<extension-point id="codanMarkerResolution" name="Codan Marker Resolution" schema="schema/codanMarkerResolution.exsd"/>
<extension
point="org.eclipse.ui.ide.markerResolution">
<markerResolutionGenerator
@ -20,4 +21,5 @@
problemId="org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem">
</resolution>
</extension>
</plugin>

View file

@ -7,6 +7,7 @@
</appinfo>
<documentation>
Extension point to plugin quick fix for codan markers
</documentation>
</annotation>
@ -98,7 +99,7 @@
<meta.section type="examples"/>
</appinfo>
<documentation>
&lt;extension
&lt;extension
point=&quot;org.eclipse.cdt.codan.checkers.ui.codanMarkerResolution&quot;&gt;
&lt;resolution
class=&quot;org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CatchByReferenceQuickFix&quot;
@ -113,7 +114,8 @@
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
Programmatically resolution can be added using CatchByReferenceQuickFix.addResolution method.
It is not API yet.
</documentation>
</annotation>
@ -122,7 +124,7 @@
<meta.section type="implementation"/>
</appinfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
see CatchByReferenceQuickFix
</documentation>
</annotation>

View file

@ -9,6 +9,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.cdt.codan.core.cxx;bundle-version="1.0.0",
org.eclipse.cdt.codan.core;bundle-version="1.0.0",
org.eclipse.cdt.core,
org.eclipse.core.resources
org.eclipse.core.resources,
org.eclipse.cdt.codan.ui;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy

View file

@ -19,4 +19,11 @@
</problem>
</checker>
</extension>
<extension
point="org.eclipse.cdt.codan.ui.codanProblemDetails">
<problemDetails
class="org.eclipse.cdt.codan.examples.uicontrib.FlexlintHelpLink"
>
</problemDetails>
</extension>
</plugin>

View file

@ -0,0 +1,39 @@
package org.eclipse.cdt.codan.examples.uicontrib;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.codan.ui.AbstractCodanProblemDetailsProvider;
public class FlexlintHelpLink extends AbstractCodanProblemDetailsProvider {
@Override
public boolean isApplicable(String id) {
String helpId = parseHelpId(getProblemMessage());
return helpId != null;
}
private Pattern messagePattern = Pattern.compile("(Warning|Error|Note|Info) #([0-9]+)"); //$NON-NLS-1$
private String parseHelpId(String problemMessage) {
// Warning #613:
// Note #613:
// Error #613:
String helpId = null;
Matcher matcher = messagePattern.matcher(problemMessage);
if (matcher.find()) {
helpId = matcher.group(2);
}
return helpId;
}
@Override
public URL getHelpURL() {
String helpId = parseHelpId(getProblemMessage());
try {
return new URL("http://www.gimpel-online.com/MsgRef.html#" + helpId); //$NON-NLS-1$
} catch (MalformedURLException e) {
return null;
}
}
}

View file

@ -16,5 +16,8 @@ Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.codan.internal.ui;x-friends:="org.eclipse.cdt.codan.ui.cxx",
org.eclipse.cdt.codan.internal.ui.actions;x-friends:="org.eclipse.cdt.codan.ui.cxx",
org.eclipse.cdt.codan.internal.ui.dialogs;x-friends:="org.eclipse.cdt.codan.ui.cxx",
org.eclipse.cdt.codan.internal.ui.preferences;x-friends:="org.eclipse.cdt.codan.ui.cxx"
org.eclipse.cdt.codan.internal.ui.preferences;x-friends:="org.eclipse.cdt.codan.ui.cxx",
org.eclipse.cdt.codan.internal.ui.views;x-internal:=true,
org.eclipse.cdt.codan.ui,
org.eclipse.cdt.codan.ui.handlers

View file

@ -3,4 +3,6 @@ output.. = bin/
bin.includes = plugin.xml,\
META-INF/,\
.,\
OSGI-INF/l10n/bundle.properties
OSGI-INF/l10n/bundle.properties,\
schema/,\
icons/

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 983 B

View file

@ -73,13 +73,13 @@
point="org.eclipse.ui.views">
<view
category="org.eclipse.cdt.ui.views"
class="org.eclipse.cdt.codan.ui.views.ProblemDetails"
icon="icons/sample.gif"
id="org.eclipse.cdt.codan.ui.views.ProblemDetails"
class="org.eclipse.cdt.codan.internal.ui.views.ProblemDetails"
icon="icons/problemDetails.gif"
id="org.eclipse.cdt.codan.internal.ui.views.ProblemDetails"
name="Problem Details">
</view>
</extension>
<extension-point id="codanProblemDetails" name="Codan Problem Details" schema="schema/codanProblemDetails.exsd"/>
<!--
<extension
point="org.eclipse.ui.bindings">

View file

@ -0,0 +1,120 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.codan.checkers.ui" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.eclipse.cdt.codan.checkers.ui" id="codanProblemDetails" name="Codan Problem Details"/>
</appinfo>
<documentation>
This extension point provides a mechanism to add extra details for a problem, which would
be displayed in Problem Details view. It can include extra locations, associated problems,
help link or extenal link.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<sequence>
<element ref="problemDetails" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="problemDetails">
<annotation>
<documentation>
root element for extension.
</documentation>
</annotation>
<complexType>
<attribute name="problemId" type="string">
<annotation>
<documentation>
Problem id for which extra details available.
If ommitted provider would be called for all problem kinds.
</documentation>
<appinfo>
<meta.attribute kind="identifier" basedOn="org.eclipse.cdt.codan.core.checkers/checker/problem/@id"/>
</appinfo>
</annotation>
</attribute>
<attribute name="class" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.codan.ui.AbstractCodanProblemDetailsProvider:"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<meta.section type="since"/>
</appinfo>
<documentation>
1.0
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="examples"/>
</appinfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="implementation"/>
</appinfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View file

@ -1,5 +1,9 @@
package org.eclipse.cdt.codan.ui.views;
package org.eclipse.cdt.codan.internal.ui.views;
import java.net.URL;
import java.util.Collection;
import org.eclipse.cdt.codan.ui.AbstractCodanProblemDetailsProvider;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.Action;
@ -12,10 +16,13 @@ import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionListener;
@ -27,20 +34,16 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
public class ProblemDetails extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "org.eclipse.cdt.codan.ui.views.ProblemDetails";
public static final String ID = "org.eclipse.cdt.codan.internal.ui.views.ProblemDetails";
private Composite area;
private Action action1;
private Action action2;
private Action doubleClickAction;
private Label description;
private Label location;
private Link helpLabel;
/**
* The constructor.
@ -59,24 +62,28 @@ public class ProblemDetails extends ViewPart {
description = new Label(area, SWT.WRAP);
description.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
location = new Label(area, SWT.WRAP);
helpLabel = new Link(area, SWT.WRAP);
helpLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
helpLabel.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String link = e.text;
if (link != null && link.startsWith("http")) {
org.eclipse.swt.program.Program.launch(e.text);
}
}
});
// Create the help context id for the area's control
//PlatformUI.getWorkbench().getHelpSystem().setHelp(area, "org.eclipse.cdt.codan.ui.viewer");
makeActions();
hookContextMenu();
hookDoubleClickAction();
contributeToActionBars();
ISelectionService ser = (ISelectionService) getSite().getService(ISelectionService.class);
ser.addSelectionListener(new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (part.getSite().getId().equals(processViewId)) {
processSelection(selection);
}
}
});
ISelection selection = ser.getSelection(processViewId);
@ -84,7 +91,8 @@ public class ProblemDetails extends ViewPart {
}
protected void processSelection(ISelection selection) {
if (selection == null || selection.isEmpty()) return;
if (selection == null || selection.isEmpty())
return;
if (selection instanceof IStructuredSelection) {
Object firstElement = ((IStructuredSelection) selection).getFirstElement();
IMarker marker = null;
@ -98,10 +106,43 @@ public class ProblemDetails extends ViewPart {
description.setText(message);
String loc = marker.getResource().getFullPath().toOSString(); //$NON-NLS-1$
int line = marker.getAttribute(IMarker.LINE_NUMBER, 0);
location.setText(loc+":"+line); //$NON-NLS-1$
location.setText(loc + ":" + line); //$NON-NLS-1$
queryProviders(marker);
area.layout();
}
}
}
private void queryProviders(IMarker marker) {
cleanProversControl();
String id = marker.getAttribute(IMarker.PROBLEM, "id"); //$NON-NLS-1$
Collection<AbstractCodanProblemDetailsProvider> providers = ProblemDetailsExtensions.getProviders(id);
for (AbstractCodanProblemDetailsProvider provider : providers) {
synchronized (provider) {
provider.setMarker(marker);
if (provider.isApplicable(id)) {
applyProvider(provider);
break;
}
}
}
}
public void cleanProversControl() {
helpLabel.setText("");
}
private void applyProvider(AbstractCodanProblemDetailsProvider provider) {
String label = provider.getHelpLabel();
final URL url = provider.getHelpURL();
if (label != null) {
helpLabel.setText(label);
}
if (url != null) {
if (label == null) {
label = url.toString();
}
helpLabel.setText("<a href=\"" + url + "\">" + label + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
@ -125,21 +166,16 @@ public class ProblemDetails extends ViewPart {
}
private void fillLocalPullDown(IMenuManager manager) {
// manager.add(action1);
// manager.add(new Separator());
// manager.add(action2);
}
private void fillContextMenu(IMenuManager manager) {
manager.add(action1);
manager.add(action2);
private void fillContextMenu(IMenuManager manager) {
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalToolBar(IToolBarManager manager) {
// manager.add(action1);
// manager.add(action2);
}
private void makeActions() {
@ -150,28 +186,8 @@ public class ProblemDetails extends ViewPart {
};
action1.setText("Action 1");
action1.setToolTipText("Action 1 tooltip");
action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
ISharedImages.IMG_OBJS_INFO_TSK));
action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
action2 = new Action() {
public void run() {
showMessage("Action 2 executed");
}
};
action2.setText("Action 2");
action2.setToolTipText("Action 2 tooltip");
action2.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
ISharedImages.IMG_OBJS_INFO_TSK));
doubleClickAction = new Action() {
public void run() {
showMessage("Double-click detected");
}
};
}
private void hookDoubleClickAction() {
// todo
}
private void showMessage(String message) {

View file

@ -0,0 +1,139 @@
/*******************************************************************************
* $QNXLicenseC:
* Copyright 2008, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*******************************************************************************/
/*
* Created by: Elena Laskavaia
* Created on: 2010-04-28
* Last modified by: $Author$
*/
package org.eclipse.cdt.codan.internal.ui.views;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.cdt.codan.internal.ui.CodanUIActivator;
import org.eclipse.cdt.codan.ui.AbstractCodanProblemDetailsProvider;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
/**
* Class that can load extension for problemDetails
*/
public class ProblemDetailsExtensions {
private static final String ALL = "*";//$NON-NLS-1$
private static final String EXTENSION_POINT_NAME = "codanProblemDetails"; //$NON-NLS-1$
private static boolean extensionsLoaded;
private static HashMap<String, Collection<?>> map = new HashMap<String, Collection<?>>();
private static synchronized void readExtensions() {
if (extensionsLoaded) return;
IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(CodanUIActivator.PLUGIN_ID, EXTENSION_POINT_NAME);
if (ep == null)
return;
try {
IConfigurationElement[] elements = ep.getConfigurationElements();
// process categories
for (int i = 0; i < elements.length; i++) {
IConfigurationElement configurationElement = elements[i];
processDetails(configurationElement);
}
} finally {
extensionsLoaded = true;
}
}
/**
* @param configurationElement
*/
private static void processDetails(IConfigurationElement configurationElement) {
if (configurationElement.getName().equals("problemDetails")) { //$NON-NLS-1$
String id = configurationElement.getAttribute("problemId"); //$NON-NLS-1$
if (id == null) {
id = ALL;
}
addExtension(id, configurationElement);
}
}
public static AbstractCodanProblemDetailsProvider resolveClass(IConfigurationElement configurationElement) {
AbstractCodanProblemDetailsProvider res;
try {
res = (AbstractCodanProblemDetailsProvider) configurationElement.createExecutableExtension("class");//$NON-NLS-1$
} catch (CoreException e) {
CodanUIActivator.log(e);
return null;
}
return res;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static void addExtension(String id, IConfigurationElement configurationElement) {
Collection collection = getCollection(id);
collection.add(configurationElement);
}
@SuppressWarnings("rawtypes")
public static void removeExtension(String id, Object el) {
Collection collection = getCollection(id);
collection.remove(el);
}
@SuppressWarnings("rawtypes")
private static Collection getCollection(String id) {
Collection collection = map.get(id);
if (collection == null) {
collection = new ArrayList();
map.put(id, collection);
}
return collection;
}
public static Collection<AbstractCodanProblemDetailsProvider> getProviders(String id) {
readExtensions();
Collection<AbstractCodanProblemDetailsProvider> providers = new ArrayList<AbstractCodanProblemDetailsProvider>();
Collection<?> collection1 = getCollection(id);
Collection<?> collection2 = getCollection(ALL);
providers.addAll(resolveProviders(collection1));
providers.addAll(resolveProviders(collection2));
return providers;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Collection<AbstractCodanProblemDetailsProvider> resolveProviders(Collection collection) {
Collection res = new ArrayList(collection);
for (Iterator iterator = res.iterator(); iterator.hasNext();) {
Object object = iterator.next();
if (object instanceof IConfigurationElement) {
// resolve
collection.remove(object);
AbstractCodanProblemDetailsProvider provider = resolveClass((IConfigurationElement) object);
if (provider!=null)
collection.add(provider);
}
}
return collection;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void addExtension(String id, AbstractCodanProblemDetailsProvider provider) {
Collection collection = getCollection(id);
collection.add(provider);
}
}

View file

@ -0,0 +1,83 @@
/*******************************************************************************
* $QNXLicenseC:
* Copyright 2008, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*******************************************************************************/
/*
* Created by: Elena Laskavaia
* Created on: 2010-04-28
* Last modified by: $Author$
*/
package org.eclipse.cdt.codan.ui;
import java.net.URL;
import org.eclipse.core.resources.IMarker;
/**
* Abstract class that provides stubs for problems details
*/
public abstract class AbstractCodanProblemDetailsProvider {
protected IMarker marker;
public AbstractCodanProblemDetailsProvider() {
}
/**
* sets the marker, called from framework to initialize provider
*/
public void setMarker(IMarker marker) {
this.marker = marker;
}
public IMarker getMarker() {
return marker;
}
protected String getProblemMessage(){
String message = marker.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$
return message;
}
/**
* return true if provider can provide details for given marker (previously set by setMarker)
* @param id - id of the problem
* @return
*/
public abstract boolean isApplicable(String id);
/**
* URL to external help for the problem, would be displayed as label, and as action
* will go to given URL is not null. If label is null (getHelpLabel) URL would be used as label.
*/
public URL getHelpURL() {
return null;
}
/**
* Label text to use to navigate to a help. Would be shown as hyperlink. If helpURL is not
* null would open a browser with given URL.
*/
public String getHelpLabel() {
return null;
}
/**
* Return help context id. Only one getHelpURL or getHelpContextId can be used.
* In case if help context id is not null hyperlink would open context help page.
*/
public String getHelpContextId() {
return null;
}
}