Copyright (c) 2000, 2013 IBM Corporation 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 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.internal.core.search; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaElementDelta; import org.eclipse.jdt.core.IJavaModel; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.core.ClasspathEntry; import org.eclipse.jdt.internal.core.ExternalFoldersManager; import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.JavaModel; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.PackageFragment; import org.eclipse.jdt.internal.core.PackageFragmentRoot; import org.eclipse.jdt.internal.core.util.Util;
A Java-specific scope for searching relative to one or more java elements.
/** * A Java-specific scope for searching relative to one or more java elements. */
@SuppressWarnings({"rawtypes", "unchecked"}) public class JavaSearchScope extends AbstractJavaSearchScope { private ArrayList elements; /* The paths of the resources in this search scope (or the classpath entries' paths if the resources are projects) */ private ArrayList projectPaths = new ArrayList(); // container paths projects private int[] projectIndexes; // Indexes of projects in list private String[] containerPaths; // path to the container (e.g. /P/src, /P/lib.jar, c:\temp\mylib.jar) private String[] relativePaths; // path relative to the container (e.g. x/y/Z.class, x/y, (empty)) private boolean[] isPkgPath; // in the case of packages, matches must be direct children of the folder protected AccessRuleSet[] pathRestrictions; private int pathsCount; private int threshold; private IPath[] enclosingProjectsAndJars; public final static AccessRuleSet NOT_ENCLOSED = new AccessRuleSet(null, (byte) 0, null); private final boolean excludeTestCode; public JavaSearchScope(boolean excludeTestCode) { this(5, excludeTestCode); } private JavaSearchScope(int size, boolean excludeTestCode) { this.excludeTestCode = excludeTestCode; initialize(size); //disabled for now as this could be expensive //JavaModelManager.getJavaModelManager().rememberScope(this); } private void addEnclosingProjectOrJar(IPath path) { int length = this.enclosingProjectsAndJars.length; for (int i = 0; i < length; i++) { if (this.enclosingProjectsAndJars[i].equals(path)) return; } System.arraycopy( this.enclosingProjectsAndJars, 0, this.enclosingProjectsAndJars = new IPath[length+1], 0, length); this.enclosingProjectsAndJars[length] = path; }
Add java project all fragment roots to current java search scope.
See Also:
  • add(JavaProject, IPath, int, HashSet, HashSet, IClasspathEntry)
/** * Add java project all fragment roots to current java search scope. * @see #add(JavaProject, IPath, int, HashSet, HashSet, IClasspathEntry) */
public void add(JavaProject project, int includeMask, HashSet projectsToBeAdded) throws JavaModelException { add(project, null, includeMask, projectsToBeAdded, new HashSet(2), null); }
Add a path to current java search scope or all project fragment roots if null. Use project resolved classpath to retrieve and store access restriction on each classpath entry. Recurse if dependent projects are found.
Params:
  • javaProject – Project used to get resolved classpath entries
  • pathToAdd – Path to add in case of single element or null if user want to add all project package fragment roots
  • includeMask – Mask to apply on classpath entries
  • projectsToBeAdded – Set to avoid infinite recursion
  • visitedProjects – Set to avoid adding twice the same project
  • referringEntry – Project raw entry in referring project classpath
Throws:
/** * Add a path to current java search scope or all project fragment roots if null. * Use project resolved classpath to retrieve and store access restriction on each classpath entry. * Recurse if dependent projects are found. * @param javaProject Project used to get resolved classpath entries * @param pathToAdd Path to add in case of single element or null if user want to add all project package fragment roots * @param includeMask Mask to apply on classpath entries * @param projectsToBeAdded Set to avoid infinite recursion * @param visitedProjects Set to avoid adding twice the same project * @param referringEntry Project raw entry in referring project classpath * @throws JavaModelException May happen while getting java model info */
void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet projectsToBeAdded, HashSet visitedProjects, IClasspathEntry referringEntry) throws JavaModelException { IProject project = javaProject.getProject(); if (!project.isAccessible() || !visitedProjects.add(project)) return; IPath projectPath = project.getFullPath(); String projectPathString = projectPath.toString(); addEnclosingProjectOrJar(projectPath); IClasspathEntry[] entries = javaProject.getResolvedClasspath(); IJavaModel model = javaProject.getJavaModel(); JavaModelManager.PerProjectInfo perProjectInfo = javaProject.getPerProjectInfo(); for (int i = 0, length = entries.length; i < length; i++) { IClasspathEntry entry = entries[i]; if (this.excludeTestCode && entry.isTest()) { continue; } AccessRuleSet access = null; ClasspathEntry cpEntry = (ClasspathEntry) entry; if (referringEntry != null) { // Add only exported entries. // Source folder are implicitly exported. if (!entry.isExported() && entry.getEntryKind() != IClasspathEntry.CPE_SOURCE) { continue; } cpEntry = cpEntry.combineWith((ClasspathEntry)referringEntry); // cpEntry = ((ClasspathEntry)referringEntry).combineWith(cpEntry); } access = cpEntry.getAccessRuleSet(); switch (entry.getEntryKind()) { case IClasspathEntry.CPE_LIBRARY: IClasspathEntry rawEntry = null; Map rootPathToRawEntries = perProjectInfo.rootPathToRawEntries; if (rootPathToRawEntries != null) { rawEntry = (IClasspathEntry) rootPathToRawEntries.get(entry.getPath()); } if (rawEntry == null) break; rawKind: switch (rawEntry.getEntryKind()) { case IClasspathEntry.CPE_LIBRARY: case IClasspathEntry.CPE_VARIABLE: if ((includeMask & APPLICATION_LIBRARIES) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { Object target = JavaModel.getTarget(path, false/*don't check existence*/); if (target instanceof IFolder) // case of an external folder path = ((IFolder) target).getFullPath(); String pathToString = path.getDevice() == null ? path.toString() : path.toOSString(); add(projectPath.toString(), "", pathToString, false/*not a package*/, access); //$NON-NLS-1$ addEnclosingProjectOrJar(entry.getPath()); } } break; case IClasspathEntry.CPE_CONTAINER: IClasspathContainer container = JavaCore.getClasspathContainer(rawEntry.getPath(), javaProject); if (container == null) break; switch (container.getKind()) { case IClasspathContainer.K_APPLICATION: if ((includeMask & APPLICATION_LIBRARIES) == 0) break rawKind; break; case IClasspathContainer.K_SYSTEM: case IClasspathContainer.K_DEFAULT_SYSTEM: if ((includeMask & SYSTEM_LIBRARIES) == 0) break rawKind; break; default: break rawKind; } IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { Object target = JavaModel.getTarget(path, false/*don't check existence*/); if (target instanceof IFolder) // case of an external folder path = ((IFolder) target).getFullPath(); String pathToString = path.getDevice() == null ? path.toString() : path.toOSString(); add(projectPath.toString(), "", pathToString, false/*not a package*/, access); //$NON-NLS-1$ addEnclosingProjectOrJar(entry.getPath()); } break; } break; case IClasspathEntry.CPE_PROJECT: if ((includeMask & REFERENCED_PROJECTS) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { JavaProject referencedProject = (JavaProject) model.getJavaProject(path.lastSegment()); if (!projectsToBeAdded.contains(referencedProject)) { // do not recurse if depending project was used to create the scope add(referencedProject, null, includeMask, projectsToBeAdded, visitedProjects, cpEntry); } } } break; case IClasspathEntry.CPE_SOURCE: if ((includeMask & SOURCES) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { add(projectPath.toString(), Util.relativePath(path,1/*remove project segment*/), projectPathString, false/*not a package*/, access); } } break; } } }
Add an element to the java search scope.
Params:
  • element – The element we want to add to current java search scope
Throws:
/** * Add an element to the java search scope. * @param element The element we want to add to current java search scope * @throws JavaModelException May happen if some Java Model info are not available */
public void add(IJavaElement element) throws JavaModelException { IPath containerPath = null; String containerPathToString = null; PackageFragmentRoot root = null; int includeMask = SOURCES | APPLICATION_LIBRARIES | SYSTEM_LIBRARIES; switch (element.getElementType()) { case IJavaElement.JAVA_MODEL: // a workspace sope should be used break; case IJavaElement.JAVA_PROJECT: add((JavaProject)element, null, includeMask, new HashSet(2), new HashSet(2), null); break; case IJavaElement.PACKAGE_FRAGMENT_ROOT: root = (PackageFragmentRoot)element; IPath rootPath = root.internalPath(); containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : rootPath; containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); IResource rootResource = root.resource(); String projectPath = root.getJavaProject().getPath().toString(); if (rootResource != null && rootResource.isAccessible()) { String relativePath = Util.relativePath(rootResource.getFullPath(), containerPath.segmentCount()); add(projectPath, relativePath, containerPathToString, false/*not a package*/, null); } else { add(projectPath, "", containerPathToString, false/*not a package*/, null); //$NON-NLS-1$ } break; case IJavaElement.PACKAGE_FRAGMENT: root = (PackageFragmentRoot)element.getParent(); projectPath = root.getJavaProject().getPath().toString(); if (root.isArchive()) { String relativePath = Util.concatWith(((PackageFragment) element).names, '/'); containerPath = root.getPath(); containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); add(projectPath, relativePath, containerPathToString, true/*package*/, null); } else { IResource resource = ((JavaElement) element).resource(); if (resource != null) { if (resource.isAccessible()) { containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.internalPath(); } else { // for working copies, get resource container full path containerPath = resource.getParent().getFullPath(); } containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); String relativePath = Util.relativePath(resource.getFullPath(), containerPath.segmentCount()); add(projectPath, relativePath, containerPathToString, true/*package*/, null); } } break; default: // remember sub-cu (or sub-class file) java elements if (element instanceof IMember) { if (this.elements == null) { this.elements = new ArrayList(); } this.elements.add(element); } root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); projectPath = root.getJavaProject().getPath().toString(); String relativePath; if (root.getKind() == IPackageFragmentRoot.K_SOURCE) { containerPath = root.getParent().getPath(); relativePath = Util.relativePath(getPath(element, false/*full path*/), 1/*remove project segment*/); } else { containerPath = root.internalPath(); relativePath = getPath(element, true/*relative path*/).toString(); } containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); add(projectPath, relativePath, containerPathToString, false/*not a package*/, null); } if (root != null) addEnclosingProjectOrJar(root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.getPath()); }
Adds the given path to this search scope. Remember if subfolders need to be included and associated access restriction as well.
/** * Adds the given path to this search scope. Remember if subfolders need to be included * and associated access restriction as well. */
private void add(String projectPath, String relativePath, String containerPath, boolean isPackage, AccessRuleSet access) { // normalize containerPath and relativePath containerPath = normalize(containerPath); relativePath = normalize(relativePath); int length = this.containerPaths.length, index = (containerPath.hashCode()& 0x7FFFFFFF) % length; String currentRelativePath, currentContainerPath; while ((currentRelativePath = this.relativePaths[index]) != null && (currentContainerPath = this.containerPaths[index]) != null) { if (currentRelativePath.equals(relativePath) && currentContainerPath.equals(containerPath)) return; if (++index == length) { index = 0; } } int idx = this.projectPaths.indexOf(projectPath); if (idx == -1) { // store project in separated list to minimize memory footprint this.projectPaths.add(projectPath); idx = this.projectPaths.indexOf(projectPath); } this.projectIndexes[index] = idx; this.relativePaths[index] = relativePath; this.containerPaths[index] = containerPath; this.isPkgPath[index] = isPackage; if (this.pathRestrictions != null) this.pathRestrictions[index] = access; else if (access != null) { this.pathRestrictions = new AccessRuleSet[this.relativePaths.length]; this.pathRestrictions[index] = access; } // assumes the threshold is never equal to the size of the table if (++this.pathsCount > this.threshold) rehash(); } /* * E.g. * * 1. /P/src/pkg/X.java * 2. /P/src/pkg * 3. /P/lib.jar|org/eclipse/jdt/core/IJavaElement.class * 4. /home/mylib.jar|x/y/z/X.class * 5. c:\temp\mylib.jar|x/y/Y.class * * @see IJavaSearchScope#encloses(String) */ @Override public boolean encloses(String resourcePathString) { int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR); if (separatorIndex != -1) { // internal or external jar (case 3, 4, or 5) String jarPath = resourcePathString.substring(0, separatorIndex); String relativePath = resourcePathString.substring(separatorIndex+1); return indexOf(jarPath, relativePath) >= 0; } // resource in workspace (case 1 or 2) return indexOf(resourcePathString) >= 0; }
Returns paths list index of given path or -1 if not found. NOTE: Use indexOf(String, String) for path inside jars
Params:
  • fullPath – the full path of the resource, e.g. 1. /P/src/pkg/X.java 2. /P/src/pkg
/** * Returns paths list index of given path or -1 if not found. * NOTE: Use indexOf(String, String) for path inside jars * * @param fullPath the full path of the resource, e.g. * 1. /P/src/pkg/X.java * 2. /P/src/pkg */
private int indexOf(String fullPath) { // cannot guess the index of the container path // fallback to sequentially looking at all known paths for (int i = 0, length = this.relativePaths.length; i < length; i++) { String currentRelativePath = this.relativePaths[i]; if (currentRelativePath == null) continue; String currentContainerPath = this.containerPaths[i]; String currentFullPath = currentRelativePath.length() == 0 ? currentContainerPath : (currentContainerPath + '/' + currentRelativePath); if (encloses(currentFullPath, fullPath, i)) return i; } return -1; }
Returns paths list index of given path or -1 if not found.
Params:
  • containerPath – the path of the container, e.g. 1. /P/src 2. /P 3. /P/lib.jar 4. /home/mylib.jar 5. c:\temp\mylib.jar
  • relativePath – the forward slash path relatively to the container, e.g. 1. x/y/Z.class 2. x/y 3. X.java 4. (empty)
/** * Returns paths list index of given path or -1 if not found. * @param containerPath the path of the container, e.g. * 1. /P/src * 2. /P * 3. /P/lib.jar * 4. /home/mylib.jar * 5. c:\temp\mylib.jar * @param relativePath the forward slash path relatively to the container, e.g. * 1. x/y/Z.class * 2. x/y * 3. X.java * 4. (empty) */
private int indexOf(String containerPath, String relativePath) { // use the hash to get faster comparison int length = this.containerPaths.length, index = (containerPath.hashCode()& 0x7FFFFFFF) % length; String currentContainerPath; while ((currentContainerPath = this.containerPaths[index]) != null) { if (currentContainerPath.equals(containerPath)) { String currentRelativePath = this.relativePaths[index]; if (encloses(currentRelativePath, relativePath, index)) return index; } if (++index == length) { index = 0; } } return -1; } /* * Returns whether the enclosing path encloses the given path (or is equal to it) */ private boolean encloses(String enclosingPath, String path, int index) { // normalize given path as it can come from outside path = normalize(path); int pathLength = path.length(); int enclosingLength = enclosingPath.length(); if (pathLength < enclosingLength) { return false; } if (enclosingLength == 0) { return true; } if (pathLength == enclosingLength) { return path.equals(enclosingPath); } if (!this.isPkgPath[index]) { return path.startsWith(enclosingPath) && path.charAt(enclosingLength) == '/'; } else { // if looking at a package, this scope encloses the given path // if the given path is a direct child of the folder // or if the given path path is the folder path (see bug 13919 Declaration for package not found if scope is not project) if (path.startsWith(enclosingPath) && ((enclosingPath.length() == path.lastIndexOf('/')) || (enclosingPath.length() == path.length()))) { return true; } } return false; } @Override public boolean encloses(IJavaElement element) { if (this.elements != null) { for (int i = 0, length = this.elements.size(); i < length; i++) { IJavaElement scopeElement = (IJavaElement)this.elements.get(i); IJavaElement searchedElement = element; while (searchedElement != null) { if (searchedElement.equals(scopeElement)) return true; searchedElement = searchedElement.getParent(); } } return false; } IPackageFragmentRoot root = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); if (root != null && root.isArchive()) { // external or internal jar IPath rootPath = root.getPath(); String rootPathToString = rootPath.getDevice() == null ? rootPath.toString() : rootPath.toOSString(); IPath relativePath = getPath(element, true/*relative path*/); return indexOf(rootPathToString, relativePath.toString()) >= 0; } // resource in workspace String fullResourcePathString = getPath(element, false/*full path*/).toString(); return indexOf(fullResourcePathString) >= 0; } @Override public IPath[] enclosingProjectsAndJars() { return this.enclosingProjectsAndJars; } private IPath getPath(IJavaElement element, boolean relativeToRoot) { switch (element.getElementType()) { case IJavaElement.JAVA_MODEL: return Path.EMPTY; case IJavaElement.JAVA_PROJECT: return element.getPath(); case IJavaElement.PACKAGE_FRAGMENT_ROOT: if (relativeToRoot) return Path.EMPTY; return element.getPath(); case IJavaElement.PACKAGE_FRAGMENT: String relativePath = Util.concatWith(((PackageFragment) element).names, '/'); return getPath(element.getParent(), relativeToRoot).append(new Path(relativePath)); case IJavaElement.COMPILATION_UNIT: case IJavaElement.CLASS_FILE: return getPath(element.getParent(), relativeToRoot).append(new Path(element.getElementName())); default: return getPath(element.getParent(), relativeToRoot); } } @Override public AccessRuleSet getAccessRuleSet(String relativePath, String containerPath) { int index = indexOf(containerPath, relativePath); if (index == -1) { // this search scope does not enclose given path return NOT_ENCLOSED; } if (this.pathRestrictions == null) return null; return this.pathRestrictions[index]; } protected void initialize(int size) { this.pathsCount = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.75f); if (this.threshold == extraRoom) extraRoom++; this.relativePaths = new String[extraRoom]; this.containerPaths = new String[extraRoom]; this.projectPaths = new ArrayList(); this.projectIndexes = new int[extraRoom]; this.isPkgPath = new boolean[extraRoom]; this.pathRestrictions = null; // null to optimize case where no access rules are used this.enclosingProjectsAndJars = new IPath[0]; } /* * Removes trailing slashes from the given path */ private String normalize(String path) { int pathLength = path.length(); int index = pathLength-1; while (index >= 0 && path.charAt(index) == '/') index--; if (index != pathLength-1) return path.substring(0, index + 1); return path; } @Override public void processDelta(IJavaElementDelta delta, int eventType) { switch (delta.getKind()) { case IJavaElementDelta.CHANGED: IJavaElementDelta[] children = delta.getAffectedChildren(); for (int i = 0, length = children.length; i < length; i++) { IJavaElementDelta child = children[i]; processDelta(child, eventType); } break; case IJavaElementDelta.REMOVED: IJavaElement element = delta.getElement(); if (this.encloses(element)) { if (this.elements != null) { this.elements.remove(element); } String path = null; switch (element.getElementType()) { case IJavaElement.JAVA_PROJECT: path = ((IJavaProject)element).getProject().getFullPath().toString(); break; case IJavaElement.PACKAGE_FRAGMENT_ROOT: path = ((IPackageFragmentRoot)element).getPath().toString(); break; default: return; } for (int i = 0; i < this.pathsCount; i++) { if (this.relativePaths[i].equals(path)) { this.relativePaths[i] = null; rehash(); break; } } } break; } }
See Also:
  • packageFragmentRoot.packageFragmentRoot(String, int, String)
/** * @see AbstractJavaSearchScope#packageFragmentRoot(String, int, String) */
@Override public IPackageFragmentRoot packageFragmentRoot(String resourcePathString, int jarSeparatorIndex, String jarPath) { int index = -1; boolean isJarFile = jarSeparatorIndex != -1; if (isJarFile) { // internal or external jar (case 3, 4, or 5) String relativePath = resourcePathString.substring(jarSeparatorIndex+1); index = indexOf(jarPath, relativePath); } else { // resource in workspace (case 1 or 2) index = indexOf(resourcePathString); } if (index >= 0) { int idx = this.projectIndexes[index]; String projectPath = idx == -1 ? null : (String) this.projectPaths.get(idx); if (projectPath != null) { IJavaProject project =JavaCore.create(ResourcesPlugin.getWorkspace().getRoot().getProject(projectPath)); if (isJarFile) { IResource resource = JavaModel.getWorkspaceTarget(new Path(jarPath)); if (resource != null) return project.getPackageFragmentRoot(resource); return project.getPackageFragmentRoot(jarPath); } Object target = JavaModel.getWorkspaceTarget(new Path(this.containerPaths[index]+'/'+this.relativePaths[index])); if (target != null) { if (target instanceof IProject) { return project.getPackageFragmentRoot((IProject) target); } IJavaElement element = JavaModelManager.create((IResource) target, project); return (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); } } } return null; } private void rehash() { JavaSearchScope newScope = new JavaSearchScope(this.pathsCount * 2, this.excludeTestCode); // double the number of expected elements newScope.projectPaths.ensureCapacity(this.projectPaths.size()); String currentPath; for (int i=0, length=this.relativePaths.length; i<length; i++) if ((currentPath = this.relativePaths[i]) != null) { int idx = this.projectIndexes[i]; String projectPath = idx == -1 ? null : (String)this.projectPaths.get(idx); newScope.add(projectPath, currentPath, this.containerPaths[i], this.isPkgPath[i], this.pathRestrictions == null ? null : this.pathRestrictions[i]); } this.relativePaths = newScope.relativePaths; this.containerPaths = newScope.containerPaths; this.projectPaths = newScope.projectPaths; this.projectIndexes = newScope.projectIndexes; this.isPkgPath = newScope.isPkgPath; this.pathRestrictions = newScope.pathRestrictions; this.threshold = newScope.threshold; } @Override public String toString() { StringBuffer result = new StringBuffer("JavaSearchScope on "); //$NON-NLS-1$ if (this.elements != null) { result.append("["); //$NON-NLS-1$ for (int i = 0, length = this.elements.size(); i < length; i++) { JavaElement element = (JavaElement)this.elements.get(i); result.append("\n\t"); //$NON-NLS-1$ result.append(element.toStringWithAncestors()); } result.append("\n]"); //$NON-NLS-1$ } else { if (this.pathsCount == 0) { result.append("[empty scope]"); //$NON-NLS-1$ } else { result.append("["); //$NON-NLS-1$ String[] paths = new String[this.relativePaths.length]; int index = 0; for (int i = 0; i < this.relativePaths.length; i++) { String path = this.relativePaths[i]; if (path == null) continue; String containerPath; if (ExternalFoldersManager.isInternalPathForExternalFolder(new Path(this.containerPaths[i]))) { Object target = JavaModel.getWorkspaceTarget(new Path(this.containerPaths[i])); containerPath = ((IFolder) target).getLocation().toOSString(); } else { containerPath = this.containerPaths[i]; } if (path.length() > 0) { paths[index++] = containerPath + '/' + path; } else { paths[index++] = containerPath; } } System.arraycopy(paths, 0, paths = new String[index], 0, index); Util.sort(paths); for (int i = 0; i < index; i++) { result.append("\n\t"); //$NON-NLS-1$ result.append(paths[i]); } result.append("\n]"); //$NON-NLS-1$ } } return result.toString(); } }