Bug 578515 - [Navigator] NestedProjectsProblemsModel: Cache removal
breaks for IResources without location

If getLocation() is is null (e.g. on virtual IFileSystem
implementations), fall back to getFullPath().

Change-Id: I16eef7a1580efd95e1bec25df86ee6f75482ffa9
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/190252
Tested-by: Platform Bot <platform-bot@eclipse.org>
Reviewed-by: Mickael Istria <mistria@redhat.com>
diff --git a/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF
index bba9360..4b33496 100644
--- a/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Plugin.name
 Bundle-SymbolicName: org.eclipse.ui.navigator.resources; singleton:=true
-Bundle-Version: 3.8.300.qualifier
+Bundle-Version: 3.8.400.qualifier
 Bundle-Activator: org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorPlugin
 Bundle-Vendor: %Plugin.providerName
 Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/nested/NestedProjectsProblemsModel.java b/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/nested/NestedProjectsProblemsModel.java
index 2d805fd..06aeb2e 100644
--- a/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/nested/NestedProjectsProblemsModel.java
+++ b/bundles/org.eclipse.ui.navigator.resources/src/org/eclipse/ui/internal/navigator/resources/nested/NestedProjectsProblemsModel.java
@@ -93,22 +93,36 @@
 			if (currentContainer == null) {
 				continue;
 			}
+
 			IPath currentLocation = currentContainer.getLocation();
-			if (currentLocation == null) {
-				continue;
+			if (currentLocation != null) {
+				// We have a physical location on disk.
+				// Use getLocation() to more efficiently handle nested projects and avoid
+				// redundant updates for identical resources appearing multiple times in the
+				// IResource tree.
+				dirtyLeafContainers.removeIf(leafContainer -> {
+					IPath leafLocation = leafContainer.getLocation();
+					return leafLocation != null && leafLocation.isPrefixOf(currentLocation);
+				});
+				if (dirtyLeafContainers.stream().noneMatch(leafContainer -> {
+					IPath leafLocation = leafContainer.getLocation();
+					return leafLocation != null && currentLocation.isPrefixOf(leafLocation);
+				})) {
+					dirtyLeafContainers.add(currentContainer);
+				}
+			} else {
+				// No physical location on disk (e.g. using a virtual
+				// org.eclipse.core.filesystem.IFileSystem implementation)
+				// Fall back to getFullPath(), which his always available, but could lead to
+				// redundant updates.
+				dirtyLeafContainers.removeIf( //
+						leafContainer -> leafContainer.getFullPath().isPrefixOf(currentContainer.getFullPath()));
+				if (dirtyLeafContainers.stream().noneMatch( //
+						leafContainer -> currentContainer.getFullPath().isPrefixOf(leafContainer.getFullPath()))) {
+					dirtyLeafContainers.add(currentContainer);
+				}
 			}
-			dirtyLeafContainers
-					.removeIf(leafContainer -> {
-						IPath leafLocation = leafContainer.getLocation();
-						return leafLocation != null && leafLocation.isPrefixOf(currentLocation);
-					});
-			if (dirtyLeafContainers.stream().noneMatch(
-					leafContainer -> {
-						IPath leafLocation = leafContainer.getLocation();
-						return leafLocation != null && currentLocation.isPrefixOf(leafLocation);
-					})) {
-				dirtyLeafContainers.add(currentContainer);
-			}
+
 			if (resource.getType() == IResource.FILE) {
 				cache.remove(resource);
 				modifiedSeveritySinceLastRun.add(resource);