Skip to content

Commit

Permalink
Load marker content generator details from extensions eclipse-platfor…
Browse files Browse the repository at this point in the history
…m#2193

It was not possible to add new columns to MarkerSupportViews via marker content generator extensions.
By loading marker fields, marker types, and groups from marker content generator extensions that will be possible.
This way, the problems view and markers view can be extended with new columns like, for example, an issue ID and URL to a detailed problem description.

Fixes eclipse-platform#2193
  • Loading branch information
travkin79 committed Sep 9, 2024
1 parent 5c74619 commit 627a21b
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream;

Expand All @@ -43,12 +45,9 @@ public class ContentGeneratorDescriptor {
private static final String MARKER_FIELD_REFERENCE = "markerFieldReference"; //$NON-NLS-1$

private IConfigurationElement configurationElement;
private MarkerField[] allFields;
private Collection<MarkerType> markerTypes;
private MarkerField[] initialVisible;
private Collection<MarkerGroup> groups;
private MarkerField[] allFieldsWithoutExtensions;
private MarkerField[] initialVisibleWithoutExtensions;
private Collection<IConfigurationElement> generatorExtensions = new ArrayList<>();
private Map<String, MarkerType> allTypesTable;

/**
* Create a new ContentGeneratorDescriptor
Expand All @@ -60,13 +59,13 @@ public ContentGeneratorDescriptor(IConfigurationElement element) {
/**
* Add the groups defined in the receiver to the collection of groups.
*/
private void addDefinedGroups(Collection<MarkerGroup> groupss) {
private void addDefinedGroups(Collection<MarkerGroup> groups) {
// Add the ones in the receiver.
addGroupsFrom(configurationElement, groupss);
addGroupsFrom(configurationElement, groups);
// Add the extensions
Iterator<IConfigurationElement> extensions = generatorExtensions.iterator();
while (extensions.hasNext()) {
addGroupsFrom(extensions.next(), groupss);
addGroupsFrom(extensions.next(), groups);
}
}

Expand Down Expand Up @@ -96,7 +95,7 @@ private void addGroupsFrom(IConfigurationElement element, Collection<MarkerGroup
* @return boolean
*/
public boolean allTypesSelected(Collection<MarkerType> selectedTypes) {
return selectedTypes.containsAll(markerTypes);
return selectedTypes.containsAll(getMarkerTypes());
}

/**
Expand All @@ -105,7 +104,26 @@ public boolean allTypesSelected(Collection<MarkerType> selectedTypes) {
* @return {@link MarkerField}[]
*/
public MarkerField[] getAllFields() {
return allFields;
List<MarkerField> allFieldsList = new ArrayList<>(Arrays.asList(allFieldsWithoutExtensions));

getExtensionsDescriptorsStream().flatMap(descriptor -> Arrays.stream(descriptor.getAllFields()))
.forEach(field -> allFieldsList.add(field));

return allFieldsList.toArray(new MarkerField[allFieldsList.size()]);
}

private Stream<ContentGeneratorDescriptor> getExtensionsDescriptorsStream() {
if (generatorExtensions != null) {
final MarkerSupportRegistry registry = MarkerSupportRegistry.getInstance();

return generatorExtensions.stream()
.map(extensionConfigElem -> extensionConfigElem
.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_ID))
.filter(id -> id != null && !id.isBlank())
.map(contentGeneratorId -> registry.getContentGenDescriptor(contentGeneratorId))
.filter(generator -> generator != null);
}
return Stream.empty();
}

/**
Expand Down Expand Up @@ -156,7 +174,12 @@ public String getId() {
* @return {@link MarkerField}[]
*/
public MarkerField[] getInitialVisible() {
return initialVisible;
List<MarkerField> allVisibleFieldsList = new ArrayList<>(Arrays.asList(initialVisibleWithoutExtensions));

getExtensionsDescriptorsStream().flatMap(descriptor -> Arrays.stream(descriptor.getInitialVisible()))
.forEach(field -> allVisibleFieldsList.add(field));

return allVisibleFieldsList.toArray(new MarkerField[allVisibleFieldsList.size()]);
}

/**
Expand All @@ -165,16 +188,15 @@ public MarkerField[] getInitialVisible() {
* @return Collection of {@link MarkerGroup}
*/
public Collection<MarkerGroup> getMarkerGroups() {
if (groups == null) {
groups = new TreeSet<>((mg1, mg2) -> mg1.getMarkerField().getName().compareTo(mg2.getMarkerField().getName()));
Collection<MarkerGroup> groups = new TreeSet<>(
(mg1, mg2) -> mg1.getMarkerField().getName().compareTo(mg2.getMarkerField().getName()));

// Add the groups defined in the receiver
addDefinedGroups(groups);
// Add the groups defined in the receiver
addDefinedGroups(groups);

if (getId().equals(MarkerSupportRegistry.PROBLEMS_GENERATOR)) {
// Add the groups that reference the receiver.
groups.addAll(MarkerSupportRegistry.getInstance().getMarkerGroups());
}
if (getId().equals(MarkerSupportRegistry.PROBLEMS_GENERATOR)) {
// Add the groups that reference the receiver.
groups.addAll(MarkerSupportRegistry.getInstance().getMarkerGroups());
}
return groups;
}
Expand All @@ -185,23 +207,41 @@ public Collection<MarkerGroup> getMarkerGroups() {
* @return Collection of {@link MarkerType}
*/
public Collection<MarkerType> getMarkerTypes() {
if (markerTypes == null) {
markerTypes = new HashSet<>();
IConfigurationElement[] markerTypeElements = configurationElement.getChildren(MarkerSupportRegistry.MARKER_TYPE_REFERENCE);
for (IConfigurationElement configElement : markerTypeElements) {
String elementName = configElement.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_ID);
MarkerType[] types = MarkerTypesModel.getInstance().getType(elementName).getAllSubTypes();
markerTypes.addAll(Arrays.asList(types));
markerTypes.add(MarkerTypesModel.getInstance().getType(elementName));
}
if (markerTypes.isEmpty()) {
MarkerType[] types = MarkerTypesModel.getInstance().getType(IMarker.PROBLEM).getAllSubTypes();
markerTypes.addAll(Arrays.asList(types));
Set<MarkerType> markerTypes = new HashSet<>();
addMarkerTypesFrom(configurationElement, markerTypes);

Iterator<IConfigurationElement> extensions = generatorExtensions.iterator();
while (extensions.hasNext()) {
IConfigurationElement extensionElement = extensions.next();
String extendingMarkerContentGeneratorId = extensionElement
.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_ID);
if (extendingMarkerContentGeneratorId != null && !extendingMarkerContentGeneratorId.isBlank()) {
ContentGeneratorDescriptor descriptor = MarkerSupportRegistry.getInstance()
.getContentGenDescriptor(extendingMarkerContentGeneratorId);
if (descriptor != null) {
markerTypes.addAll(descriptor.getMarkerTypes());
}
}
}
return markerTypes;
}

private void addMarkerTypesFrom(IConfigurationElement markerContentGeneratorConfigElement,
Collection<MarkerType> markerTypes) {
IConfigurationElement[] markerTypeElements = markerContentGeneratorConfigElement
.getChildren(MarkerSupportRegistry.MARKER_TYPE_REFERENCE);
for (IConfigurationElement configElement : markerTypeElements) {
String elementName = configElement.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_ID);
MarkerType[] types = MarkerTypesModel.getInstance().getType(elementName).getAllSubTypes();
markerTypes.addAll(Arrays.asList(types));
markerTypes.add(MarkerTypesModel.getInstance().getType(elementName));
}
if (markerTypes.isEmpty()) {
MarkerType[] types = MarkerTypesModel.getInstance().getType(IMarker.PROBLEM).getAllSubTypes();
markerTypes.addAll(Arrays.asList(types));
}
}

/**
* Return the name for the receiver.
*
Expand All @@ -227,14 +267,12 @@ public MarkerType getType(String typeId) {
* @return Map of {@link String} to {@link MarkerType}
*/
public Map<String, MarkerType> getTypesTable() {
if (allTypesTable == null) {
allTypesTable = new HashMap<>();
Map<String, MarkerType> allTypesTable = new HashMap<>();

Iterator<MarkerType> allIterator = markerTypes.iterator();
while (allIterator.hasNext()) {
MarkerType next = allIterator.next();
allTypesTable.put(next.getId(), next);
}
Iterator<MarkerType> allIterator = getMarkerTypes().iterator();
while (allIterator.hasNext()) {
MarkerType next = allIterator.next();
allTypesTable.put(next.getId(), next);
}
return allTypesTable;
}
Expand Down Expand Up @@ -264,11 +302,11 @@ public void initializeFromConfigurationElement(
}
}

allFields = new MarkerField[allFieldList.size()];
allFieldList.toArray(allFields);
allFieldsWithoutExtensions = new MarkerField[allFieldList.size()];
allFieldList.toArray(allFieldsWithoutExtensions);

initialVisible = new MarkerField[initialVisibleList.size()];
initialVisibleList.toArray(initialVisible);
initialVisibleWithoutExtensions = new MarkerField[initialVisibleList.size()];
initialVisibleList.toArray(initialVisibleWithoutExtensions);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
import org.eclipse.ui.internal.views.markers.FiltersConfigurationDialog;
import org.eclipse.ui.internal.views.markers.MarkerContentGenerator;
import org.eclipse.ui.tests.harness.util.UITestCase;
import org.eclipse.ui.views.markers.MarkerField;
import org.eclipse.ui.views.markers.MarkerSupportView;
import org.eclipse.ui.views.markers.internal.ContentGeneratorDescriptor;
import org.eclipse.ui.views.markers.internal.MarkerGroup;
import org.eclipse.ui.views.markers.internal.MarkerMessages;
import org.eclipse.ui.views.markers.internal.MarkerSupportRegistry;
import org.eclipse.ui.views.markers.internal.MarkerType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
Expand Down Expand Up @@ -125,6 +130,59 @@ public void limitDisabled() throws Exception {
assertFalse(isLimitEnabled);
}

@Test
public void markerContentGeneratorExtensionLoaded() throws Exception {
MarkerSupportView view = (MarkerSupportView) PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().showView(PROBLEM_VIEW_ID);

MarkerContentGenerator generator = getMarkerContentGenerator(view);
ContentGeneratorDescriptor descriptor = MarkerSupportRegistry.getInstance()
.getContentGenDescriptor(generator.getId());
assertNotNull(descriptor);

MarkerField[] allFields = descriptor.getAllFields();
boolean foundAdditionalField1 = false;
boolean foundRecursivelyAddedField2 = false;
for (MarkerField field : allFields) {
if (ProblemKeyMarkerField.class.equals(field.getClass())) {
if ("Problem Key".equals(field.getName())) {
foundAdditionalField1 = true;
}

if ("Problem Key V2".equals(field.getName())) {
foundRecursivelyAddedField2 = true;
}
}
}
assertTrue("MarkerFields from marker content generator extensions not loaded.",
foundAdditionalField1);
assertTrue("MarkerField not loaded from recursive marker content generator extension.",
foundRecursivelyAddedField2);

MarkerField[] initiallyVisibleFields = descriptor.getInitialVisible();
boolean foundAdditionalVisbileField = false;
for (MarkerField field : initiallyVisibleFields) {
if ("Problem Key".equals(field.getName())) {
foundAdditionalVisbileField = true;
}
}
assertTrue("Visible attribute from marker fields from marker content generator extensions not loaded.",
foundAdditionalVisbileField);

MarkerType markerTypeFromExtension = descriptor.getType("org.eclipse.ui.tests.markers.artificial.problem");
assertNotNull("Marker type from marker content generator extensions not loaded.", markerTypeFromExtension);
assertTrue(descriptor.getMarkerTypes().contains(markerTypeFromExtension));

Collection<MarkerGroup> groups = descriptor.getMarkerGroups();
boolean foundAdditionalMarkerGroup = false;
for (MarkerGroup group : groups) {
if ("org.eclipse.ui.tests.test.extended".equals(group.getId())) {
foundAdditionalMarkerGroup = true;
}
}
assertTrue("Marker groups from marker content generator extensions not loaded.", foundAdditionalMarkerGroup);
}

public static MarkerContentGenerator getMarkerContentGenerator(MarkerSupportView view) {
MarkerContentGenerator generator = null;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.eclipse.ui.tests.markers;

import org.eclipse.ui.views.markers.MarkerField;
import org.eclipse.ui.views.markers.MarkerItem;

public class ProblemKeyMarkerField extends MarkerField {

@Override
public String getValue(MarkerItem item) {
if (item == null) {
return "";
}
return item.getAttributeValue("problemKey", "");
}

}
70 changes: 69 additions & 1 deletion tests/org.eclipse.ui.tests/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3411,7 +3411,56 @@
</markerContentGenerator>
<markerContentGenerator
id="org.eclipse.ui.tests.customScopeContentGenerator">
</markerContentGenerator>
</markerContentGenerator>
<markerField
class="org.eclipse.ui.tests.markers.ProblemKeyMarkerField"
id="org.eclipse.ui.tests.markerField.problemKey"
name="Problem Key">
</markerField>
<markerField
class="org.eclipse.ui.tests.markers.ProblemKeyMarkerField"
id="org.eclipse.ui.tests.markerField.problemKeyV2"
name="Problem Key V2">
</markerField>
<markerContentGenerator
id="org.eclipse.ui.tests.additionalProblemMarkerContentGenerator"
name="Additional Problem Marker Content Generator">
<markerFieldReference
id="org.eclipse.ui.tests.markerField.problemKey">
</markerFieldReference>
<markerTypeReference
id="org.eclipse.ui.tests.markers.static.analysis.problem">
</markerTypeReference>
<markerTypeReference
id="org.eclipse.ui.tests.markers.artificial.problem">
</markerTypeReference>
</markerContentGenerator>
<markerContentGeneratorExtension
generatorId="org.eclipse.ui.ide.problemsGenerator"
id="org.eclipse.ui.tests.additionalProblemMarkerContentGenerator">
<markerGrouping
id="org.eclipse.ui.tests.test.extended"
label="Extended Problem Category">
</markerGrouping>
</markerContentGeneratorExtension>
<markerContentGeneratorExtension
generatorId="org.eclipse.ui.ide.allMarkersGenerator"
id="org.eclipse.ui.tests.additionalProblemMarkerContentGenerator">
</markerContentGeneratorExtension>
<markerContentGenerator
id="org.eclipse.ui.tests.additionalProblemMarkerContentGenerator2"
name="Additional Problem Marker Content Generator 2">
<markerFieldReference
id="org.eclipse.ui.tests.markerField.problemKeyV2">
</markerFieldReference>
<markerTypeReference
id="org.eclipse.ui.tests.markers.static.analysis.problem">
</markerTypeReference>
</markerContentGenerator>
<markerContentGeneratorExtension
generatorId="org.eclipse.ui.tests.additionalProblemMarkerContentGenerator"
id="org.eclipse.ui.tests.additionalProblemMarkerContentGenerator2">
</markerContentGeneratorExtension>
</extension>
<extension
id="categoryTestMarker"
Expand Down Expand Up @@ -4838,5 +4887,24 @@
categoryId="org.eclipse.ui.tests.issue1832">
</categoryActivityBinding>
</extension>
<extension
id="markers.static.analysis.problem"
name="Static Analysis Test Problem"
point="org.eclipse.core.resources.markers">
<super
type="org.eclipse.core.resources.problemmarker">
</super>
<persistent
value="true">
</persistent>
<attribute
name="problemKey">
</attribute>
</extension>
<extension
id="markers.artificial.problem"
name="Artificial Test Problem"
point="org.eclipse.core.resources.markers">
</extension>

</plugin>

0 comments on commit 627a21b

Please sign in to comment.