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

Collapse All | Expand All

(-)search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java (-99 / +156 lines)
Lines 24-30 Link Here
24
import org.eclipse.jdt.core.IJavaModel;
24
import org.eclipse.jdt.core.IJavaModel;
25
import org.eclipse.jdt.core.IJavaProject;
25
import org.eclipse.jdt.core.IJavaProject;
26
import org.eclipse.jdt.core.IMember;
26
import org.eclipse.jdt.core.IMember;
27
import org.eclipse.jdt.core.IOpenable;
28
import org.eclipse.jdt.core.IPackageFragmentRoot;
27
import org.eclipse.jdt.core.IPackageFragmentRoot;
29
import org.eclipse.jdt.core.JavaModelException;
28
import org.eclipse.jdt.core.JavaModelException;
30
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
29
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
Lines 42-53 Link Here
42
	private ArrayList elements;
41
	private ArrayList elements;
43
42
44
	/* The paths of the resources in this search scope 
43
	/* The paths of the resources in this search scope 
45
	   (or the classpath entries' paths 
44
	    (or the classpath entries' paths if the resources are projects) 
46
	   if the resources are projects) */
45
	*/
47
	private String[] paths;
46
	private String[] containerPaths; // path to the container (e.g. /P/src, /P/lib.jar, c:\temp\mylib.jar)
48
	private boolean[] pathWithSubFolders;
47
	private String[] relativePaths; // path relative to the container (e.g. x/y/Z.class, x/y, (empty))
48
	private boolean[] isPkgPath; // in the case of packages, matches must be direct children of the folder
49
	protected AccessRuleSet[] pathRestrictions;
49
	protected AccessRuleSet[] pathRestrictions;
50
	private String[] containerPaths;
51
	private int pathsCount;
50
	private int pathsCount;
52
	private int threshold;
51
	private int threshold;
53
	
52
	
Lines 134-140 Link Here
134
							IPath path = entry.getPath();
133
							IPath path = entry.getPath();
135
							if (pathToAdd == null || pathToAdd.equals(path)) {
134
							if (pathToAdd == null || pathToAdd.equals(path)) {
136
								String pathToString = path.getDevice() == null ? path.toString() : path.toOSString();
135
								String pathToString = path.getDevice() == null ? path.toString() : path.toOSString();
137
								add("", pathToString, true, access); //$NON-NLS-1$
136
								add("", pathToString, false/*not a package*/, access); //$NON-NLS-1$
138
								addEnclosingProjectOrJar(path);
137
								addEnclosingProjectOrJar(path);
139
							}
138
							}
140
						}
139
						}
Lines 147-153 Link Here
147
							IPath path = entry.getPath();
146
							IPath path = entry.getPath();
148
							if (pathToAdd == null || pathToAdd.equals(path)) {
147
							if (pathToAdd == null || pathToAdd.equals(path)) {
149
								String pathToString = path.getDevice() == null ? path.toString() : path.toOSString();
148
								String pathToString = path.getDevice() == null ? path.toString() : path.toOSString();
150
								add("", pathToString, true, access); //$NON-NLS-1$
149
								add("", pathToString, false/*not a package*/, access); //$NON-NLS-1$
151
								addEnclosingProjectOrJar(path);
150
								addEnclosingProjectOrJar(path);
152
							}
151
							}
153
						}
152
						}
Lines 166-172 Link Here
166
				if ((includeMask & SOURCES) != 0) {
165
				if ((includeMask & SOURCES) != 0) {
167
					IPath path = entry.getPath();
166
					IPath path = entry.getPath();
168
					if (pathToAdd == null || pathToAdd.equals(path)) {
167
					if (pathToAdd == null || pathToAdd.equals(path)) {
169
						add(Util.relativePath(path,1/*remove project segment*/), projectPathString, true, access);
168
						add(Util.relativePath(path,1/*remove project segment*/), projectPathString, false/*not a package*/, access);
170
					}
169
					}
171
				}
170
				}
172
				break;
171
				break;
Lines 197-205 Link Here
197
			IResource rootResource = root.getResource();
196
			IResource rootResource = root.getResource();
198
			if (rootResource != null && rootResource.isAccessible()) {
197
			if (rootResource != null && rootResource.isAccessible()) {
199
				String relativePath = Util.relativePath(rootResource.getFullPath(), containerPath.segmentCount());
198
				String relativePath = Util.relativePath(rootResource.getFullPath(), containerPath.segmentCount());
200
				add(relativePath, containerPathToString, true, null);
199
				add(relativePath, containerPathToString, false/*not a package*/, null);
201
			} else {
200
			} else {
202
				add("", containerPathToString, true, null); //$NON-NLS-1$
201
				add("", containerPathToString, false/*not a package*/, null); //$NON-NLS-1$
203
			}
202
			}
204
			break;
203
			break;
205
		case IJavaElement.PACKAGE_FRAGMENT:
204
		case IJavaElement.PACKAGE_FRAGMENT:
Lines 208-221 Link Here
208
				String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
207
				String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
209
				containerPath = root.getPath();
208
				containerPath = root.getPath();
210
				containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
209
				containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
211
				add(relativePath, containerPathToString, false, null);
210
				add(relativePath, containerPathToString, true/*package*/, null);
212
			} else {
211
			} else {
213
				IResource resource = element.getResource();
212
				IResource resource = element.getResource();
214
				if (resource != null && resource.isAccessible()) {
213
				if (resource != null && resource.isAccessible()) {
215
					containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.getPath();
214
					containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.getPath();
216
					containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
215
					containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
217
					String relativePath = Util.relativePath(resource.getFullPath(), containerPath.segmentCount());
216
					String relativePath = Util.relativePath(resource.getFullPath(), containerPath.segmentCount());
218
					add(relativePath, containerPathToString, false, null);
217
					add(relativePath, containerPathToString, true/*package*/, null);
219
				}
218
				}
220
			}
219
			}
221
			break;
220
			break;
Lines 237-243 Link Here
237
				relativePath = getPath(element, true/*relative path*/).toString();
236
				relativePath = getPath(element, true/*relative path*/).toString();
238
			}
237
			}
239
			containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
238
			containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString();
240
			add(relativePath, containerPathToString, true, null);
239
			add(relativePath, containerPathToString, false/*not a package*/, null);
241
	}
240
	}
242
	
241
	
243
	if (containerPath != null)
242
	if (containerPath != null)
Lines 248-342 Link Here
248
 * Adds the given path to this search scope. Remember if subfolders need to be included
247
 * Adds the given path to this search scope. Remember if subfolders need to be included
249
 * and associated access restriction as well.
248
 * and associated access restriction as well.
250
 */
249
 */
251
private void add(String relativePath, String containerPath, boolean withSubFolders, AccessRuleSet access) {
250
private void add(String relativePath, String containerPath, boolean isPackage, AccessRuleSet access) {
252
	int index = (containerPath.hashCode() & 0x7FFFFFFF) % this.paths.length;
251
	// normalize containerPath and relativePath
253
	String currentPath, currentContainerPath;
252
	containerPath = normalize(containerPath);
254
	while ((currentPath = this.paths[index]) != null && (currentContainerPath = this.containerPaths[index]) != null) {
253
	relativePath = normalize(relativePath);
255
		if (currentPath.equals(relativePath) && currentContainerPath.equals(containerPath))
254
255
	int index = (containerPath.hashCode() & 0x7FFFFFFF) % this.containerPaths.length;
256
	String currentRelativePath, currentContainerPath;
257
	while ((currentRelativePath = this.relativePaths[index]) != null && (currentContainerPath = this.containerPaths[index]) != null) {
258
		if (currentRelativePath.equals(relativePath) && currentContainerPath.equals(containerPath))
256
			return;
259
			return;
257
		index = (index + 1) % this.paths.length;
260
		index = (index + 1) % this.relativePaths.length;
258
	}
261
	}
259
	this.paths[index] = relativePath;
262
	this.relativePaths[index] = relativePath;
260
	this.containerPaths[index] = containerPath;
263
	this.containerPaths[index] = containerPath;
261
	this.pathWithSubFolders[index] = withSubFolders;
264
	this.isPkgPath[index] = isPackage;
262
	if (this.pathRestrictions != null)
265
	if (this.pathRestrictions != null)
263
		this.pathRestrictions[index] = access;
266
		this.pathRestrictions[index] = access;
264
	else if (access != null) {
267
	else if (access != null) {
265
		this.pathRestrictions = new AccessRuleSet[this.paths.length];
268
		this.pathRestrictions = new AccessRuleSet[this.relativePaths.length];
266
		this.pathRestrictions[index] = access;
269
		this.pathRestrictions[index] = access;
267
	}
270
	}
268
271
269
	// assumes the threshold is never equal to the size of the table
272
	// assumes the threshold is never equal to the size of the table
270
	if (++this.pathsCount > this.threshold)
273
	if (++this.pathsCount > this.threshold)
271
		rehash();
274
		rehash();
272
		
273
}
275
}
274
276
275
/* (non-Javadoc)
277
/* 
278
 * E.g.
279
 * 
280
 * 1. /P/src/pkg/X.java
281
 * 2. /P/src/pkg
282
 * 3. /P/lib.jar|org/eclipse/jdt/core/IJavaElement.class
283
 * 4. /home/mylib.jar|x/y/z/X.class
284
 * 5. c:\temp\mylib.jar|x/y/Y.class
285
 * 
276
 * @see IJavaSearchScope#encloses(String)
286
 * @see IJavaSearchScope#encloses(String)
277
 */
287
 */
278
public boolean encloses(String resourcePathString) {
288
public boolean encloses(String resourcePathString) {
279
	int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR);
289
	int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR);
280
	if (separatorIndex != -1) {
290
	if (separatorIndex != -1) {
281
		return indexOf(resourcePathString.substring(separatorIndex+1), resourcePathString.substring(0, separatorIndex)) >= 0;
291
		// internal or external jar (case 3, 4, or 5)
292
		String jarPath = resourcePathString.substring(0, separatorIndex);
293
		String relativePath = resourcePathString.substring(separatorIndex+1);
294
		return indexOf(jarPath, relativePath) >= 0;
282
	}
295
	}
283
	return indexOf(resourcePathString, null) >= 0;
296
	// resource in workspace (case 1 or 2)
297
	return indexOf(resourcePathString) >= 0;
284
}
298
}
285
299
286
/**
300
/**
287
 * Returns paths list index of given path or -1 if not found.
301
 * Returns paths list index of given path or -1 if not found.
302
 * NOTE: Use indexOf(String, String) for path inside jars
303
 * 
304
 * @param fullPath the full path of the resource, e.g.
305
 *   1. /P/src/pkg/X.java
306
 *   2. /P/src/pkg
288
 */
307
 */
289
private int indexOf(String relativePath, String containerPath) {
308
private int indexOf(String fullPath) {
290
	if (containerPath != null) {
309
	// cannot guess the index of the container path
291
		// if container path is known, use the hash to get faster comparison
292
		int index = (containerPath.hashCode()& 0x7FFFFFFF) % this.paths.length;
293
		String currentContainerPath;
294
		while ((currentContainerPath = this.containerPaths[index]) != null) {
295
			if (currentContainerPath.equals(containerPath)) {
296
				String scopePath = this.paths[index];
297
				if (encloses(scopePath, relativePath, index))
298
					return index;
299
			}
300
			index = (index + 1) % this.paths.length;
301
		}
302
		return -1;
303
	}
304
	
305
	// fallback to sequentially looking at all known paths
310
	// fallback to sequentially looking at all known paths
306
	for (int i = 0, length = this.paths.length; i < length; i++) {
311
	for (int i = 0, length = this.relativePaths.length; i < length; i++) {
307
		String scopePath = this.paths[i];
312
		String currentRelativePath = this.relativePaths[i];
308
		if (scopePath == null) continue;
313
		if (currentRelativePath == null) continue;
309
		if (encloses(this.containerPaths[i] + '/' + scopePath, relativePath, i))
314
		String currentContainerPath = this.containerPaths[i];
315
		String currentFullPath = currentRelativePath.length() == 0 ? currentContainerPath : (currentContainerPath + '/' + currentRelativePath);
316
		if (encloses(currentFullPath, fullPath, i))
310
			return i;
317
			return i;
311
	}
318
	}
312
	return -1;
319
	return -1;
313
}
320
}
314
321
315
private boolean encloses(String scopePath, String path, int index) {
322
/**
316
	if (this.pathWithSubFolders[index]) {
323
 * Returns paths list index of given path or -1 if not found.
317
		// TODO (frederic) apply similar change also if not looking at subfolders
324
 * @param containerPath the path of the container, e.g.
318
		int pathLength = path.length();
325
 *   1. /P/src
319
		int scopeLength = scopePath.length();
326
 *   2. /P
320
		if (pathLength < scopeLength) {
327
 *   3. /P/lib.jar
321
			return false;
328
 *   4. /home/mylib.jar
322
		}
329
 *   5. c:\temp\mylib.jar
323
		if (scopeLength == 0) {
330
 * @param relativePath the forward slash path relatively to the container, e.g.
324
			return true;
331
 *   1. x/y/Z.class
325
		}
332
 *   2. x/y
326
		if (pathLength == scopeLength) {
333
 *   3. X.java
327
			return path.equals(scopePath);
334
 *   4. (empty)
328
		}
335
 */
329
		if (path.startsWith(scopePath)) {
336
private int indexOf(String containerPath, String relativePath) {
330
			if (scopePath.charAt(scopeLength-1) == '/') scopeLength--;
337
	// use the hash to get faster comparison
331
			return path.charAt(scopeLength) == '/';
338
	int index = (containerPath.hashCode()& 0x7FFFFFFF) % this.containerPaths.length;
339
	String currentContainerPath;
340
	while ((currentContainerPath = this.containerPaths[index]) != null) {
341
		if (currentContainerPath.equals(containerPath)) {
342
			String currentRelativePath = this.relativePaths[index];
343
			if (encloses(currentRelativePath, relativePath, index))
344
				return index;
332
		}
345
		}
346
		index = (index + 1) % this.relativePaths.length;
347
	}
348
	return -1;
349
}
350
351
/*
352
 * Returns whether the enclosing path encloses the given path (or is equal to it)
353
 */
354
private boolean encloses(String enclosingPath, String path, int index) {
355
	// normalize given path as it can come from outside
356
	path = normalize(path);
357
	
358
	int pathLength = path.length();
359
	int enclosingLength = enclosingPath.length();
360
	if (pathLength < enclosingLength) {
361
		return false;
362
	}
363
	if (enclosingLength == 0) {
364
		return true;
365
	}
366
	if (pathLength == enclosingLength) {
367
		return path.equals(enclosingPath);
368
	}
369
	if (!this.isPkgPath[index]) {
370
		return path.startsWith(enclosingPath)
371
			&& path.charAt(enclosingLength) == '/';
333
	} else {
372
	} else {
334
		// if not looking at subfolders, this scope encloses the given path 
373
		// if looking at a package, this scope encloses the given path 
335
		// if this path is a direct child of the scope's ressource
374
		// if the given path is a direct child of the folder
336
		// or if this path is the scope's resource (see bug 13919 Declaration for package not found if scope is not project)
375
		// or if the given path path is the folder path (see bug 13919 Declaration for package not found if scope is not project)
337
		if (path.startsWith(scopePath) 
376
		if (path.startsWith(enclosingPath) 
338
			&& ((scopePath.length() == path.lastIndexOf('/'))
377
			&& ((enclosingPath.length() == path.lastIndexOf('/'))
339
				|| (scopePath.length() == path.length()))) {
378
				|| (enclosingPath.length() == path.length()))) {
340
			return true;
379
			return true;
341
		}
380
		}
342
	}
381
	}
Lines 361-372 Link Here
361
	}
400
	}
362
	IPackageFragmentRoot root = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
401
	IPackageFragmentRoot root = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
363
	if (root != null && root.isArchive()) {
402
	if (root != null && root.isArchive()) {
403
		// external or internal jar
364
		IPath rootPath = root.getPath();
404
		IPath rootPath = root.getPath();
365
		String rootPathToString = rootPath.getDevice() == null ? rootPath.toString() : rootPath.toOSString();
405
		String rootPathToString = rootPath.getDevice() == null ? rootPath.toString() : rootPath.toOSString();
366
		IPath relativePath = getPath(element, true/*relative path*/);
406
		IPath relativePath = getPath(element, true/*relative path*/);
367
		return indexOf(relativePath.toString(), rootPathToString) >= 0;
407
		return indexOf(rootPathToString, relativePath.toString()) >= 0;
368
	}
408
	}
369
	return this.indexOf(getPath(element, false/*full path*/).toString(), null) >= 0;
409
	// resource in workspace
410
	String fullResourcePathString = getPath(element, false/*full path*/).toString();
411
	return indexOf(fullResourcePathString) >= 0;
370
}
412
}
371
413
372
/* (non-Javadoc)
414
/* (non-Javadoc)
Lines 376-398 Link Here
376
	return this.enclosingProjectsAndJars;
418
	return this.enclosingProjectsAndJars;
377
}
419
}
378
private IPath getPath(IJavaElement element, boolean relativeToRoot) {
420
private IPath getPath(IJavaElement element, boolean relativeToRoot) {
379
	if (element instanceof IPackageFragmentRoot) {
421
	switch (element.getElementType()) {
380
		if (relativeToRoot)
422
		case IJavaElement.JAVA_MODEL:
381
			return Path.EMPTY;
423
			return Path.EMPTY;
382
		return ((IPackageFragmentRoot)element).getPath();
424
		case IJavaElement.JAVA_PROJECT:
383
	}
425
			return element.getPath();
384
	IJavaElement parent = element.getParent();
426
		case IJavaElement.PACKAGE_FRAGMENT_ROOT:
385
	IPath parentPath = parent == null ? null : getPath(parent, relativeToRoot);
427
			if (relativeToRoot)
386
	IPath childPath;
428
				return Path.EMPTY;
387
	if (element instanceof PackageFragment) {
429
			return element.getPath();
388
		String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
430
		case IJavaElement.PACKAGE_FRAGMENT:
389
		childPath = new Path(relativePath);
431
			String relativePath = Util.concatWith(((PackageFragment) element).names, '/');
390
	} else if (element instanceof IOpenable) {
432
			return getPath(element.getParent(), relativeToRoot).append(new Path(relativePath));
391
		childPath = new Path(element.getElementName());
433
		case IJavaElement.COMPILATION_UNIT:
392
	} else {
434
		case IJavaElement.CLASS_FILE:
393
		return parentPath;
435
			return getPath(element.getParent(), relativeToRoot).append(new Path(element.getElementName()));
436
		default:
437
			return getPath(element.getParent(), relativeToRoot);
394
	}
438
	}
395
	return parentPath == null ? childPath : parentPath.append(childPath);
396
}
439
}
397
440
398
/**
441
/**
Lines 402-408 Link Here
402
 * 	Returns specific uninit access rule set when scope does not enclose the given path.
445
 * 	Returns specific uninit access rule set when scope does not enclose the given path.
403
 */
446
 */
404
public AccessRuleSet getAccessRuleSet(String relativePath, String containerPath) {
447
public AccessRuleSet getAccessRuleSet(String relativePath, String containerPath) {
405
	int index = indexOf(relativePath, containerPath);
448
	int index = indexOf(containerPath, relativePath);
406
	if (index == -1) {
449
	if (index == -1) {
407
		// this search scope does not enclose given path
450
		// this search scope does not enclose given path
408
		return NOT_ENCLOSED;
451
		return NOT_ENCLOSED;
Lines 418-430 Link Here
418
	int extraRoom = (int) (size * 1.75f);
461
	int extraRoom = (int) (size * 1.75f);
419
	if (this.threshold == extraRoom)
462
	if (this.threshold == extraRoom)
420
		extraRoom++;
463
		extraRoom++;
421
	this.paths = new String[extraRoom];
464
	this.relativePaths = new String[extraRoom];
422
	this.containerPaths = new String[extraRoom];
465
	this.containerPaths = new String[extraRoom];
423
	this.pathWithSubFolders = new boolean[extraRoom];
466
	this.isPkgPath = new boolean[extraRoom];
424
	this.pathRestrictions = null; // null to optimize case where no access rules are used
467
	this.pathRestrictions = null; // null to optimize case where no access rules are used
425
468
426
	this.enclosingProjectsAndJars = new IPath[0];
469
	this.enclosingProjectsAndJars = new IPath[0];
427
}
470
}
471
472
/*
473
 * Removes trailing slashes from the given path
474
 */
475
private String normalize(String path) {
476
	int pathLength = path.length();
477
	int index = pathLength-1;
478
	while (index >= 0 && path.charAt(index) == '/')
479
		index--;
480
	if (index != pathLength-1)
481
		return path.substring(0, index + 1);
482
	return path;
483
}
484
428
/*
485
/*
429
 * @see AbstractSearchScope#processDelta(IJavaElementDelta)
486
 * @see AbstractSearchScope#processDelta(IJavaElementDelta)
430
 */
487
 */
Lines 453-465 Link Here
453
						}
510
						}
454
						int toRemove = -1;
511
						int toRemove = -1;
455
						for (int i = 0; i < this.pathsCount; i++) {
512
						for (int i = 0; i < this.pathsCount; i++) {
456
							if (this.paths[i].equals(path)) {
513
							if (this.relativePaths[i].equals(path)) { // TODO (jerome) this compares String and IPath !
457
								toRemove = i;
514
								toRemove = i;
458
								break;
515
								break;
459
							}
516
							}
460
						}
517
						}
461
						if (toRemove != -1) {
518
						if (toRemove != -1) {
462
							this.paths[toRemove] = null;
519
							this.relativePaths[toRemove] = null;
463
							rehash();
520
							rehash();
464
						}
521
						}
465
				}
522
				}
Lines 471-483 Link Here
471
private void rehash() {
528
private void rehash() {
472
	JavaSearchScope newScope = new JavaSearchScope(this.pathsCount * 2);		// double the number of expected elements
529
	JavaSearchScope newScope = new JavaSearchScope(this.pathsCount * 2);		// double the number of expected elements
473
	String currentPath;
530
	String currentPath;
474
	for (int i = this.paths.length; --i >= 0;)
531
	for (int i = this.relativePaths.length; --i >= 0;)
475
		if ((currentPath = this.paths[i]) != null)
532
		if ((currentPath = this.relativePaths[i]) != null)
476
			newScope.add(currentPath, this.containerPaths[i], this.pathWithSubFolders[i], this.pathRestrictions == null ? null : this.pathRestrictions[i]);
533
			newScope.add(currentPath, this.containerPaths[i], this.isPkgPath[i], this.pathRestrictions == null ? null : this.pathRestrictions[i]);
477
534
478
	this.paths = newScope.paths;
535
	this.relativePaths = newScope.relativePaths;
479
	this.containerPaths = newScope.containerPaths;
536
	this.containerPaths = newScope.containerPaths;
480
	this.pathWithSubFolders = newScope.pathWithSubFolders;
537
	this.isPkgPath = newScope.isPkgPath;
481
	this.pathRestrictions = newScope.pathRestrictions;
538
	this.pathRestrictions = newScope.pathRestrictions;
482
	this.threshold = newScope.threshold;
539
	this.threshold = newScope.threshold;
483
}
540
}
Lines 497-504 Link Here
497
			result.append("[empty scope]"); //$NON-NLS-1$
554
			result.append("[empty scope]"); //$NON-NLS-1$
498
		} else {
555
		} else {
499
			result.append("["); //$NON-NLS-1$
556
			result.append("["); //$NON-NLS-1$
500
			for (int i = 0; i < this.paths.length; i++) {
557
			for (int i = 0; i < this.relativePaths.length; i++) {
501
				String path = this.paths[i];
558
				String path = this.relativePaths[i];
502
				if (path == null) continue;
559
				if (path == null) continue;
503
				result.append("\n\t"); //$NON-NLS-1$
560
				result.append("\n\t"); //$NON-NLS-1$
504
				result.append(this.containerPaths[i]);
561
				result.append(this.containerPaths[i]);

Return to bug 101777