diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ExtendedMarkersView.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ExtendedMarkersView.java index 2a3fdb661a0..af74d82ab88 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ExtendedMarkersView.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ExtendedMarkersView.java @@ -24,11 +24,14 @@ import java.util.Collection; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import org.eclipse.core.commands.operations.IUndoContext; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.Assert; @@ -1642,16 +1645,35 @@ public void selectionChanged(IWorkbenchPart part, ISelection selection) { } // try to adapt them in resources and add it to the // selectedElements - List selectedElements = new ArrayList<>(); + Set selectedElements = new LinkedHashSet<>(); for (Object object : objectsToAdapt) { Object resElement = MarkerResourceUtil.adapt2ResourceElement(object); if (resElement != null) { selectedElements.add(resElement); } } + if (isProjectNestingActive(part)) { + List selectedProjects = selectedElements.stream().filter(IProject.class::isInstance) + .map(IProject.class::cast).toList(); + if (!selectedProjects.isEmpty()) { + selectedElements.addAll(MarkerResourceUtil.getNestedChildProjects(selectedProjects)); + } + } MarkerContentGenerator gen = view.getGenerator(); gen.updateSelectedResource(selectedElements.toArray(), part == null); } + + } + + /** + * Check if project nesting is active for this marker view + * + * @param part the currently selected part + * @return true if nesting should be performed, false + * otherwise + */ + protected boolean isProjectNestingActive(IWorkbenchPart part) { + return false; } /** diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/MarkerResourceUtil.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/MarkerResourceUtil.java index 93a5062e156..ce8b6890125 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/MarkerResourceUtil.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/MarkerResourceUtil.java @@ -31,6 +31,7 @@ import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.ui.internal.ide.Policy; import org.eclipse.ui.internal.util.Util; @@ -286,6 +287,45 @@ static Collection getProjectsAsCollection(Object[] elements) { return projects; } + /** + * Returns all nested child projects of the given projects. A project is + * considered a nested child if its location is a descendant of the parent + * project's location. This supports the hierarchical project display feature. + * + * @param parentProjects + * the projects to find nested children for + * @return collection of all nested child projects (does not include the parent + * projects themselves) + */ + static Collection getNestedChildProjects(Collection parentProjects) { + if (parentProjects == null || parentProjects.isEmpty()) { + return Set.of(); + } + Set nestedChildren = new HashSet<>(); + + for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { + if (!project.exists() || !project.isAccessible()) { + continue; + } + IPath projectLocation = project.getLocation(); + if (projectLocation == null) { + continue; + } + // Check if this project is nested under any of the parent projects + for (IProject parentProject : parentProjects) { + if (parentProject.equals(project)) { + continue; // Skip the project itself + } + IPath parentLocation = parentProject.getLocation(); + if (parentLocation != null && parentLocation.isPrefixOf(projectLocation)) { + nestedChildren.add(project); + break; + } + } + } + return nestedChildren; + } + /** * Add the resources in resourceMapping to the resourceCollection */ diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ProblemsView.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ProblemsView.java index b6c0a4e1227..d48dc04316e 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ProblemsView.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/views/markers/ProblemsView.java @@ -17,9 +17,11 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.Assert; import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages; +import org.eclipse.ui.navigator.CommonNavigator; import org.eclipse.ui.views.markers.MarkerSupportView; import org.eclipse.ui.views.markers.internal.MarkerMessages; import org.eclipse.ui.views.markers.internal.MarkerSupportRegistry; @@ -64,4 +66,14 @@ protected String getDeleteOperationName(IMarker[] markers) { return markers.length == 1 ? MarkerMessages.deleteProblemMarker_operationName : MarkerMessages.deleteProblemMarkers_operationName; } + @Override + protected boolean isProjectNestingActive(IWorkbenchPart part) { + if (part instanceof CommonNavigator navigator) { + return navigator.getNavigatorContentService().getActivationService().isNavigatorExtensionActive( + "org.eclipse.ui.navigator.resources.nested.nestedProjectContentProvider"); //$NON-NLS-1$ + + } + return false; + } + }