Bug 576341 - QuickAccess allows to open a file for a given path

Change-Id: Icf0130ca7e3dce4b3f21f11a9f96c04913398d70
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/191883
Tested-by: Platform Bot <platform-bot@eclipse.org>
Reviewed-by: Mickael Istria <mistria@redhat.com>
diff --git a/bundles/org.eclipse.ui.ide/plugin.properties b/bundles/org.eclipse.ui.ide/plugin.properties
index e1e922f..e8cb831 100644
--- a/bundles/org.eclipse.ui.ide/plugin.properties
+++ b/bundles/org.eclipse.ui.ide/plugin.properties
@@ -360,3 +360,4 @@
 importer.eclipseWorkspace=Eclipse workspace
 importer.eclipseProject=Eclipse project
 quickAccess.resources.name=Resources
+quickAccess.filesystemPath.name=Filesystem path
diff --git a/bundles/org.eclipse.ui.ide/plugin.xml b/bundles/org.eclipse.ui.ide/plugin.xml
index 49d78e3..017ca47 100644
--- a/bundles/org.eclipse.ui.ide/plugin.xml
+++ b/bundles/org.eclipse.ui.ide/plugin.xml
@@ -2708,6 +2708,11 @@
             name="%quickAccess.resources.name"
             requiresUIAccess="false">
       </computer>
+      <computer
+            class="org.eclipse.ui.internal.ide.dialogs.OpenFilesystemQuickAccessComputer"
+            name="%quickAccess.filesystemPath.name"
+            requiresUIAccess="false">
+      </computer>
    </extension>
 
 </plugin>
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenFilesystemQuickAccessComputer.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenFilesystemQuickAccessComputer.java
new file mode 100644
index 0000000..d7ed1ac
--- /dev/null
+++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenFilesystemQuickAccessComputer.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Red Hat, Inc. and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.ui.internal.ide.dialogs;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Optional;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.ui.internal.ide.dialogs.OpenResourceQuickAccessComputer.ResourceElement;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.ui.quickaccess.IQuickAccessComputerExtension;
+import org.eclipse.ui.quickaccess.QuickAccessElement;
+
+/**
+ * @since 3.18.600
+ */
+public class OpenFilesystemQuickAccessComputer implements IQuickAccessComputerExtension {
+
+	private class FileElement extends QuickAccessElement {
+
+		private File file;
+
+		public FileElement(File file) {
+			this.file = file;
+		}
+
+		@Override
+		public String getLabel() {
+			return file.getAbsolutePath();
+		}
+
+		@Override
+		public ImageDescriptor getImageDescriptor() {
+			return null;
+		}
+
+		@Override
+		public String getId() {
+			return file.getAbsolutePath();
+		}
+
+		@Override
+		public void execute() {
+			new UIJob(getLabel()) {
+				@Override
+				public IStatus runInUIThread(IProgressMonitor monitor) {
+					try {
+						IDE.openEditorOnFileStore(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(),
+								EFS.getStore(file.toURI()));
+					} catch (CoreException e) {
+						return new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, e.getMessage(), e);
+					}
+					return Status.OK_STATUS;
+				}
+			}.schedule();
+		}
+
+	}
+
+	private static final QuickAccessElement[] NOTHING = new QuickAccessElement[0];
+
+	@Override
+	public QuickAccessElement[] computeElements() {
+		return NOTHING;
+	}
+
+	@Override
+	public void resetState() {
+		// Nothing to do
+	}
+
+	@Override
+	public boolean needsRefresh() {
+		return true;
+	}
+
+	@Override
+	public QuickAccessElement[] computeElements(String query, IProgressMonitor monitor) {
+		File file = new File(query);
+		if (file.isFile() && file.canRead()) {
+			return Arrays.stream(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.toURI())) //
+					.sorted(Comparator.comparingInt(resource -> resource.getFullPath().segmentCount())) //
+					.findFirst() //
+					.map(resource -> (QuickAccessElement) new ResourceElement(new WorkbenchLabelProvider(), resource)) //
+					.or(() -> Optional.of(new FileElement(file))) //
+					.map(element -> new QuickAccessElement[] { element }) //
+					.orElse(NOTHING);
+		}
+		return NOTHING;
+	}
+
+}
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenResourceQuickAccessComputer.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenResourceQuickAccessComputer.java
index c49619e..510bf9a 100644
--- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenResourceQuickAccessComputer.java
+++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/OpenResourceQuickAccessComputer.java
@@ -91,11 +91,11 @@
 		return false;
 	}
 
-	private static class ResourceElement extends QuickAccessElement {
+	static class ResourceElement extends QuickAccessElement {
 		private final WorkbenchLabelProvider fLabelProvider;
 		private final IFile fFile;
 
-		private ResourceElement(WorkbenchLabelProvider labelProvider, IFile resource) {
+		ResourceElement(WorkbenchLabelProvider labelProvider, IFile resource) {
 			fLabelProvider = labelProvider;
 			fFile = resource;
 		}