View | Details | Raw Unified | Return to bug 182930 | Differences between
and this patch

Collapse All | Expand All

(-)model/org/eclipse/jdt/internal/core/JavaProject.java (+5 lines)
Lines 66-71 Link Here
66
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
66
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
67
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
67
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
68
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
68
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
69
import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
69
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
70
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
70
import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper;
71
import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper;
71
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
72
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
Lines 1809-1814 Link Here
1809
	public IProject getProject() {
1810
	public IProject getProject() {
1810
		return this.project;
1811
		return this.project;
1811
	}
1812
	}
1813
	
1814
	public ProjectCache getProjectCache() throws JavaModelException {
1815
		return ((JavaProjectElementInfo) getElementInfo()).getProjectCache(this);
1816
	}
1812
1817
1813
	/**
1818
	/**
1814
	 * @see IJavaProject
1819
	 * @see IJavaProject
(-)model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java (-46 / +96 lines)
Lines 18-23 Link Here
18
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.IPath;
19
import org.eclipse.core.runtime.IPath;
20
import org.eclipse.jdt.core.*;
20
import org.eclipse.jdt.core.*;
21
import org.eclipse.jdt.internal.core.util.HashSetOfArray;
21
import org.eclipse.jdt.internal.core.util.Util;
22
import org.eclipse.jdt.internal.core.util.Util;
22
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
23
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
23
24
Lines 37-46 Link Here
37
	static final IPackageFragmentRoot[] NO_ROOTS = new IPackageFragmentRoot[0];
38
	static final IPackageFragmentRoot[] NO_ROOTS = new IPackageFragmentRoot[0];
38
39
39
	static class ProjectCache {
40
	static class ProjectCache {
40
		ProjectCache(IPackageFragmentRoot[] allPkgFragmentRootsCache, HashtableOfArrayToObject allPkgFragmentsCache, Map rootToResolvedEntries) {
41
		ProjectCache(IPackageFragmentRoot[] allPkgFragmentRootsCache, Map rootToResolvedEntries, Map pkgFragmentsCaches) {
41
			this.allPkgFragmentRootsCache = allPkgFragmentRootsCache;
42
			this.allPkgFragmentRootsCache = allPkgFragmentRootsCache;
42
			this.allPkgFragmentsCache = allPkgFragmentsCache;
43
			this.rootToResolvedEntries = rootToResolvedEntries;
43
			this.rootToResolvedEntries = rootToResolvedEntries;
44
			this.pkgFragmentsCaches = pkgFragmentsCaches;
44
		}
45
		}
45
		
46
		
46
		/*
47
		/*
Lines 50-59 Link Here
50
		
51
		
51
		/*
52
		/*
52
		 * A cache of all package fragments in this project.
53
		 * A cache of all package fragments in this project.
53
		 * (a map from String[] (the package name) to IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name)
54
		 * (a map from String[] (the package name) to IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name))
54
		 */
55
		 */
55
		public HashtableOfArrayToObject allPkgFragmentsCache;
56
		public HashtableOfArrayToObject allPkgFragmentsCache;
56
		
57
		
58
		/*
59
		 * A cache of package fragments for each package fragment root of this project
60
		 * (a map from IPackageFragmentRoot to a set of String[] (the package name))
61
		 */
62
		public Map pkgFragmentsCaches;
63
		
57
		public Map rootToResolvedEntries;		
64
		public Map rootToResolvedEntries;		
58
	}
65
	}
59
	
66
	
Lines 68-79 Link Here
68
	 * Adds the given name and its super names to the given set
75
	 * Adds the given name and its super names to the given set
69
	 * (e.g. for {"a", "b", "c"}, adds {"a", "b", "c"}, {"a", "b"}, and {"a"})
76
	 * (e.g. for {"a", "b", "c"}, adds {"a", "b", "c"}, {"a", "b"}, and {"a"})
70
	 */
77
	 */
71
	public static void addSuperPackageNames(String[] pkgName, HashtableOfArrayToObject packageFragments) {
78
	static void addSuperPackageNames(String[] pkgName, HashtableOfArrayToObject packageFragments) {
72
		int length = pkgName.length;
79
		for (int i = pkgName.length-1; i > 0; i--) {
73
		for (int i = length-1; i > 0; i--) {
80
			if (packageFragments.getKey(pkgName, i) == null) {
74
			System.arraycopy(pkgName, 0, pkgName = new String[i], 0, i);
81
				System.arraycopy(pkgName, 0, pkgName = new String[i], 0, i);
75
			if (packageFragments.get(pkgName) == null)
76
				packageFragments.put(pkgName, NO_ROOTS);
82
				packageFragments.put(pkgName, NO_ROOTS);
83
			}
77
		}
84
		}
78
	}
85
	}
79
	
86
	
Lines 202-248 Link Here
202
				reverseMap.clear();
209
				reverseMap.clear();
203
			}
210
			}
204
			
211
			
205
			HashMap otherRoots = JavaModelManager.getJavaModelManager().deltaState.otherRoots;
212
			HashMap rootInfos = JavaModelManager.getJavaModelManager().deltaState.roots;
206
			HashtableOfArrayToObject fragmentsCache = new HashtableOfArrayToObject();
213
			HashMap pkgFragmentsCaches = new HashMap();
207
			for (int i = 0, length = roots.length; i < length; i++) {
214
			int length = roots.length;
215
			for (int i = 0; i < length; i++) {
208
				IPackageFragmentRoot root = roots[i];
216
				IPackageFragmentRoot root = roots[i];
209
				IJavaElement[] frags = null;
217
				DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo) rootInfos.get(root.getPath());
210
				try {
218
				if (rootInfo == null || rootInfo.project.equals(project)) {
211
					if (root.isArchive() 
219
					// compute fragment cache
212
							&& !root.isOpen() 
220
					HashSetOfArray fragmentsCache = new HashSetOfArray();
213
							&& otherRoots.get(((JarPackageFragmentRoot) root).jarPath) == null/*only if jar belongs to 1 project (https://bugs.eclipse.org/bugs/show_bug.cgi?id=161175)*/) {
221
					initializePackageNames(root, fragmentsCache);
214
						JarPackageFragmentRootInfo info = new JarPackageFragmentRootInfo();
222
					pkgFragmentsCaches.put(root, fragmentsCache);
215
						((JarPackageFragmentRoot) root).computeChildren(info, new HashMap());
216
						frags = info.children;
217
					} else 
218
						frags = root.getChildren();
219
				} catch (JavaModelException e) {
220
					// root doesn't exist: ignore
221
					continue;
222
				}
223
				for (int j = 0, length2 = frags.length; j < length2; j++) {
224
					PackageFragment fragment= (PackageFragment) frags[j];
225
					String[] pkgName = fragment.names;
226
					Object existing = fragmentsCache.get(pkgName);
227
					if (existing == null || existing == NO_ROOTS) {
228
						fragmentsCache.put(pkgName, root);
229
						// ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
230
						// are also in the map
231
						addSuperPackageNames(pkgName, fragmentsCache);
232
					} else {
233
						if (existing instanceof PackageFragmentRoot) {
234
							fragmentsCache.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
235
						} else {
236
							IPackageFragmentRoot[] entry= (IPackageFragmentRoot[]) existing;
237
							IPackageFragmentRoot[] copy= new IPackageFragmentRoot[entry.length + 1];
238
							System.arraycopy(entry, 0, copy, 0, entry.length);
239
							copy[entry.length]= root;
240
							fragmentsCache.put(pkgName, copy);
241
						}
242
					}
243
				}
223
				}
244
			}
224
			}
245
			cache = new ProjectCache(roots, fragmentsCache, reverseMap);
225
			
226
			cache = new ProjectCache(roots, reverseMap, pkgFragmentsCaches);
246
			this.projectCache = cache;
227
			this.projectCache = cache;
247
		}
228
		}
248
		return cache;
229
		return cache;
Lines 258-263 Link Here
258
		}
239
		}
259
		return this.nonJavaResources;
240
		return this.nonJavaResources;
260
	}
241
	}
242
	
243
	private void initializePackageNames(IPackageFragmentRoot root, HashSetOfArray fragmentsCache) {
244
		IJavaElement[] frags = null;
245
		try {
246
			if (!root.isOpen()) {
247
				PackageFragmentRootInfo info = root.isArchive() ? new JarPackageFragmentRootInfo() : new PackageFragmentRootInfo();
248
				((PackageFragmentRoot) root).computeChildren(info, new HashMap());
249
				frags = info.children;
250
			} else 
251
				frags = root.getChildren();
252
		} catch (JavaModelException e) {
253
			// root doesn't exist: ignore
254
			return;
255
		}
256
		for (int j = 0, length2 = frags.length; j < length2; j++) {
257
			fragmentsCache.add(((PackageFragment) frags[j]).names);
258
		}
259
	}
261
260
262
	/*
261
	/*
263
	 * Returns whether the given path is a classpath entry or an output location.
262
	 * Returns whether the given path is a classpath entry or an output location.
Lines 284-289 Link Here
284
	 */
283
	 */
285
	NameLookup newNameLookup(JavaProject project, ICompilationUnit[] workingCopies) {
284
	NameLookup newNameLookup(JavaProject project, ICompilationUnit[] workingCopies) {
286
		ProjectCache cache = getProjectCache(project);
285
		ProjectCache cache = getProjectCache(project);
286
		HashtableOfArrayToObject allPkgFragmentsCache = cache.allPkgFragmentsCache;
287
		if (allPkgFragmentsCache == null) {
288
			HashMap rootInfos = JavaModelManager.getJavaModelManager().deltaState.roots;
289
			IPackageFragmentRoot[] allRoots = cache.allPkgFragmentRootsCache;
290
			int length = allRoots.length;
291
			allPkgFragmentsCache = new HashtableOfArrayToObject();
292
			for (int i = 0; i < length; i++) {
293
				IPackageFragmentRoot root = allRoots[i];
294
				DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo) rootInfos.get(root.getPath());
295
				JavaProject rootProject = rootInfo == null ? project : rootInfo.project;
296
				HashSetOfArray fragmentsCache;
297
				if (rootProject.equals(project)) {
298
					// retrieve package fragments cache from this project
299
					fragmentsCache = (HashSetOfArray) cache.pkgFragmentsCaches.get(root);
300
				} else {
301
					// retrieve package fragments  cache from the root's project
302
					ProjectCache rootProjectCache;
303
					try {
304
						rootProjectCache = rootProject.getProjectCache();
305
					} catch (JavaModelException e) {
306
						// project doesn't exit
307
						continue;
308
					}
309
					fragmentsCache = (HashSetOfArray) rootProjectCache.pkgFragmentsCaches.get(root);
310
				}
311
				Object[][] set = fragmentsCache.set;
312
				for (int j = 0, length2 = set.length; j < length2; j++) {
313
					String[] pkgName = (String[]) set[j];
314
					if (pkgName == null)
315
						continue;
316
					Object existing = allPkgFragmentsCache.get(pkgName);
317
					if (existing == null || existing == NO_ROOTS) {
318
						allPkgFragmentsCache.put(pkgName, root);
319
						// ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
320
						// are also in the map
321
						addSuperPackageNames(pkgName, allPkgFragmentsCache);
322
					} else {
323
						if (existing instanceof PackageFragmentRoot) {
324
							allPkgFragmentsCache.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
325
						} else {
326
							IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) existing;
327
							int rootLength = roots.length;
328
							System.arraycopy(roots, 0, roots = new IPackageFragmentRoot[rootLength+1], 0, rootLength);
329
							roots[rootLength] = root;
330
							allPkgFragmentsCache.put(pkgName, roots);
331
						}
332
					}
333
				}
334
			}
335
			cache.allPkgFragmentsCache = allPkgFragmentsCache;
336
		}
287
		return new NameLookup(cache.allPkgFragmentRootsCache, cache.allPkgFragmentsCache, workingCopies, cache.rootToResolvedEntries);
337
		return new NameLookup(cache.allPkgFragmentRootsCache, cache.allPkgFragmentsCache, workingCopies, cache.rootToResolvedEntries);
288
	}
338
	}
289
	
339
	
(-)model/org/eclipse/jdt/internal/core/util/HashSetOfArray.java (+149 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core.util;
12
13
/**
14
 * HashSet of Object[]
15
 */
16
public final class HashSetOfArray implements Cloneable {
17
	
18
	// to avoid using Enumerations, walk the individual tables skipping nulls
19
	public Object[][] set;
20
21
	public int elementSize; // number of elements in the table
22
	int threshold;
23
24
	public HashSetOfArray() {
25
		this(13);
26
	}
27
28
	public HashSetOfArray(int size) {
29
30
		this.elementSize = 0;
31
		this.threshold = size; // size represents the expected number of elements
32
		int extraRoom = (int) (size * 1.75f);
33
		if (this.threshold == extraRoom)
34
			extraRoom++;
35
		this.set = new Object[extraRoom][];
36
	}
37
38
	public Object clone() throws CloneNotSupportedException {
39
		HashSetOfArray result = (HashSetOfArray) super.clone();
40
		result.elementSize = this.elementSize;
41
		result.threshold = this.threshold;
42
43
		int length = this.set.length;
44
		result.set = new Object[length][];
45
		System.arraycopy(this.set, 0, result.set, 0, length);
46
47
		return result;
48
	}
49
50
	public boolean contains(Object[] array) {
51
		int length = this.set.length;
52
		int index = hashCode(array) % length;
53
		int arrayLength = array.length;
54
		Object[] currentArray;
55
		while ((currentArray = this.set[index]) != null) {
56
			if (currentArray.length == arrayLength && Util.equalArraysOrNull(currentArray, array))
57
				return true;
58
			if (++index == length) {
59
				index = 0;
60
			}
61
		}
62
		return false;
63
	}
64
65
	private int hashCode(Object[] element) {
66
		return hashCode(element, element.length);
67
	}
68
	
69
	private int hashCode(Object[] element, int length) {
70
		int hash = 0;
71
		for (int i = length-1; i >= 0; i--)
72
			hash = Util.combineHashCodes(hash, element[i].hashCode());
73
		return hash & 0x7FFFFFFF;
74
	}
75
	
76
	public Object add(Object[] array) {
77
		int length = this.set.length;
78
		int index = hashCode(array) % length;
79
		int arrayLength = array.length;
80
		Object[] currentArray;
81
		while ((currentArray = this.set[index]) != null) {
82
			if (currentArray.length == arrayLength && Util.equalArraysOrNull(currentArray, array))
83
				return this.set[index] = array;
84
			if (++index == length) {
85
				index = 0;
86
			}
87
		}
88
		this.set[index] = array;
89
90
		// assumes the threshold is never equal to the size of the table
91
		if (++this.elementSize > threshold)
92
			rehash();
93
		return array;
94
	}
95
96
	public Object remove(Object[] array) {
97
		int length = this.set.length;
98
		int index = hashCode(array) % length;
99
		int arrayLength = array.length;
100
		Object[] currentArray;
101
		while ((currentArray = this.set[index]) != null) {
102
			if (currentArray.length == arrayLength && Util.equalArraysOrNull(currentArray, array)) {
103
				Object existing = this.set[index];
104
				this.elementSize--;
105
				this.set[index] = null;
106
				rehash();
107
				return existing;
108
			}
109
			if (++index == length) {
110
				index = 0;
111
			}
112
		}
113
		return null;
114
	}
115
116
	private void rehash() {
117
118
		HashSetOfArray newHashSet = new HashSetOfArray(elementSize * 2);		// double the number of expected elements
119
		Object[] currentArray;
120
		for (int i = this.set.length; --i >= 0;)
121
			if ((currentArray = this.set[i]) != null)
122
				newHashSet.add(currentArray);
123
124
		this.set = newHashSet.set;
125
		this.threshold = newHashSet.threshold;
126
	}
127
128
	public int size() {
129
		return elementSize;
130
	}
131
132
	public String toString() {
133
		StringBuffer buffer = new StringBuffer();
134
		Object[] element;
135
		for (int i = 0, length = this.set.length; i < length; i++)
136
			if ((element = this.set[i]) != null) {
137
				buffer.append('{');
138
				for (int j = 0, length2 = element.length; j < length2; j++) {
139
					buffer.append(element[j]);
140
					if (j != length2-1) 
141
						buffer.append(", "); //$NON-NLS-1$
142
				}
143
				buffer.append("}");  //$NON-NLS-1$
144
				if (i != length-1)
145
					buffer.append('\n');
146
			}
147
		return buffer.toString();
148
	}
149
}

Return to bug 182930