From 5d0e9dc625503be8a171e2592c22b20c1a7df919 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Tue, 6 Dec 2016 00:18:59 -0500 Subject: [PATCH] Bug 507285 - Factor out the core logic in OpenIncludeAction into a separate class CElementIncludeResolver Change-Id: I07e78c3bbb39e24ec7684b32177a5b4c7881b1d2 --- .../ui/editor/CElementIncludeResolver.java | 238 ++++++++++++++++++ .../internal/ui/editor/OpenIncludeAction.java | 223 +--------------- 2 files changed, 241 insertions(+), 220 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementIncludeResolver.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementIncludeResolver.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementIncludeResolver.java new file mode 100644 index 00000000000..1475fc464d2 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CElementIncludeResolver.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright (c) 2016 Nathan Ridge and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.editor; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceProxy; +import org.eclipse.core.resources.IResourceProxyVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.parser.ExtendedScannerInfo; +import org.eclipse.cdt.core.parser.IExtendedScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.utils.PathUtil; +import org.eclipse.cdt.utils.UNCPathConverter; + +import org.eclipse.cdt.internal.core.resources.ResourceLookup; + +import org.eclipse.cdt.internal.ui.dialogs.ElementListSelectionDialog; + +/** + * Handles resolution of an include represented as a CElement (IInclude). + */ +public class CElementIncludeResolver { + public static IPath resolveInclude(IInclude include) throws CoreException { + IResource res = include.getUnderlyingResource(); + ArrayList filesFound = new ArrayList(4); + String fullFileName= include.getFullFileName(); + if (fullFileName != null) { + IPath fullPath = new Path(fullFileName); + if (fullPath.isAbsolute() && fullPath.toFile().exists()) { + filesFound.add(fullPath); + } else if (fullPath.isUNC()) { + IFileStore store = EFS.getStore(UNCPathConverter.getInstance().toURI(fullPath)); + if (store.fetchInfo().exists()) { + filesFound.add(fullPath); + } + } + } + if (filesFound.isEmpty() && res != null) { + IProject proj = res.getProject(); + String includeName = include.getElementName(); + // Search in the scannerInfo information + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(proj); + if (provider != null) { + IScannerInfo info = provider.getScannerInformation(res); + // XXXX this should fall back to project by itself + if (info == null) { + info = provider.getScannerInformation(proj); + } + if (info != null) { + IExtendedScannerInfo scanInfo = new ExtendedScannerInfo(info); + + boolean isSystemInclude = include.isStandard(); + + if (!isSystemInclude) { + // search in current directory + IPath location= include.getTranslationUnit().getLocation(); + if (location != null) { + String currentDir= location.removeLastSegments(1).toOSString(); + findFile(new String[] { currentDir }, includeName, filesFound); + } + if (filesFound.isEmpty()) { + // search in "..." include directories + String[] localIncludePaths = scanInfo.getLocalIncludePath(); + findFile(localIncludePaths, includeName, filesFound); + } + } + + if (filesFound.isEmpty()) { + // search in <...> include directories + String[] includePaths = scanInfo.getIncludePaths(); + findFile(includePaths, includeName, filesFound); + } + } + + if (filesFound.isEmpty()) { + // Fall back and search the project + findFile(proj, new Path(includeName), filesFound); + } + } + } + IPath fileToOpen; + int nElementsFound= filesFound.size(); + if (nElementsFound == 0) { + noElementsFound(); + fileToOpen= null; + } else if (nElementsFound == 1) { + fileToOpen= filesFound.get(0); + } else { + fileToOpen= chooseFile(filesFound); + } + return fileToOpen; + } + + private static void noElementsFound() { + MessageBox errorMsg = new MessageBox(CUIPlugin.getActiveWorkbenchShell(), SWT.ICON_ERROR | SWT.OK); + errorMsg.setText(CUIPlugin.getResourceString("OpenIncludeAction.error")); //$NON-NLS-1$ + errorMsg.setMessage (CUIPlugin.getResourceString("OpenIncludeAction.error.description")); //$NON-NLS-1$ + errorMsg.open(); + } + + private static void findFile(String[] includePaths, String name, ArrayList list) + throws CoreException { + // in case it is an absolute path + IPath includeFile= new Path(name); + if (includeFile.isAbsolute()) { + includeFile = PathUtil.getCanonicalPathWindows(includeFile); + if (includeFile.toFile().exists()) { + list.add(includeFile); + return; + } + } + HashSet foundSet = new HashSet(); + for (String includePath : includePaths) { + IPath path = PathUtil.getCanonicalPathWindows(new Path(includePath).append(includeFile)); + File file = path.toFile(); + if (file.exists()) { + IPath[] paths = resolveIncludeLink(path); + for (IPath p : paths) { + if (foundSet.add(p)) { + list.add(p); + } + } + } + } + } + + /** + * Recurse in the project. + * @param parent + * @param name + * @param list + * @throws CoreException + */ + private static void findFile(IContainer parent, final IPath name, final ArrayList list) throws CoreException { + parent.accept(new IResourceProxyVisitor() { + + @Override + public boolean visit(IResourceProxy proxy) throws CoreException { + if (proxy.getType() == IResource.FILE && proxy.getName().equalsIgnoreCase(name.lastSegment())) { + IPath rPath = proxy.requestResource().getLocation(); + if (rPath != null) { + int numSegToRemove = rPath.segmentCount() - name.segmentCount(); + IPath sPath = rPath.removeFirstSegments(numSegToRemove); + sPath = sPath.setDevice(name.getDevice()); + if (Platform.getOS().equals(Platform.OS_WIN32) ? + sPath.toOSString().equalsIgnoreCase(name.toOSString()) : + sPath.equals(name)) { + list.add(rPath); + } + return false; + } + } + return true; + } + }, 0); + } + + private static IPath chooseFile(ArrayList filesFound) { + ILabelProvider renderer= new LabelProvider() { + @Override + public String getText(Object element) { + if (element instanceof IPath) { + IPath file= (IPath)element; + return file.lastSegment() + " - " + file.toString(); //$NON-NLS-1$ + } + return super.getText(element); + } + }; + + ElementListSelectionDialog dialog= new ElementListSelectionDialog(CUIPlugin.getActiveWorkbenchShell(), renderer, false, false); + dialog.setTitle(CUIPlugin.getResourceString(OpenIncludeAction.DIALOG_TITLE)); + dialog.setMessage(CUIPlugin.getResourceString(OpenIncludeAction.DIALOG_MESSAGE)); + dialog.setElements(filesFound); + + if (dialog.open() == Window.OK) { + return (IPath) dialog.getSelectedElement(); + } + return null; + } + + /** + * Returns the path as is, if it points to a workspace resource. If the path + * does not point to a workspace resource, but there are linked workspace + * resources pointing to it, returns the paths of these resources. + * Otherwise, returns the path as is. + */ + private static IPath[] resolveIncludeLink(IPath path) { + if (!isInProject(path)) { + IFile[] files = ResourceLookup.findFilesForLocation(path); + if (files.length > 0) { + IPath[] paths = new IPath[files.length]; + for (int i = 0; i < files.length; i++) { + paths[i] = files[i].getFullPath(); + } + return paths; + } + } + + return new IPath[] { path }; + } + + private static boolean isInProject(IPath path) { + return getWorkspaceRoot().getFileForLocation(path) != null; + } + + private static IWorkspaceRoot getWorkspaceRoot() { + return ResourcesPlugin.getWorkspace().getRoot(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java index 66dd27615f5..7ea163056ea 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java @@ -14,51 +14,21 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.editor; -import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.filesystem.IFileStore; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceProxy; -import org.eclipse.core.resources.IResourceProxyVisitor; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.Action; -import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IInclude; -import org.eclipse.cdt.core.parser.ExtendedScannerInfo; -import org.eclipse.cdt.core.parser.IExtendedScannerInfo; -import org.eclipse.cdt.core.parser.IScannerInfo; -import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.cdt.utils.PathUtil; -import org.eclipse.cdt.utils.UNCPathConverter; - -import org.eclipse.cdt.internal.core.resources.ResourceLookup; import org.eclipse.cdt.internal.ui.CPluginImages; -import org.eclipse.cdt.internal.ui.dialogs.ElementListSelectionDialog; import org.eclipse.cdt.internal.ui.util.EditorUtility; @@ -66,12 +36,11 @@ public class OpenIncludeAction extends Action { private static final String PREFIX= "OpenIncludeAction."; //$NON-NLS-1$ - private static final String DIALOG_TITLE= PREFIX + "dialog.title"; //$NON-NLS-1$ - private static final String DIALOG_MESSAGE= PREFIX + "dialog.message"; //$NON-NLS-1$ + static final String DIALOG_TITLE= PREFIX + "dialog.title"; //$NON-NLS-1$ + static final String DIALOG_MESSAGE= PREFIX + "dialog.message"; //$NON-NLS-1$ private ISelectionProvider fSelectionProvider; - public OpenIncludeAction(ISelectionProvider provider) { super(CUIPlugin.getResourceString(PREFIX + "label")); //$NON-NLS-1$ setDescription(CUIPlugin.getResourceString(PREFIX + "description")); //$NON-NLS-1$ @@ -88,202 +57,16 @@ public class OpenIncludeAction extends Action { if (include == null) { return; } - try { - IResource res = include.getUnderlyingResource(); - ArrayList filesFound = new ArrayList(4); - String fullFileName= include.getFullFileName(); - if (fullFileName != null) { - IPath fullPath = new Path(fullFileName); - if (fullPath.isAbsolute() && fullPath.toFile().exists()) { - filesFound.add(fullPath); - } else if (fullPath.isUNC()) { - IFileStore store = EFS.getStore(UNCPathConverter.getInstance().toURI(fullPath)); - if (store.fetchInfo().exists()) { - filesFound.add(fullPath); - } - } - } - if (filesFound.isEmpty() && res != null) { - IProject proj = res.getProject(); - String includeName = include.getElementName(); - // Search in the scannerInfo information - IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(proj); - if (provider != null) { - IScannerInfo info = provider.getScannerInformation(res); - // XXXX this should fall back to project by itself - if (info == null) { - info = provider.getScannerInformation(proj); - } - if (info != null) { - IExtendedScannerInfo scanInfo = new ExtendedScannerInfo(info); - - boolean isSystemInclude = include.isStandard(); - - if (!isSystemInclude) { - // search in current directory - IPath location= include.getTranslationUnit().getLocation(); - if (location != null) { - String currentDir= location.removeLastSegments(1).toOSString(); - findFile(new String[] { currentDir }, includeName, filesFound); - } - if (filesFound.isEmpty()) { - // search in "..." include directories - String[] localIncludePaths = scanInfo.getLocalIncludePath(); - findFile(localIncludePaths, includeName, filesFound); - } - } - - if (filesFound.isEmpty()) { - // search in <...> include directories - String[] includePaths = scanInfo.getIncludePaths(); - findFile(includePaths, includeName, filesFound); - } - } - - if (filesFound.isEmpty()) { - // Fall back and search the project - findFile(proj, new Path(includeName), filesFound); - } - } - } - IPath fileToOpen; - int nElementsFound= filesFound.size(); - if (nElementsFound == 0) { - noElementsFound(); - fileToOpen= null; - } else if (nElementsFound == 1) { - fileToOpen= filesFound.get(0); - } else { - fileToOpen= chooseFile(filesFound); - } - + IPath fileToOpen = CElementIncludeResolver.resolveInclude(include); if (fileToOpen != null) { EditorUtility.openInEditor(fileToOpen, include); } - } catch (CModelException e) { - CUIPlugin.log(e.getStatus()); } catch (CoreException e) { CUIPlugin.log(e.getStatus()); } } - private void noElementsFound() { - MessageBox errorMsg = new MessageBox(CUIPlugin.getActiveWorkbenchShell(), SWT.ICON_ERROR | SWT.OK); - errorMsg.setText(CUIPlugin.getResourceString("OpenIncludeAction.error")); //$NON-NLS-1$ - errorMsg.setMessage (CUIPlugin.getResourceString("OpenIncludeAction.error.description")); //$NON-NLS-1$ - errorMsg.open(); - } - - private boolean isInProject(IPath path) { - return getWorkspaceRoot().getFileForLocation(path) != null; - } - - /** - * Returns the path as is, if it points to a workspace resource. If the path - * does not point to a workspace resource, but there are linked workspace - * resources pointing to it, returns the paths of these resources. - * Otherwise, returns the path as is. - */ - private IPath[] resolveIncludeLink(IPath path) { - if (!isInProject(path)) { - IFile[] files = ResourceLookup.findFilesForLocation(path); - if (files.length > 0) { - IPath[] paths = new IPath[files.length]; - for (int i = 0; i < files.length; i++) { - paths[i] = files[i].getFullPath(); - } - return paths; - } - } - - return new IPath[] { path }; - } - - private IWorkspaceRoot getWorkspaceRoot() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - - private void findFile(String[] includePaths, String name, ArrayList list) - throws CoreException { - // in case it is an absolute path - IPath includeFile= new Path(name); - if (includeFile.isAbsolute()) { - includeFile = PathUtil.getCanonicalPathWindows(includeFile); - if (includeFile.toFile().exists()) { - list.add(includeFile); - return; - } - } - HashSet foundSet = new HashSet(); - for (String includePath : includePaths) { - IPath path = PathUtil.getCanonicalPathWindows(new Path(includePath).append(includeFile)); - File file = path.toFile(); - if (file.exists()) { - IPath[] paths = resolveIncludeLink(path); - for (IPath p : paths) { - if (foundSet.add(p)) { - list.add(p); - } - } - } - } - } - - /** - * Recurse in the project. - * @param parent - * @param name - * @param list - * @throws CoreException - */ - private void findFile(IContainer parent, final IPath name, final ArrayList list) throws CoreException { - parent.accept(new IResourceProxyVisitor() { - - @Override - public boolean visit(IResourceProxy proxy) throws CoreException { - if (proxy.getType() == IResource.FILE && proxy.getName().equalsIgnoreCase(name.lastSegment())) { - IPath rPath = proxy.requestResource().getLocation(); - if (rPath != null) { - int numSegToRemove = rPath.segmentCount() - name.segmentCount(); - IPath sPath = rPath.removeFirstSegments(numSegToRemove); - sPath = sPath.setDevice(name.getDevice()); - if (Platform.getOS().equals(Platform.OS_WIN32) ? - sPath.toOSString().equalsIgnoreCase(name.toOSString()) : - sPath.equals(name)) { - list.add(rPath); - } - return false; - } - } - return true; - } - }, 0); - } - - private IPath chooseFile(ArrayList filesFound) { - ILabelProvider renderer= new LabelProvider() { - @Override - public String getText(Object element) { - if (element instanceof IPath) { - IPath file= (IPath)element; - return file.lastSegment() + " - " + file.toString(); //$NON-NLS-1$ - } - return super.getText(element); - } - }; - - ElementListSelectionDialog dialog= new ElementListSelectionDialog(CUIPlugin.getActiveWorkbenchShell(), renderer, false, false); - dialog.setTitle(CUIPlugin.getResourceString(DIALOG_TITLE)); - dialog.setMessage(CUIPlugin.getResourceString(DIALOG_MESSAGE)); - dialog.setElements(filesFound); - - if (dialog.open() == Window.OK) { - return (IPath) dialog.getSelectedElement(); - } - return null; - } - private static IInclude getIncludeStatement(ISelection sel) { if (!sel.isEmpty() && sel instanceof IStructuredSelection) { List list= ((IStructuredSelection)sel).toList();