package org.python.pydev.shared_core.locator; import java.util.ArrayList; import java.util.HashSet; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.python.pydev.shared_core.log.Log; public class GetContainers { /** * This method is a workaround for w.getRoot().getContainerForLocation(path); which does not work consistently because * it filters out files which should not be filtered (i.e.: if a project is not in the workspace but imported). * * Also, it can fail to get resources in linked folders in the pythonpath. * * @param project is optional (may be null): if given we'll search in it dependencies first. */ public IContainer getContainerForLocation(IPath location, IProject project) { boolean stopOnFirst = true; IContainer[] filesForLocation = getContainersForLocation(location, project, stopOnFirst); if (filesForLocation != null && filesForLocation.length > 0) { return filesForLocation[0]; } return null; } /** * This method is a workaround for w.getRoot().getContainersForLocation(path); which does not work consistently because * it filters out files which should not be filtered (i.e.: if a project is not in the workspace but imported). * * Also, it can fail to get resources in linked folders in the pythonpath. * * @param project is optional (may be null): if given we'll search in it dependencies first. */ public IContainer[] getContainersForLocation(IPath location, IProject project, boolean stopOnFirst) { ArrayList<IContainer> lst = new ArrayList<>(); HashSet<IProject> checked = new HashSet<>(); IWorkspace w = ResourcesPlugin.getWorkspace(); if (project != null) { checked.add(project); IContainer f = getContainerInProject(location, project); if (f != null) { if (stopOnFirst) { return new IContainer[] { f }; } else { lst.add(f); } } try { IProject[] referencedProjects = project.getDescription().getReferencedProjects(); for (int i = 0; i < referencedProjects.length; i++) { IProject p = referencedProjects[i]; checked.add(p); f = getContainerInProject(location, p); if (f != null) { if (stopOnFirst) { return new IContainer[] { f }; } else { lst.add(f); } } } } catch (CoreException e) { Log.log(e); } } IProject[] projects = w.getRoot().getProjects(IContainer.INCLUDE_HIDDEN); for (int i = 0; i < projects.length; i++) { IProject p = projects[i]; if (checked.contains(p)) { continue; } checked.add(p); IContainer f = getContainerInProject(location, p); if (f != null) { if (stopOnFirst) { return new IContainer[] { f }; } else { lst.add(f); } } } return lst.toArray(new IContainer[lst.size()]); } /** * Gets an IContainer inside a container given a path in the filesystem (resolves the full path of the container and * checks if the location given is under it). */ protected IContainer getContainerInContainer(IPath location, IContainer container) { IPath projectLocation = container.getLocation(); if (projectLocation != null && projectLocation.isPrefixOf(location)) { int segmentsToRemove = projectLocation.segmentCount(); IPath removeFirstSegments = location.removeFirstSegments(segmentsToRemove); if (removeFirstSegments.segmentCount() == 0) { return container; //I.e.: equal to container } IContainer file = container.getFolder(removeFirstSegments); if (file.exists()) { return file; } } return null; } /** * Tries to get a file from a project. Considers source folders (which could be linked) or resources directly beneath * the project. * @param location this is the path location to be gotten. * @param project this is the project we're searching. * @return the file found or null if it was not found. */ protected IContainer getContainerInProject(IPath location, IProject project) { IContainer file = getContainerInContainer(location, project); if (file != null) { return file; } return null; } }