Proposal 

 

RFC

Marker Help and Resolution - Draft 1

Summary
Support for marker help and marker resolution provides an opportunity to add significant useful functionality to the eclipse platform. Marker help support means that the user will be able to select a marker, press F1, and receive specific help for the selected marker. Resolution support will allow the user to select a resolution for a particular marker. Resolutions could invoke any arbitrary code but would typically involve correcting a problem indicated by the marker or performing a required task.

By Randy Giffen and Karice McIntyre, OTI
Last Modified: 7 Dec, 2001 - Added comments from Nick Edgar


The Details

Problem

Currently there is no way to associate a marker with a specific F1 help context id. In addition there are several kinds of markers for which there is a typical resolution that could be performed by the IDE when directed to do so by the user (for example, adding a missing import statement to a .java file). However, there is no way to associate the code that could perform such a resolution with a marker.

Background Info

The Eclipse platform includes support for displaying help in response to the user pressing F1. This functionality requires that a help context be associated with the widget which has focus (or a widget in its parent chain). The associated help context can be a static id which is passed to the help support system or an IContextComputer which dynamically computes the id based on the state of the widget. The latter mechanism can be used to access an API that provides a help context id for a selected marker.

Markers are defined using the org.eclipse.core.resources.markers extension point. The org.eclipse.core.resources plug-in defines a base marker type and several standard subtypes (problem, task, bookmark, and textmarker). There is currently no general way to identify a specific "kind" of marker (at the granularity needed to associate it with a help context or resolution). IMarker does define a getId method. However, this id is unique relative to the resource with which the marker is associated, it is not globally unique. More importantly, this id is instance-based. Thus two makers which are the same kind of marker will return different values for getId.

The org.eclipse.core.resources.markers extension point allows plug-ins to declare new marker subtypes but, in most cases, marker type is too coarse to use as a way of indicating specific kinds of markers. Marker attributes can be used for such a purpose. However, for most markers there is no defined attribute that would be appropriate for this purpose. For example, the following are the extension declarations in the org.eclipse.core.resources plug-in for problem and task markers:

<extension id="problemmarker" point="org.eclipse.core.resources.markers" name="%problemName">
   <super type="org.eclipse.core.resources.marker"/>
   <persistent value="true"/>
   <attribute name="severity"/>
   <attribute name="message"/>
   <attribute name="location"/>
</extension>
<extension id="taskmarker" point="org.eclipse.core.resources.markers" name="%taskName">
   <super type="org.eclipse.core.resources.marker"/>
   <persistent value="true"/>
   <attribute name="priority"/>
   <attribute name="message"/>
   <attribute name="done"/>
</extension>

Only the message attribute is likely to identify the specific kind of marker to associate with a F1 help context id. However this attribute cannot be used as its value is not unique across maker types and its value will be locale specific.
Other marker types may define an attribute that would be appropriate for this purpose. For example, the following is the extension declaration in the org.eclipse.jdt.core plug-in for java problem markers:

<extension id="problem" point="org.eclipse.core.resources.markers" name="%javaProblemName">
   <super type="org.eclipse.core.resources.problemmarker"/>
   <super type="org.eclipse.core.resources.textmarker"/>
   <persistent value="true"/>
   <attribute name="id"/>
   <attribute name="flags"/>
</extension>

It declares an "id" attribute that is likely to be appropriate for the purpose of associating a marker with a F1 help context id.

Desired Functionality

F1 Marker help

The workbench should provide public API to obtain a help context id for a given marker. This API would be accessed by the tasklist, for example, to obtain a help context for the selected task in response to the user pressing F1. This context id would we used to call the help support system API in the normal manner (via WorkbenchHelp).

The API would provide a getHelpContextId(IMarker) method. This method could be added to WorkbenchHelp. The API will only return a single help context id. It is up to help context definers to ensure that ids do not overlap. Note that this method will return a static context id. It will not return an IContextComputer. Furthermore the marker help extension point will only support the specification of a static help context id, it will not allow the specification of an IContextComputer. This is to avoid running plug-in code (and thus possibly triggering plug-in loading) when determining a help context id. Thus the marker help extension point must allow for a precise targeting of specific kinds of markers.
 

Marker Resolutions

It is improtant to distinguish resolutions and actions. The workbench already supports the ability to add object actions to markers (the current extension point has only a limited ability to specify the kind of marker for which the action is intended but this could be improved). Actions are completely general in terms of the code they actually perform. An action could in theory help "resolve" a marker, but it could just as easily open a dialog to edit properties of the marker. Resolutions, on the other hand, are specifically designed to perform work which results in the marker no longer being required.

It is hard to predict exactly how resolutions will appear in the UI. The may be presented as a list in a dialog or perhaps as a submenu. For example, 1) the task list may add a Resolutions item to its context menu 2) code assist may show a dialog listing resolutions when it encounters a problem such as an unresolved type. However, it is unlikely that they would require the full IAction API. Thus it would be reasonable to define an IMarkerResolution interface as follows:

public interface IMarkerResolution {
    /**
    * Initializes the resolution with the given marker.
    * It is assumed that the marker meets all the criteria specified in the
    * extension point which contributed this resolution.
    */
    public void init(IMarker);
    /**
    * Returns true if the resolution is appropriate for its marker
    */
    public boolean isAppropriate();
    /**
    * Returns a short label indicating what the resolution will do.
    */
    public void getLabel();
    /**
    * Runs this resolution, passing the triggering SWT event.
    */
    public void runWithEvent(Event event);
}

The org.eclipse.ui.markerResolution extension point will require a label, class name and targeting criteria to map a particular kind of marker to a resolution (see options below). While the label defined in the extension point (ex. Add import package statement) will be adequate to show the user, it would be more useful to obtain the label programmatically (ex. Add import org.eclipse.swt.widgets). In addition, while targeting criteria can be specified in the extension point, it would be possible to do a further target check programmatically. Thus resolutions will be instantiated before presenting them to the user, if the resolution's plug-in is loaded. Otherwise only the plugin.xml label and targeting will be used. In such a case, if it is later (after plug-in loading and resolution instantiation) determined that a selected resolution is not appropriate, the user will be informed by an info dialog.

An IMarkerResolutionRegistry would be will. API access to this registry could be added to IWorkbench. The registry would return all resolutions appropriate for a given marker (more than one resolution can be offered for a given marker).

Possible Solutions

1. The org.eclipse.core.resources plug-in adds an attribute named "org.eclipse.core.resources.id" attribute to its marker extension. This would also appear as a public static ID field on IMarker.

Example help extension:

  1. None required. A help context could be defined for the attribute value using existing help extension points.
  2. As an alternative we could provide an extension point to provide a layer of indirection between a marker id and a help context id.
<extension point="org.eclipse.ui.markerHelp">
   <markerHelp
      markerId="org.eclipse.jdt.core.unresolvedType"
      helpContextId="org.eclipse.jdt.ui.unresolvedType"/>
</extension>

    The level of indirection seems nice and it opens the possibility of mapping one marker id to more than one help context. However, in most cases these would probably seem like pointless extensions that simply slow down plug-in initialization and increase the size of the plug-in registry.

Example resolution extension:

<extension point="org.eclipse.ui.markerResolution">
   <resolution
      markerId="org.eclipse.jdt.core.unresolvedType"
      label="Add Import"
      class="org.eclipse.jdt.ui.AddImportResolution"/>
</extension>
 

2. The org.eclipse.ui plug-in will define a new marker type called helpmarker. This marker will define a single attribute org.eclipse.ui.helpId (this id would be used for both F1 help contexts and resolutions). This marker would be defined as a super type of any marker for which a helpId would be set.

Example help extension:

  1. None required. A help context could be defined for the attribute value using existing help extension points.
  2. As an alternative we could provide an extension point to provide a layer of indirection between a marker id and a help context id. However this is probably not needed, developers could always do their own mapping on marker creation if needed.


<extension point="org.eclipse.ui.markerHelp">
   <markerHelp
      helpId="org.eclipse.jdt.core.unresolvedType"
      helpContextId="org.eclipse.jdt.ui.unresolvedType"/>
</extension>
 

Example resolution extension:

<extension point="org.eclipse.ui.markerResolution">
   <resolution
      helpId="org.eclipse.jdt.core.unresolvedType"
      label="Add Import"
      class="org.eclipse.jdt.ui.AddImportResolution"/>
</extension>
 

3. We leave it up to marker creators to define their markers in such a way (using marker subtypes and attributes) that the markers can be mapped to help context ids and resolutions at the proper granularity.

Example help extension:

<extension point="org.eclipse.ui.markerHelp">
   <markerHelp
      markerType="org.eclipse.jdt.core.problem">
      <attribute name="id" value= "org.eclipse.jdt.core.unresolvedType"/>
      <helpContextId  value="org.eclipse.jdt.ui.unresolvedType"/>
   </markerHelp>
</extension>

A variation of this is to provide a mapping rule to use the matching attribute value(s) to be substituted as the help context id (or as part of it).
For example, JDT UI could define:

   <markerHelp
      markerType = "org.eclipse.jdt.core.problem">
      <attribute name="id" value="%id%"/>
      <helpContextId value="org.eclipse.jdt.ui.problem%id%"/>
   </markerHelp>

So the actual id value, e.g. "123" would get substituted into the help context id, giving "org.eclipse.jdt.ui.problem123".
This could also be used to implement Proposal 2 in terms of Proposal 3.  For example, Eclipse UI would define an identity mapping:

   <markerHelp
      markerType = "org.eclipse.ui.helpmarker">
      <attribute name="org.eclipse.ui.helpId" value="%helpId%"/>
      <helpContextId value="%helpId%"/>
   </markerHelp>
 

Example resolution extension:

<extension point="org.eclipse.ui.markerResolution">
   <markerResolution
      label="Add Import"
      class="org.eclipse.jdt.ui.AddImportResolution"
      markerType="org.eclipse.jdt.core.problem">
      <attribute name="id" value= "4563"/>
   </markerResolution>
</extension>
 

Defense of Solution

The preferred solution is option 3.
Option 1 is easy to understand and use but it is unclear that it would be able to support both  F1 help and resolutions at the desired level of granularity.
Option 2 is easy to understand and use and the chances of an error in the implementation are low. However, it would require "core level" plug-ins to reference a UI marker type.
Option 3 offers flexibility for plug-ins like org.eclipse.jdt.core which already define an id attribute and would not want to add another redundant one just to support help. This option is also similar to the popup menu extension point for adding actions to a marker.
The main disadvantage of option 3 is that it is the most complicated to implement.
 

RFC

This proposal is not currently being voted on however you should: If you have serious concerns don't wait until there is a vote - speak up now!
 
 

RFC Termination Date

The period for comment ends 1 week from date proposal is submitted to the mailing list.