Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java')
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java309
1 files changed, 169 insertions, 140 deletions
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
index b2ab4c68..b9f378eb 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
@@ -1,10 +1,10 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
+ * Copyright (c) 2000, 2005 IBM Corporation 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/cpl-v10.html
- *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
@@ -27,7 +27,7 @@ import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.JavaModelManager;
@@ -44,16 +44,22 @@ public class JavaSearchScope extends AbstractSearchScope {
/* The paths of the resources in this search scope
(or the classpath entries' paths
if the resources are projects) */
- private IPath[] paths;
+ private String[] paths;
private boolean[] pathWithSubFolders;
- private AccessRestriction[] pathRestrictions;
+ protected AccessRuleSet[] pathRestrictions;
+ private String[] containerPaths;
private int pathsCount;
+ private int threshold;
private IPath[] enclosingProjectsAndJars;
- public final static AccessRestriction UNINIT_RESTRICTION = new AccessRestriction(null, null, null, null);
+ public final static AccessRuleSet NOT_ENCLOSED = new AccessRuleSet(null);
public JavaSearchScope() {
- this.initialize();
+ this(5);
+}
+
+private JavaSearchScope(int size) {
+ initialize(size);
//disabled for now as this could be expensive
//JavaModelManager.getJavaModelManager().rememberScope(this);
@@ -95,7 +101,9 @@ void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visi
IProject project = javaProject.getProject();
if (!project.isAccessible() || !visitedProjects.add(project)) return;
- this.addEnclosingProjectOrJar(project.getFullPath());
+ IPath projectPath = project.getFullPath();
+ String projectPathString = projectPath.toString();
+ this.addEnclosingProjectOrJar(projectPath);
IClasspathEntry[] entries = javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
IJavaModel model = javaProject.getJavaModel();
@@ -107,16 +115,16 @@ void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visi
rawEntry = (IClasspathEntry) perProjectInfo.resolvedPathToRawEntries.get(entry.getPath());
}
if (rawEntry == null) continue;
- AccessRestriction access = null;
- ClasspathEntry cpEntry = null;
- if (rawEntry instanceof ClasspathEntry) {
- cpEntry = (ClasspathEntry) rawEntry;
- if (referringEntry != null) {
- cpEntry = cpEntry.combineWith(referringEntry);
+ AccessRuleSet access = null;
+ ClasspathEntry cpEntry = (ClasspathEntry) rawEntry;
+ 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.getImportRestriction();
}
+ access = cpEntry.getAccessRuleSet();
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY:
switch (rawEntry.getEntryKind()) {
@@ -125,7 +133,7 @@ void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visi
if ((includeMask & APPLICATION_LIBRARIES) != 0) {
IPath path = entry.getPath();
if (pathToAdd == null || pathToAdd.equals(path)) {
- add(path, true, access);
+ add("", path.toString(), true, access); //$NON-NLS-1$
addEnclosingProjectOrJar(path);
}
}
@@ -137,7 +145,7 @@ void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visi
|| (includeMask & SYSTEM_LIBRARIES) != 0) {
IPath path = entry.getPath();
if (pathToAdd == null || pathToAdd.equals(path)) {
- add(path, true, access);
+ add("", path.toString(), true, access); //$NON-NLS-1$
addEnclosingProjectOrJar(path);
}
}
@@ -156,7 +164,7 @@ void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visi
if ((includeMask & SOURCES) != 0) {
IPath path = entry.getPath();
if (pathToAdd == null || pathToAdd.equals(path)) {
- add(entry.getPath(), true, access);
+ add(Util.relativePath(path,1/*remove project segment*/), projectPathString, true, access);
}
}
break;
@@ -164,57 +172,38 @@ void add(JavaProject javaProject, IPath pathToAdd, int includeMask, HashSet visi
}
}
/**
- * Add an element to the java search scope. use element project to retrieve and
- * store access restriction corresponding to the provided element.
+ * 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 {
-// add(element, element.getJavaProject());
- add(element, null);
-}
-/**
- * Add an element to the java search scope. If project is not null, then use it to
- * retrieve and store access restriction corresponding to the provided element.
- * @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, IJavaProject project) throws JavaModelException {
- IPackageFragmentRoot root = null;
+ IPath containerPath = 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:
- if (project == null)
- add((JavaProject)element, null, includeMask, new HashSet(2), null);
- else
- add((JavaProject)project, element.getPath(), includeMask, new HashSet(2), null);
+ add((JavaProject)element, null, includeMask, new HashSet(2), null);
break;
case IJavaElement.PACKAGE_FRAGMENT_ROOT:
- root = (IPackageFragmentRoot)element;
- if (project == null)
- add(root.getPath(), true, null);
- else
- add((JavaProject)project, root.getPath(), includeMask, new HashSet(2), null);
+ IPackageFragmentRoot root = (IPackageFragmentRoot)element;
+ IPath rootPath = root.getPath();
+ containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : rootPath;
+ add("", containerPath.toString(), true, null); //$NON-NLS-1$
break;
case IJavaElement.PACKAGE_FRAGMENT:
root = (IPackageFragmentRoot)element.getParent();
if (root.isArchive()) {
String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
- IPath path = root.getPath().append(new Path(relativePath));
- if (project == null)
- add(path, false, null);
- else
- add((JavaProject)project, path, includeMask, new HashSet(2), null);
+ containerPath = root.getPath();
+ add(relativePath, containerPath.toString(), false, null);
} else {
IResource resource = element.getResource();
if (resource != null && resource.isAccessible()) {
- if (project == null)
- add(resource.getFullPath(), false, null);
- else
- add((JavaProject)project, resource.getFullPath(), includeMask, new HashSet(2), null);
+ containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.getPath();
+ String relativePath = Util.relativePath(resource.getFullPath(), containerPath.segmentCount());
+ add(relativePath, containerPath.toString(), false, null);
}
}
break;
@@ -226,100 +215,108 @@ public void add(IJavaElement element, IJavaProject project) throws JavaModelExce
}
this.elements.add(element);
}
- this.add(this.fullPath(element), true, null);
-
- // find package fragment root including this java element
- IJavaElement parent = element.getParent();
- while (parent != null && !(parent instanceof IPackageFragmentRoot)) {
- parent = parent.getParent();
- }
- if (parent instanceof IPackageFragmentRoot) {
- root = (IPackageFragmentRoot)parent;
+ root = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ String relativePath;
+ if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+ containerPath = root.getParent().getPath();
+ relativePath = Util.relativePath(getPath(element, false/*full path*/), 1/*remove project segmet*/);
+ } else {
+ containerPath = root.getPath();
+ relativePath = getPath(element, true/*relative path*/).toString();
}
+ add(relativePath, containerPath.toString(), true, null);
}
- if (root != null) {
- if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
- this.addEnclosingProjectOrJar(root.getPath());
- } else {
- this.addEnclosingProjectOrJar(root.getJavaProject().getProject().getFullPath());
- }
- }
+ if (containerPath != null)
+ addEnclosingProjectOrJar(containerPath);
}
/**
* Adds the given path to this search scope. Remember if subfolders need to be included
* and associated access restriction as well.
*/
-private void add(IPath path, boolean withSubFolders, AccessRestriction access) {
- if (this.paths.length == this.pathsCount) {
- System.arraycopy(
- this.paths,
- 0,
- this.paths = new IPath[this.pathsCount * 2],
- 0,
- this.pathsCount);
- System.arraycopy(
- this.pathWithSubFolders,
- 0,
- this.pathWithSubFolders = new boolean[this.pathsCount * 2],
- 0,
- this.pathsCount);
- System.arraycopy(
- this.pathRestrictions,
- 0,
- this.pathRestrictions = new AccessRestriction[this.pathsCount * 2],
- 0,
- this.pathsCount);
+private void add(String relativePath, String containerPath, boolean withSubFolders, AccessRuleSet access) {
+ int index = (containerPath.hashCode() & 0x7FFFFFFF) % this.paths.length;
+ String currentPath, currentContainerPath;
+ while ((currentPath = this.paths[index]) != null && (currentContainerPath = this.containerPaths[index]) != null) {
+ if (currentPath.equals(relativePath) && currentContainerPath.equals(containerPath))
+ return;
+ index = (index + 1) % this.paths.length;
+ }
+ this.paths[index] = relativePath;
+ this.containerPaths[index] = containerPath;
+ this.pathWithSubFolders[index] = withSubFolders;
+ if (this.pathRestrictions != null)
+ this.pathRestrictions[index] = access;
+ else if (access != null) {
+ this.pathRestrictions = new AccessRuleSet[this.paths.length];
+ this.pathRestrictions[index] = access;
}
- this.paths[this.pathsCount] = path;
- this.pathWithSubFolders[this.pathsCount] = withSubFolders;
- this.pathRestrictions[this.pathsCount++] = access;
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.pathsCount > this.threshold)
+ rehash();
+
}
/* (non-Javadoc)
* @see IJavaSearchScope#encloses(String)
*/
public boolean encloses(String resourcePathString) {
- return this.encloses(fullPath(resourcePathString)) >= 0;
-}
-private IPath fullPath(String resourcePathString) {
- IPath resourcePath;
int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR);
if (separatorIndex != -1) {
- resourcePath =
- new Path(resourcePathString.substring(0, separatorIndex)).
- append(new Path(resourcePathString.substring(separatorIndex+1)));
- } else {
- resourcePath = new Path(resourcePathString);
+ return indexOf(resourcePathString.substring(separatorIndex+1), resourcePathString.substring(0, separatorIndex)) >= 0;
}
- return resourcePath;
+ return indexOf(resourcePathString, null) >= 0;
}
/**
* Returns paths list index of given path or -1 if not found.
*/
-private int encloses(IPath path) {
- for (int i = 0; i < this.pathsCount; i++) {
- if (this.pathWithSubFolders[i]) {
- if (this.paths[i].isPrefixOf(path)) {
- return i;
- }
- } else {
- // if not looking at subfolders, this scope encloses the given path
- // if this path is a direct child of the scope's ressource
- // or if this path is the scope's resource (see bug 13919 Declaration for package not found if scope is not project)
- IPath scopePath = this.paths[i];
- if (scopePath.isPrefixOf(path)
- && ((scopePath.segmentCount() == path.segmentCount() - 1)
- || (scopePath.segmentCount() == path.segmentCount()))) {
- return i;
+private int indexOf(String relativePath, String containerPath) {
+ if (containerPath != null) {
+ // if container path is known, use the hash to get faster comparison
+ int index = (containerPath.hashCode()& 0x7FFFFFFF) % this.paths.length;
+ String currentContainerPath;
+ while ((currentContainerPath = this.containerPaths[index]) != null) {
+ if (currentContainerPath.equals(containerPath)) {
+ String scopePath = this.paths[index];
+ if (encloses(scopePath, relativePath, index))
+ return index;
}
+ index = (index + 1) % this.paths.length;
}
+ return -1;
+ }
+
+ // fallback to sequentially looking at all known paths
+ for (int i = 0, length = this.paths.length; i < length; i++) {
+ String scopePath = this.paths[i];
+ if (scopePath == null) continue;
+ if (encloses(this.containerPaths[i] + '/' + scopePath, relativePath, i))
+ return i;
}
return -1;
}
+private boolean encloses(String scopePath, String path, int index) {
+ if (this.pathWithSubFolders[index]) {
+ if (path.startsWith(scopePath)) {
+ return true;
+ }
+ } else {
+ // if not looking at subfolders, this scope encloses the given path
+ // if this path is a direct child of the scope's ressource
+ // or if this path is the scope's resource (see bug 13919 Declaration for package not found if scope is not project)
+ if (path.startsWith(scopePath)
+ && ((scopePath.length() == path.lastIndexOf('/'))
+ || (scopePath.length() == path.length()))) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* (non-Javadoc)
* @see IJavaSearchScope#encloses(IJavaElement)
*/
@@ -336,7 +333,13 @@ public boolean encloses(IJavaElement element) {
}
return false;
}
- return this.encloses(this.fullPath(element)) >= 0;
+ IPackageFragmentRoot root = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ if (root != null && root.isArchive()) {
+ IPath rootPath = root.getPath();
+ IPath relativePath = getPath(element, true/*relative path*/);
+ return indexOf(relativePath.toString(), rootPath.toString()) >= 0;
+ }
+ return this.indexOf(getPath(element, false/*full path*/).toString(), null) >= 0;
}
/* (non-Javadoc)
@@ -345,12 +348,14 @@ public boolean encloses(IJavaElement element) {
public IPath[] enclosingProjectsAndJars() {
return this.enclosingProjectsAndJars;
}
-private IPath fullPath(IJavaElement element) {
+private IPath getPath(IJavaElement element, boolean relativeToRoot) {
if (element instanceof IPackageFragmentRoot) {
+ if (relativeToRoot)
+ return Path.EMPTY;
return ((IPackageFragmentRoot)element).getPath();
}
IJavaElement parent = element.getParent();
- IPath parentPath = parent == null ? null : this.fullPath(parent);
+ IPath parentPath = parent == null ? null : getPath(parent, relativeToRoot);
IPath childPath;
if (element instanceof PackageFragment) {
String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
@@ -364,25 +369,33 @@ private IPath fullPath(IJavaElement element) {
}
/**
- * Get access restriction corresponding to a given path.
- * @param path The path user want to have restriction access
- * @return The access restriction for given path or null if none is set for it.
- * Returns specific uninit restriction when scope does not enclose the given path.
+ * Get access rule set corresponding to a given path.
+ * @param relativePath The path user want to have restriction access
+ * @return The access rule set for given path or null if none is set for it.
+ * Returns specific uninit access rule set when scope does not enclose the given path.
*/
-public AccessRestriction getAccessRestriction(String path) {
- int index = encloses(fullPath(path));
+public AccessRuleSet getAccessRuleSet(String relativePath, String containerPath) {
+ int index = indexOf(relativePath, containerPath);
if (index == -1) {
// this search scope does not enclose given path
- return UNINIT_RESTRICTION;
+ return NOT_ENCLOSED;
}
+ if (this.pathRestrictions == null)
+ return null;
return this.pathRestrictions[index];
}
-protected void initialize() {
- this.paths = new IPath[1];
- this.pathWithSubFolders = new boolean[1];
- this.pathRestrictions = new AccessRestriction[1];
+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.paths = new String[extraRoom];
+ this.containerPaths = new String[extraRoom];
+ this.pathWithSubFolders = new boolean[extraRoom];
+ this.pathRestrictions = null; // null to optimize case where no access rules are used
+
this.enclosingProjectsAndJars = new IPath[0];
}
/*
@@ -419,18 +432,29 @@ public void processDelta(IJavaElementDelta delta) {
}
}
if (toRemove != -1) {
- int last = this.pathsCount-1;
- if (toRemove != last) {
- this.paths[toRemove] = this.paths[last];
- this.pathWithSubFolders[toRemove] = this.pathWithSubFolders[last];
- }
- this.pathsCount--;
+ this.paths[toRemove] = null;
+ rehash();
}
}
}
break;
}
}
+
+private void rehash() {
+ JavaSearchScope newScope = new JavaSearchScope(this.pathsCount * 2); // double the number of expected elements
+ String currentPath;
+ for (int i = this.paths.length; --i >= 0;)
+ if ((currentPath = this.paths[i]) != null)
+ newScope.add(currentPath, this.containerPaths[i], this.pathWithSubFolders[i], this.pathRestrictions == null ? null : this.pathRestrictions[i]);
+
+ this.paths = newScope.paths;
+ this.containerPaths = newScope.containerPaths;
+ this.pathWithSubFolders = newScope.pathWithSubFolders;
+ this.pathRestrictions = newScope.pathRestrictions;
+ this.threshold = newScope.threshold;
+}
+
public String toString() {
StringBuffer result = new StringBuffer("JavaSearchScope on "); //$NON-NLS-1$
if (this.elements != null) {
@@ -446,10 +470,15 @@ public String toString() {
result.append("[empty scope]"); //$NON-NLS-1$
} else {
result.append("["); //$NON-NLS-1$
- for (int i = 0; i < this.pathsCount; i++) {
- IPath path = this.paths[i];
+ for (int i = 0; i < this.paths.length; i++) {
+ String path = this.paths[i];
+ if (path == null) continue;
result.append("\n\t"); //$NON-NLS-1$
- result.append(path.toString());
+ result.append(this.containerPaths[i]);
+ if (path.length() > 0) {
+ result.append('/');
+ result.append(path);
+ }
}
result.append("\n]"); //$NON-NLS-1$
}

Back to the top