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

Collapse All | Expand All

(-)search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java (-11 / +20 lines)
Lines 723-733 Link Here
723
	public void searchAllSecondaryTypeNames(
723
	public void searchAllSecondaryTypeNames(
724
			IPackageFragmentRoot[] sourceFolders,
724
			IPackageFragmentRoot[] sourceFolders,
725
			final IRestrictedAccessTypeRequestor nameRequestor,
725
			final IRestrictedAccessTypeRequestor nameRequestor,
726
			boolean waitForIndexes,
726
			IProgressMonitor progressMonitor)  throws JavaModelException {
727
			IProgressMonitor progressMonitor)  throws JavaModelException {
727
728
728
		if (VERBOSE) {
729
		if (VERBOSE) {
729
			Util.verbose("BasicSearchEngine.searchAllSecondaryTypeNames(char[], char[], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
730
			Util.verbose("BasicSearchEngine.searchAllSecondaryTypeNames(IPackageFragmentRoot[], IRestrictedAccessTypeRequestor, boolean, IProgressMonitor)"); //$NON-NLS-1$
730
			StringBuffer buffer = new StringBuffer(" -> source folders: "); //$NON-NLS-1$
731
			StringBuffer buffer = new StringBuffer("	- source folders: "); //$NON-NLS-1$
731
			int length = sourceFolders.length;
732
			int length = sourceFolders.length;
732
			for (int i=0; i<length; i++) {
733
			for (int i=0; i<length; i++) {
733
				if (i==0) {
734
				if (i==0) {
Lines 737-743 Link Here
737
				}
738
				}
738
				buffer.append(sourceFolders[i].getElementName());
739
				buffer.append(sourceFolders[i].getElementName());
739
			}
740
			}
740
			buffer.append(']');
741
			buffer.append("]\n	- waitForIndexes: "); //$NON-NLS-1$
742
			buffer.append(waitForIndexes);
741
			Util.verbose(buffer.toString());
743
			Util.verbose(buffer.toString());
742
		}
744
		}
743
745
Lines 792-805 Link Here
792
		if (progressMonitor != null) {
794
		if (progressMonitor != null) {
793
			progressMonitor.beginTask(Messages.engine_searching, 100); 
795
			progressMonitor.beginTask(Messages.engine_searching, 100); 
794
		}
796
		}
795
		indexManager.performConcurrentJob(
797
		try {
796
			new PatternSearchJob(
798
			indexManager.performConcurrentJob(
797
				pattern, 
799
				new PatternSearchJob(
798
				getDefaultSearchParticipant(), // Java search only
800
					pattern, 
799
				createJavaSearchScope(sourceFolders), 
801
					getDefaultSearchParticipant(), // Java search only
800
				searchRequestor),
802
					createJavaSearchScope(sourceFolders), 
801
			IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
803
					searchRequestor),
802
			progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
804
				waitForIndexes
805
					? IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH
806
					: IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH,
807
				progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
808
		}
809
		catch (OperationCanceledException oce) {
810
			// do nothing
811
		}
803
	}
812
	}
804
813
805
	/**
814
	/**
(-)search/org/eclipse/jdt/internal/core/search/indexing/InternalSearchDocument.java (-2 / +1 lines)
Lines 30-37 Link Here
30
				if (length > 1 && key[length-2] == IIndexConstants.SEPARATOR && key[length-1] == IIndexConstants.SECONDARY_SUFFIX ) {
30
				if (length > 1 && key[length-2] == IIndexConstants.SEPARATOR && key[length-1] == IIndexConstants.SECONDARY_SUFFIX ) {
31
					// This is a key of a secondary type => reset java model manager secondary types cache for document path project
31
					// This is a key of a secondary type => reset java model manager secondary types cache for document path project
32
					JavaModelManager manager = JavaModelManager.getJavaModelManager();
32
					JavaModelManager manager = JavaModelManager.getJavaModelManager();
33
					manager.resetSecondaryTypesCache(getPath());
33
					manager.secondaryTypeAdding(getPath(), key);
34
//					manager.addSecondaryType(getPath(), key);
35
				}
34
				}
36
			}
35
			}
37
		}
36
		}
(-)model/org/eclipse/jdt/internal/core/NameLookup.java (-8 / +12 lines)
Lines 509-522 Link Here
509
			Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$
509
			Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$
510
			Util.verbose(" -> pkg name: " + packageName);  //$NON-NLS-1$
510
			Util.verbose(" -> pkg name: " + packageName);  //$NON-NLS-1$
511
			Util.verbose(" -> type name: " + typeName);  //$NON-NLS-1$
511
			Util.verbose(" -> type name: " + typeName);  //$NON-NLS-1$
512
			Util.verbose(" -> projects: "+project.getElementName()); //$NON-NLS-1$
512
			Util.verbose(" -> project: "+project.getElementName()); //$NON-NLS-1$
513
		}
513
		}
514
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
514
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
515
		try {
515
		try {
516
			IJavaProject javaProject = project;
516
			IJavaProject javaProject = project;
517
			HashMap secondaryTypePaths = manager.getSecondaryTypes(javaProject, waitForIndexes, monitor);
517
			Map secondaryTypePaths = manager.secondaryTypes(javaProject, waitForIndexes, monitor);
518
			if (secondaryTypePaths.size() > 0) {
518
			if (secondaryTypePaths.size() > 0) {
519
				HashMap types = (HashMap) secondaryTypePaths.get(packageName==null?"":packageName); //$NON-NLS-1$
519
				Map types = (Map) secondaryTypePaths.get(packageName==null?"":packageName); //$NON-NLS-1$
520
				if (types != null && types.size() > 0) {
520
				if (types != null && types.size() > 0) {
521
					IType type = (IType) types.get(typeName);
521
					IType type = (IType) types.get(typeName);
522
					if (type != null) {
522
					if (type != null) {
Lines 568-587 Link Here
568
		// Try to find type in package fragments list
568
		// Try to find type in package fragments list
569
		IType type = null;
569
		IType type = null;
570
		int length= packages.length;
570
		int length= packages.length;
571
		IJavaProject project = null;
571
		HashSet projects = null;
572
		for (int i= 0; i < length; i++) {
572
		for (int i= 0; i < length; i++) {
573
			type = findType(typeName, packages[i], partialMatch, acceptFlags);
573
			type = findType(typeName, packages[i], partialMatch, acceptFlags);
574
			if (type != null) {
574
			if (type != null) {
575
				return type;
575
				return type;
576
			}
576
			}
577
			if (considerSecondaryTypes && project == null) {
577
			if (considerSecondaryTypes) {
578
				project = packages[i].getJavaProject();
578
				if (projects == null) projects = new HashSet(3);
579
				projects.add(packages[i].getJavaProject());
579
			}
580
			}
580
		}
581
		}
581
582
582
		// If type was not found, try to find it as secondary in source folders
583
		// If type was not found, try to find it as secondary in source folders
583
		if (considerSecondaryTypes && project != null) {
584
		if (considerSecondaryTypes && projects != null) {
584
			type = findSecondaryType(packageName, typeName, project, waitForIndexes, monitor);
585
			Iterator allProjects = projects.iterator();
586
			while (type == null && allProjects.hasNext()) {
587
				type = findSecondaryType(packageName, typeName, (IJavaProject) allProjects.next(), waitForIndexes, monitor);
588
			}
585
		}
589
		}
586
		return type;
590
		return type;
587
	}
591
	}
(-)model/org/eclipse/jdt/internal/core/JavaModelManager.java (-191 / +390 lines)
Lines 172-179 Link Here
172
	
172
	
173
	private static final String ENABLE_NEW_FORMATTER = JavaCore.PLUGIN_ID + "/formatter/enable_new" ; //$NON-NLS-1$
173
	private static final String ENABLE_NEW_FORMATTER = JavaCore.PLUGIN_ID + "/formatter/enable_new" ; //$NON-NLS-1$
174
174
175
	private final static String DIRTY_CACHE = "***dirty***"; //$NON-NLS-1$
175
	private final static String INDEXED_SECONDARY_TYPES = "#@*_indexing secondary cache_*@#"; //$NON-NLS-1$
176
	private final static HashMap NO_SECONDARY_TYPES = new HashMap(0);
177
176
178
	public static boolean PERF_VARIABLE_INITIALIZER = false;
177
	public static boolean PERF_VARIABLE_INITIALIZER = false;
179
	public static boolean PERF_CONTAINER_INITIALIZER = false;
178
	public static boolean PERF_CONTAINER_INITIALIZER = false;
Lines 820-826 Link Here
820
		
819
		
821
		public IEclipsePreferences preferences;
820
		public IEclipsePreferences preferences;
822
		public Hashtable options;
821
		public Hashtable options;
823
		public HashMap secondaryTypes;
822
		public Hashtable secondaryTypes;
824
		public LRUCache javadocCache;
823
		public LRUCache javadocCache;
825
		
824
		
826
		public PerProjectInfo(IProject project) {
825
		public PerProjectInfo(IProject project) {
Lines 1435-1548 Link Here
1435
	}
1434
	}
1436
1435
1437
	/**
1436
	/**
1438
	 * Get all secondary types for a project and store result in per project info cache.
1439
	 * 
1440
	 * @param project Project we want get secondary types from
1441
	 * @return HashMap Table of secondary type names->path for given project
1442
	 */
1443
	public HashMap getSecondaryTypes(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) throws JavaModelException {
1444
		if (VERBOSE) {
1445
			StringBuffer buffer = new StringBuffer("JavaModelManager.getSecondaryTypesPaths("); //$NON-NLS-1$
1446
			buffer.append(project.getElementName());
1447
			buffer.append(')');
1448
			Util.verbose(buffer.toString());
1449
		}
1450
1451
		// Wait the end of indexing if requested
1452
		final PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project.getProject());
1453
		IndexManager manager = getIndexManager();
1454
		boolean indexing = manager.awaitingJobsCount() > 0;
1455
		if (indexing && waitForIndexes) {
1456
			while (manager.awaitingJobsCount() > 0) {
1457
				if (monitor != null && monitor.isCanceled()) {
1458
					if (projectInfo.secondaryTypes == null) return NO_SECONDARY_TYPES;
1459
					return projectInfo.secondaryTypes;
1460
				}
1461
				try {
1462
					Thread.sleep(10);
1463
				} catch (InterruptedException e) {
1464
					if (projectInfo.secondaryTypes == null) return NO_SECONDARY_TYPES;
1465
					return projectInfo.secondaryTypes;
1466
				}
1467
			}
1468
		}
1469
1470
		// Return cache if not empty and not dirty
1471
		if (projectInfo.secondaryTypes != null && projectInfo.secondaryTypes.get(DIRTY_CACHE) == null) {
1472
			return projectInfo.secondaryTypes;
1473
		}
1474
		
1475
		// Return cache if not waiting for indexing
1476
		if (indexing && !waitForIndexes) {
1477
			if (projectInfo.secondaryTypes == null) {
1478
				return NO_SECONDARY_TYPES; // cache is not initialized return empty one
1479
			}
1480
			return projectInfo.secondaryTypes; // cache is dirty => return current one...
1481
		}
1482
1483
		// Init variables for search
1484
		final HashMap secondaryTypes = new HashMap(3);
1485
		IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
1486
			public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) {
1487
				String key = packageName==null ? "" : new String(packageName); //$NON-NLS-1$
1488
				HashMap types = (HashMap) secondaryTypes.get(key);
1489
				if (types == null) types = new HashMap(3);
1490
				types.put(new String(simpleTypeName), path);
1491
				secondaryTypes.put(key, types);
1492
			}
1493
		};
1494
1495
		// Build scope using prereq projects but only source folders
1496
		IPackageFragmentRoot[] allRoots = project.getAllPackageFragmentRoots();
1497
		int length = allRoots.length, size = 0;
1498
		IPackageFragmentRoot[] allSourceFolders = new IPackageFragmentRoot[length];
1499
		for (int i=0; i<length; i++) {
1500
			if (allRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
1501
				allSourceFolders[size++] = allRoots[i];
1502
			}
1503
		}
1504
		if (size < length) {
1505
			System.arraycopy(allSourceFolders, 0, allSourceFolders = new IPackageFragmentRoot[size], 0, size);
1506
		}
1507
1508
		// Search all secondary types on scope
1509
		new BasicSearchEngine().searchAllSecondaryTypeNames(allSourceFolders, nameRequestor, monitor);
1510
		if (VERBOSE) {
1511
			System.out.print(Thread.currentThread() + "	-> secondary paths: ");  //$NON-NLS-1$
1512
			System.out.println();
1513
			Iterator keys = secondaryTypes.keySet().iterator();
1514
			while (keys.hasNext()) {
1515
				String qualifiedName = (String) keys.next();
1516
				Util.verbose("		- "+qualifiedName+'-'+secondaryTypes.get(qualifiedName) ); //$NON-NLS-1$
1517
			}
1518
		}
1519
1520
		// Build types from paths
1521
		Iterator packages = secondaryTypes.keySet().iterator();
1522
		while (packages.hasNext()) {
1523
			String packName = (String) packages.next();
1524
			HashMap types = (HashMap) secondaryTypes.get(packName);
1525
			Iterator names = types.keySet().iterator();
1526
			while (names.hasNext()) {
1527
				String typeName = (String) names.next();
1528
				String path = (String) types.get(typeName);
1529
				if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path)) {
1530
					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
1531
					ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom(file, null);
1532
					IType type = unit.getType(typeName);
1533
					types.put(typeName, type); // replace stored path with type itself
1534
				}
1535
			}
1536
		}
1537
1538
		// Store result in per project info cache if still null or dirty (may have been set by another thread...)
1539
		if (projectInfo.secondaryTypes == null || projectInfo.secondaryTypes.get(DIRTY_CACHE) != null) {
1540
			projectInfo.secondaryTypes = secondaryTypes;
1541
		}
1542
		return projectInfo.secondaryTypes;
1543
	}
1544
1545
	/**
1546
	 * Returns the temporary cache for newly opened elements for the current thread.
1437
	 * Returns the temporary cache for newly opened elements for the current thread.
1547
	 * Creates it if not already created.
1438
	 * Creates it if not already created.
1548
	 */
1439
	 */
Lines 2400-2485 Link Here
2400
		MANAGER = new JavaModelManager();
2291
		MANAGER = new JavaModelManager();
2401
	}
2292
	}
2402
2293
2403
	/**
2404
	 * Remove a file from its project secondary types cache.
2405
	 * 
2406
	 * @param file File to remove
2407
	 */
2408
	public void removeFromSecondaryTypesCache(IFile file) {
2409
		if (VERBOSE) {
2410
			StringBuffer buffer = new StringBuffer("JavaModelManager.removeSecondaryTypePaths("); //$NON-NLS-1$
2411
			buffer.append(file.getName());
2412
			buffer.append(')');
2413
			Util.verbose(buffer.toString());
2414
		}
2415
		if (file != null) {
2416
			PerProjectInfo projectInfo = getPerProjectInfo(file.getProject(), false);
2417
			if (projectInfo != null && projectInfo.secondaryTypes != null) {
2418
				if (VERBOSE) {
2419
					Util.verbose("-> remove file from cache of project: "+file.getProject().getName()); //$NON-NLS-1$
2420
				}
2421
				Iterator packages = projectInfo.secondaryTypes.keySet().iterator();
2422
				while (packages.hasNext()) {
2423
					String packName = (String) packages.next();
2424
					Object object = projectInfo.secondaryTypes.get(packName);
2425
					if (object instanceof HashMap) {
2426
						HashMap types = (HashMap) object;
2427
						Iterator names = types.keySet().iterator();
2428
						while (names.hasNext()) {
2429
							String typeName = (String) names.next();
2430
							IType type = (IType) types.get(typeName);
2431
							if (file.equals(type.getResource())) {
2432
								types.remove(typeName);
2433
								if (types.size() == 0) {
2434
									projectInfo.secondaryTypes.remove(packName);
2435
								}
2436
								return;
2437
							}
2438
						}
2439
					}
2440
				}
2441
			}
2442
		}
2443
	}
2444
2445
	/**
2446
	 * Reset secondary types cache for a project got from given path.
2447
	 * If secondary types cache already exist, do not reset it now to avoid
2448
	 * cache desynchronization (this reset is done in indexing thread...).
2449
	 * Instead flag the cache as dirty to store the fact that current cache
2450
	 * should be recomputed when indexing will be ended.
2451
	 * 
2452
	 * @param path Path of file containing a secondary type
2453
	 */
2454
	public void resetSecondaryTypesCache(String path) {
2455
		if (VERBOSE) {
2456
			StringBuffer buffer = new StringBuffer("JavaModelManager.resetSecondaryTypePaths("); //$NON-NLS-1$
2457
			buffer.append(path);
2458
			buffer.append(')');
2459
			Util.verbose(buffer.toString());
2460
		}
2461
		IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
2462
		IResource resource = wRoot.findMember(path);
2463
		if (resource != null) {
2464
			PerProjectInfo projectInfo = getPerProjectInfo(resource.getProject(), false);
2465
			if (projectInfo != null) {
2466
				if (VERBOSE) {
2467
					Util.verbose("-> reset cache for project: "+resource.getProject().getName()); //$NON-NLS-1$
2468
				}
2469
				if (projectInfo.secondaryTypes != null) {
2470
					Object dirty = projectInfo.secondaryTypes.get(DIRTY_CACHE);
2471
					if (dirty == null) {
2472
						projectInfo.secondaryTypes.put(DIRTY_CACHE, resource);
2473
					} else {
2474
						HashSet resources = (dirty instanceof HashSet) ? (HashSet) dirty : new HashSet(3);
2475
						resources.add(resource);
2476
						projectInfo.secondaryTypes.put(DIRTY_CACHE, resource);
2477
					}
2478
				}
2479
			}
2480
		}
2481
	}
2482
2483
	/*
2294
	/*
2484
	 * Resets the temporary cache for newly created elements to null.
2295
	 * Resets the temporary cache for newly created elements to null.
2485
	 */
2296
	 */
Lines 2694-2699 Link Here
2694
	}
2505
	}
2695
2506
2696
	/**
2507
	/**
2508
	 * Add a secondary type in temporary indexing cache for a project got from given path.
2509
	 * 
2510
	 * Current secondary types cache is not modified as we want to wait that indexing
2511
	 * was finished before taking new secondary types into account.
2512
	 * 
2513
	 * Indexing cache is a specific entry in secondary types cache which key is
2514
	 * {@link #INDEXED_SECONDARY_TYPES } and value a map with same structure than
2515
	 * secondary types cache itself.
2516
	 * 
2517
	 * @see #secondaryTypes(IJavaProject, boolean, IProgressMonitor)
2518
	 */
2519
	public void secondaryTypeAdding(String path, char[] key) {
2520
		if (VERBOSE) {
2521
			StringBuffer buffer = new StringBuffer("JavaModelManager.addSecondaryType("); //$NON-NLS-1$
2522
			buffer.append(path);
2523
			buffer.append(',');
2524
			buffer.append('[');
2525
			buffer.append(new String(key));
2526
			buffer.append(']');
2527
			buffer.append(')');
2528
			Util.verbose(buffer.toString());
2529
		}
2530
		IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
2531
		IResource resource = wRoot.findMember(path);
2532
		if (resource != null) {
2533
			if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path) && resource.getType() == IResource.FILE) {
2534
				IProject project = resource.getProject();
2535
				try {
2536
					PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project);
2537
					// Get or create map to cache secondary types while indexing (can be not synchronized as indexing insure a non-concurrent usage)
2538
					HashMap indexedSecondaryTypes = null;
2539
					if (projectInfo.secondaryTypes == null) {
2540
						projectInfo.secondaryTypes = new Hashtable(3);
2541
						indexedSecondaryTypes = new HashMap(3);
2542
						projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, indexedSecondaryTypes);
2543
					} else {
2544
						indexedSecondaryTypes = (HashMap) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
2545
						if (indexedSecondaryTypes == null) {
2546
							indexedSecondaryTypes = new HashMap(3);
2547
							projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, indexedSecondaryTypes);
2548
						}
2549
					}
2550
					// Store the secondary type in temporary cache (these are just handles => no problem to create it now...)
2551
					HashMap allTypes = (HashMap) indexedSecondaryTypes.get(resource);
2552
					if (allTypes == null) {
2553
						allTypes = new HashMap(3);
2554
						indexedSecondaryTypes.put(resource, allTypes);
2555
					}
2556
					ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom((IFile)resource, null);
2557
					if (unit != null) {
2558
						char[][] names = CharOperation.splitOn('/', key);
2559
						String typeName = new String(names[0]);
2560
						String packName = new String(names[1]);
2561
						HashMap packageTypes = (HashMap) allTypes.get(packName);
2562
						if (packageTypes == null) {
2563
							packageTypes = new HashMap(3);
2564
							allTypes.put(packName, packageTypes);
2565
						}
2566
						packageTypes.put(typeName, unit.getType(typeName));
2567
					}
2568
					if (VERBOSE) {
2569
						Util.verbose("	- indexing cache:"); //$NON-NLS-1$
2570
						Iterator keys = indexedSecondaryTypes.keySet().iterator();
2571
						while (keys.hasNext()) {
2572
							IFile file = (IFile) keys.next();
2573
							Util.verbose("		+ "+file.getFullPath()+':'+indexedSecondaryTypes.get(file) ); //$NON-NLS-1$
2574
						}
2575
					}
2576
				}
2577
				catch (JavaModelException jme) {
2578
					// do nothing
2579
				}
2580
			}
2581
		}
2582
	}
2583
2584
	/**
2585
	 * Get all secondary types for a project and store result in per project info cache.
2586
	 * 
2587
	 * This cache is an Hashtable<String, HashMap<String, IType>>:
2588
	 * 	- key: package name
2589
	 * 	- value:
2590
	 * 		+ key: type name
2591
	 * 		+ value: java model handle for the secondary type
2592
	 * Hashtable was used to protect callers from possible concurrent access.
2593
	 * 
2594
	 * Note that this map may have a specific entry which key is {@link #INDEXED_SECONDARY_TYPES }
2595
	 * and value is a map containing all secondary types created during indexing.
2596
	 * When this key is in cache and indexing is finished, returned map is merged
2597
	 * with the value of this special key. If indexing is not finished and caller does
2598
	 * not wait for the end of indexing, returned map is the current secondary
2599
	 * types cache content which may be invalid...
2600
	 * 
2601
	 * @param project Project we want get secondary types from
2602
	 * @return HashMap Table of secondary type names->path for given project
2603
	 */
2604
	public Map secondaryTypes(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) throws JavaModelException {
2605
		if (VERBOSE) {
2606
			StringBuffer buffer = new StringBuffer("JavaModelManager.secondaryTypes("); //$NON-NLS-1$
2607
			buffer.append(project.getElementName());
2608
			buffer.append(',');
2609
			buffer.append(waitForIndexes);
2610
			buffer.append(')');
2611
			Util.verbose(buffer.toString());
2612
		}
2613
2614
		// Return cache if not empty and there's no new secondary types created during indexing
2615
		final PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project.getProject());
2616
		Map indexingSecondaryCache = projectInfo.secondaryTypes == null ? null : (Map) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
2617
		if (projectInfo.secondaryTypes != null && indexingSecondaryCache == null) {
2618
			return projectInfo.secondaryTypes;
2619
		}
2620
2621
		// Perform search request only if secondary types cache is not initialized yet (this will happen only once!)
2622
		if (projectInfo.secondaryTypes == null) {
2623
			return secondaryTypesSearching(project, waitForIndexes, monitor, projectInfo);
2624
		}
2625
2626
		// New secondary types have been created while indexing secondary types cache
2627
		// => need to know whether the indexing is finished or not
2628
		boolean indexing = this.indexManager.awaitingJobsCount() > 0;
2629
		if (indexing) {
2630
			if (!waitForIndexes)  {
2631
				// Indexing is running but caller cannot wait => return current cache
2632
				return projectInfo.secondaryTypes;
2633
			}
2634
2635
			// Wait for the end of indexing or a cancel
2636
			while (this.indexManager.awaitingJobsCount() > 0) {
2637
				if (monitor != null && monitor.isCanceled()) {
2638
					return projectInfo.secondaryTypes;
2639
				}
2640
				try {
2641
					Thread.sleep(10);
2642
				} catch (InterruptedException e) {
2643
					return projectInfo.secondaryTypes;
2644
				}
2645
			}
2646
		}
2647
2648
		// Indexing is finished => merge caches and return result
2649
		return secondaryTypesMerging(projectInfo.secondaryTypes);
2650
	}
2651
	
2652
	/*
2653
	 * Return secondary types cache merged with new secondary types created while indexing
2654
	 * Note that merge result is directly stored in given parameter map.
2655
	 */
2656
	private Hashtable secondaryTypesMerging(Hashtable secondaryTypes) {
2657
		if (VERBOSE) {
2658
			Util.verbose("JavaModelManager.getSecondaryTypesMerged()"); //$NON-NLS-1$
2659
			Util.verbose("	- current cache to merge:"); //$NON-NLS-1$
2660
			Iterator keys = secondaryTypes.keySet().iterator();
2661
			while (keys.hasNext()) {
2662
				String packName = (String) keys.next();
2663
				Util.verbose("		+ "+packName+':'+secondaryTypes.get(packName) ); //$NON-NLS-1$
2664
			}
2665
		}
2666
2667
		// Return current cache if there's no indexing cache (double check, this should not happen)
2668
		HashMap indexedSecondaryTypes = (HashMap) secondaryTypes.remove(INDEXED_SECONDARY_TYPES);
2669
		if (indexedSecondaryTypes == null) {
2670
			return secondaryTypes;
2671
		}
2672
2673
		// Merge indexing cache in secondary types one
2674
		Iterator files = indexedSecondaryTypes.keySet().iterator();
2675
		while (files.hasNext()) {
2676
			IFile file = (IFile) files.next();
2677
	
2678
			// Remove all secondary types of indexed file from cache
2679
			secondaryTypesRemoving(secondaryTypes, file);
2680
			
2681
			// Add all indexing file secondary types in given secondary types cache
2682
			HashMap fileSecondaryTypes = (HashMap) indexedSecondaryTypes.get(file);
2683
			Iterator packages = fileSecondaryTypes.keySet().iterator();
2684
			while (packages.hasNext()) {
2685
				String packageName = (String) packages.next();
2686
				HashMap cachedTypes = (HashMap) secondaryTypes.get(packageName);
2687
				if (cachedTypes == null) {
2688
					secondaryTypes.put(packageName, fileSecondaryTypes.get(packageName));
2689
				} else {
2690
					HashMap types = (HashMap) fileSecondaryTypes.get(packageName);
2691
					Iterator typeNames = types.keySet().iterator();
2692
					while (typeNames.hasNext()) {
2693
						String typeName = (String) typeNames.next();
2694
						cachedTypes.put(typeName, types.get(typeName));
2695
					}
2696
				}
2697
			}
2698
		}
2699
		if (VERBOSE) {
2700
			Util.verbose("	- secondary types cache merged:"); //$NON-NLS-1$
2701
			Iterator keys = secondaryTypes.keySet().iterator();
2702
			while (keys.hasNext()) {
2703
				String packName = (String) keys.next();
2704
				Util.verbose("		+ "+packName+':'+secondaryTypes.get(packName) ); //$NON-NLS-1$
2705
			}
2706
		}
2707
		return secondaryTypes;
2708
	}
2709
2710
	/*
2711
	 * Perform search request to get all secondary types of a given project.
2712
	 * If not waiting for indexes and indexing is running, will return types found in current built indexes...
2713
	 */
2714
	private Map secondaryTypesSearching(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor, final PerProjectInfo projectInfo) throws JavaModelException {
2715
		if (VERBOSE || BasicSearchEngine.VERBOSE) {
2716
			StringBuffer buffer = new StringBuffer("JavaModelManager.secondaryTypesSearch("); //$NON-NLS-1$
2717
			buffer.append(project.getElementName());
2718
			buffer.append(',');
2719
			buffer.append(waitForIndexes);
2720
			buffer.append(')');
2721
			Util.verbose(buffer.toString());
2722
		}
2723
2724
		final Hashtable secondaryTypes = new Hashtable(3);
2725
		IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
2726
			public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) {
2727
				String key = packageName==null ? "" : new String(packageName); //$NON-NLS-1$
2728
				HashMap types = (HashMap) secondaryTypes.get(key);
2729
				if (types == null) types = new HashMap(3);
2730
				types.put(new String(simpleTypeName), path);
2731
				secondaryTypes.put(key, types);
2732
			}
2733
		};
2734
2735
		// Build scope using prereq projects but only source folders
2736
		IPackageFragmentRoot[] allRoots = project.getAllPackageFragmentRoots();
2737
		int length = allRoots.length, size = 0;
2738
		IPackageFragmentRoot[] allSourceFolders = new IPackageFragmentRoot[length];
2739
		for (int i=0; i<length; i++) {
2740
			if (allRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
2741
				allSourceFolders[size++] = allRoots[i];
2742
			}
2743
		}
2744
		if (size < length) {
2745
			System.arraycopy(allSourceFolders, 0, allSourceFolders = new IPackageFragmentRoot[size], 0, size);
2746
		}
2747
2748
		// Search all secondary types on scope
2749
		new BasicSearchEngine().searchAllSecondaryTypeNames(allSourceFolders, nameRequestor, waitForIndexes, monitor);
2750
2751
		// Build types from paths
2752
		Iterator packages = secondaryTypes.keySet().iterator();
2753
		while (packages.hasNext()) {
2754
			String packName = (String) packages.next();
2755
			HashMap types = (HashMap) secondaryTypes.get(packName);
2756
			Iterator names = types.keySet().iterator();
2757
			while (names.hasNext()) {
2758
				String typeName = (String) names.next();
2759
				String path = (String) types.get(typeName);
2760
				if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path)) {
2761
					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
2762
					ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom(file, null);
2763
					IType type = unit.getType(typeName);
2764
					types.put(typeName, type); // replace stored path with type itself
2765
				}
2766
			}
2767
		}
2768
2769
		// Store result in per project info cache if still null or there's still an indexing cache (may have been set by another thread...)
2770
		if (projectInfo.secondaryTypes == null || projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES) != null) {
2771
			projectInfo.secondaryTypes = secondaryTypes;
2772
			if (VERBOSE || BasicSearchEngine.VERBOSE) {
2773
				System.out.print(Thread.currentThread() + "	-> secondary paths stored in cache: ");  //$NON-NLS-1$
2774
				System.out.println();
2775
				Iterator keys = secondaryTypes.keySet().iterator();
2776
				while (keys.hasNext()) {
2777
					String qualifiedName = (String) keys.next();
2778
					Util.verbose("		- "+qualifiedName+'-'+secondaryTypes.get(qualifiedName) ); //$NON-NLS-1$
2779
				}
2780
			}
2781
		}
2782
		return projectInfo.secondaryTypes;
2783
	}
2784
2785
	/**
2786
	 * Remove from secondary types cache all types belonging to a given file.
2787
	 * Clean secondary types cache built while indexing if requested.
2788
	 * 
2789
	 * Project's secondary types cache is found using file location.
2790
	 * 
2791
	 * @param file File to remove
2792
	 */
2793
	public void secondaryTypesRemoving(IFile file, boolean cleanIndexCache) {
2794
		if (VERBOSE) {
2795
			StringBuffer buffer = new StringBuffer("JavaModelManager.removeFromSecondaryTypesCache("); //$NON-NLS-1$
2796
			buffer.append(file.getName());
2797
			buffer.append(')');
2798
			Util.verbose(buffer.toString());
2799
		}
2800
		if (file != null) {
2801
			PerProjectInfo projectInfo = getPerProjectInfo(file.getProject(), false);
2802
			if (projectInfo != null && projectInfo.secondaryTypes != null) {
2803
				if (VERBOSE) {
2804
					Util.verbose("-> remove file from cache of project: "+file.getProject().getName()); //$NON-NLS-1$
2805
				}
2806
2807
				// Clean current cache
2808
				secondaryTypesRemoving(projectInfo.secondaryTypes, file);
2809
				
2810
				// Clean indexing cache if necessary
2811
				if (!cleanIndexCache) return;
2812
				HashMap indexingCache = (HashMap) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
2813
				if (indexingCache != null) {
2814
					Set keys = indexingCache.keySet();
2815
					int filesSize = keys.size(), filesCount = 0;
2816
					IFile[] removed = null;
2817
					Iterator cachedFiles = keys.iterator();
2818
					while (cachedFiles.hasNext()) {
2819
						IFile cachedFile = (IFile) cachedFiles.next();
2820
						if (file.equals(cachedFile)) {
2821
							if (removed == null) removed = new IFile[filesSize];
2822
							filesSize--;
2823
							removed[filesCount++] = cachedFile;
2824
						}
2825
					}
2826
					for (int i=0; i<filesCount; i++) {
2827
						indexingCache.remove(removed[i]);
2828
					}
2829
				}
2830
			}
2831
		}
2832
	}
2833
2834
	/*
2835
	 * Remove from a given cache map all secondary types belonging to a given file.
2836
	 * Note that there can have several secondary types per file...
2837
	 */
2838
	private void secondaryTypesRemoving(Hashtable secondaryTypesMap, IFile file) {
2839
		if (VERBOSE) {
2840
			StringBuffer buffer = new StringBuffer("JavaModelManager.removeSecondaryTypesFromMap("); //$NON-NLS-1$
2841
			Iterator keys = secondaryTypesMap.keySet().iterator();
2842
			while (keys.hasNext()) {
2843
				String qualifiedName = (String) keys.next();
2844
				buffer.append(qualifiedName+':'+secondaryTypesMap.get(qualifiedName));
2845
			}
2846
			buffer.append(',');
2847
			buffer.append(file.getFullPath());
2848
			buffer.append(')');
2849
			Util.verbose(buffer.toString());
2850
		}
2851
		Set packageKeys = secondaryTypesMap.keySet();
2852
		int packagesSize = packageKeys.size(), removedPackagesCount = 0;
2853
		String[] removedPackages = null;
2854
		Iterator packages = packageKeys.iterator();
2855
		while (packages.hasNext()) {
2856
			String packName = (String) packages.next();
2857
			if (packName != INDEXED_SECONDARY_TYPES) { // skip indexing cache entry if present (!= is intentional)
2858
				HashMap types = (HashMap) secondaryTypesMap.get(packName);
2859
				Set nameKeys = types.keySet();
2860
				int namesSize = nameKeys.size(), removedNamesCount = 0;
2861
				String[] removedNames = null;
2862
				Iterator names = nameKeys.iterator();
2863
				while (names.hasNext()) {
2864
					String typeName = (String) names.next();
2865
					IType type = (IType) types.get(typeName);
2866
					if (file.equals(type.getResource())) {
2867
						if (removedNames == null) removedNames = new String[namesSize];
2868
						namesSize--;
2869
						removedNames[removedNamesCount++] = typeName;
2870
					}
2871
				}
2872
				for (int i=0; i<removedNamesCount; i++) {
2873
					types.remove(removedNames[i]);
2874
				}
2875
				if (types.size() == 0) {
2876
					if (removedPackages == null) removedPackages = new String[packagesSize];
2877
					packagesSize--;
2878
					removedPackages[removedPackagesCount++] = packName;
2879
				}
2880
			}
2881
		}
2882
		for (int i=0; i<removedPackagesCount; i++) {
2883
			secondaryTypesMap.remove(removedPackages[i]);
2884
		}
2885
		if (VERBOSE) {
2886
			Util.verbose("	- new secondary types map:"); //$NON-NLS-1$
2887
			Iterator keys = secondaryTypesMap.keySet().iterator();
2888
			while (keys.hasNext()) {
2889
				String qualifiedName = (String) keys.next();
2890
				Util.verbose("		+ "+qualifiedName+':'+secondaryTypesMap.get(qualifiedName) ); //$NON-NLS-1$
2891
			}
2892
		}
2893
	}
2894
2895
	/**
2697
	 * Record the order in which to build the java projects (batch build). This order is based
2896
	 * Record the order in which to build the java projects (batch build). This order is based
2698
	 * on the projects classpath settings.
2897
	 * on the projects classpath settings.
2699
	 */
2898
	 */
(-)model/org/eclipse/jdt/internal/core/DeltaProcessor.java (-1 / +4 lines)
Lines 2398-2407 Link Here
2398
							break;
2398
							break;
2399
					case IResourceDelta.ADDED :
2399
					case IResourceDelta.ADDED :
2400
						indexManager.addSource(file, file.getProject().getFullPath());
2400
						indexManager.addSource(file, file.getProject().getFullPath());
2401
						// Clean file from secondary types cache but do not update indexing secondary type cache as it will be updated through indexing itself
2402
						this.manager.secondaryTypesRemoving(file, false);
2401
						break;
2403
						break;
2402
					case IResourceDelta.REMOVED :
2404
					case IResourceDelta.REMOVED :
2403
						indexManager.remove(Util.relativePath(file.getFullPath(), 1/*remove project segment*/), file.getProject().getFullPath());
2405
						indexManager.remove(Util.relativePath(file.getFullPath(), 1/*remove project segment*/), file.getProject().getFullPath());
2404
						this.manager.removeFromSecondaryTypesCache(file);
2406
						// Clean file from secondary types cache and update indexing secondary type cache as indexing cannot remove secondary types from cache
2407
						this.manager.secondaryTypesRemoving(file, true);
2405
						break;
2408
						break;
2406
				}
2409
				}
2407
		}
2410
		}
(-)src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java (-10 / +211 lines)
Lines 11-20 Link Here
11
package org.eclipse.jdt.core.tests.model;
11
package org.eclipse.jdt.core.tests.model;
12
12
13
13
14
import java.io.File;
14
import java.io.IOException;
15
import java.io.IOException;
15
16
16
import junit.framework.Test;
17
import junit.framework.Test;
17
18
19
import org.eclipse.core.resources.IFile;
20
import org.eclipse.core.resources.IResource;
18
import org.eclipse.core.resources.IWorkspaceRunnable;
21
import org.eclipse.core.resources.IWorkspaceRunnable;
19
import org.eclipse.core.runtime.CoreException;
22
import org.eclipse.core.runtime.CoreException;
20
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.IProgressMonitor;
Lines 92-100 Link Here
92
// Use this static initializer to specify subset for tests
95
// Use this static initializer to specify subset for tests
93
// All specified tests which do not belong to the class are skipped...
96
// All specified tests which do not belong to the class are skipped...
94
static {
97
static {
98
//	JavaModelManager.VERBOSE = true;
99
//	org.eclipse.jdt.internal.core.search.BasicSearchEngine.VERBOSE = true;
95
//	TESTS_PREFIX = "testBug36032";
100
//	TESTS_PREFIX = "testBug36032";
96
// TESTS_NAMES = new String[] { "testTypeWithDollarName" };
101
//	TESTS_NAMES = new String[] { "testBug118823b" };
97
//	TESTS_NUMBERS = new int[] { 114338 };
102
//	TESTS_NUMBERS = new int[] { 118823 };
98
//	TESTS_RANGE = new int[] { 16, -1 };
103
//	TESTS_RANGE = new int[] { 16, -1 };
99
}
104
}
100
public static Test suite() {
105
public static Test suite() {
Lines 104-110 Link Here
104
	assertProblems(message, expected, this.problemRequestor);
109
	assertProblems(message, expected, this.problemRequestor);
105
}
110
}
106
// Expect no error as soon as indexing is finished
111
// Expect no error as soon as indexing is finished
107
protected void assertNoProblem(char[] source) throws InterruptedException, JavaModelException {
112
protected void assertNoProblem(char[] source, ICompilationUnit unit) throws InterruptedException, JavaModelException {
108
	IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
113
	IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
109
	if (this.problemRequestor.problemCount > 0) {
114
	if (this.problemRequestor.problemCount > 0) {
110
		// If errors then wait for indexes to finish
115
		// If errors then wait for indexes to finish
Lines 113-119 Link Here
113
		}
118
		}
114
		// Reconcile again to see if error goes away
119
		// Reconcile again to see if error goes away
115
		this.problemRequestor.initialize(source);
120
		this.problemRequestor.initialize(source);
116
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
121
		unit.reconcile(AST.JLS3, true, null, null);
117
		if (this.problemRequestor.problemCount > 0) {
122
		if (this.problemRequestor.problemCount > 0) {
118
			assertEquals("Working copy should NOT have any problem!", "", this.problemRequestor.problems.toString());
123
			assertEquals("Working copy should NOT have any problem!", "", this.problemRequestor.problems.toString());
119
		}
124
		}
Lines 2489-2495 Link Here
2489
/**
2494
/**
2490
 * Bug 36032:[plan] JavaProject.findType() fails to find second type in source file
2495
 * Bug 36032:[plan] JavaProject.findType() fails to find second type in source file
2491
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=36032"
2496
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=36032"
2492
 *
2493
 */
2497
 */
2494
public void testBug36032a() throws CoreException, InterruptedException {
2498
public void testBug36032a() throws CoreException, InterruptedException {
2495
	try {
2499
	try {
Lines 2516-2522 Link Here
2516
		this.workingCopy = getCompilationUnit("/P/Test.java").getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
2520
		this.workingCopy = getCompilationUnit("/P/Test.java").getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
2517
		this.workingCopy.getBuffer().setContents(source);
2521
		this.workingCopy.getBuffer().setContents(source);
2518
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2522
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2519
		assertNoProblem(sourceChars);
2523
		assertNoProblem(sourceChars, this.workingCopy);
2520
2524
2521
		// Add new secondary type
2525
		// Add new secondary type
2522
		this.createFile(
2526
		this.createFile(
Lines 2536-2542 Link Here
2536
		this.problemRequestor.initialize(sourceChars);
2540
		this.problemRequestor.initialize(sourceChars);
2537
		this.workingCopy.getBuffer().setContents(source);
2541
		this.workingCopy.getBuffer().setContents(source);
2538
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2542
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2539
		assertNoProblem(sourceChars);
2543
		assertNoProblem(sourceChars, this.workingCopy);
2540
	} finally {
2544
	} finally {
2541
		deleteProject("P");
2545
		deleteProject("P");
2542
	}
2546
	}
Lines 2571-2577 Link Here
2571
		this.workingCopy = getCompilationUnit("/P/Test.java").getWorkingCopy(new WorkingCopyOwner() {}, this.problemRequestor, null);
2575
		this.workingCopy = getCompilationUnit("/P/Test.java").getWorkingCopy(new WorkingCopyOwner() {}, this.problemRequestor, null);
2572
		this.workingCopy.getBuffer().setContents(source);
2576
		this.workingCopy.getBuffer().setContents(source);
2573
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2577
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2574
		assertNoProblem(sourceChars);
2578
		assertNoProblem(sourceChars, this.workingCopy);
2575
2579
2576
		// Delete secondary type => should get a problem
2580
		// Delete secondary type => should get a problem
2577
		waitUntilIndexesReady();
2581
		waitUntilIndexesReady();
Lines 2599-2605 Link Here
2599
		this.problemRequestor.initialize(sourceChars);
2603
		this.problemRequestor.initialize(sourceChars);
2600
		this.workingCopy.getBuffer().setContents(source);
2604
		this.workingCopy.getBuffer().setContents(source);
2601
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2605
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2602
		assertNoProblem(sourceChars);
2606
		assertNoProblem(sourceChars, this.workingCopy);
2603
	} finally {
2607
	} finally {
2604
		deleteProject("P");
2608
		deleteProject("P");
2605
	}
2609
	}
Lines 2646-2652 Link Here
2646
		this.workingCopy = getCompilationUnit("/P2/test/Test2.java").getWorkingCopy(new WorkingCopyOwner() {}, this.problemRequestor, null);
2650
		this.workingCopy = getCompilationUnit("/P2/test/Test2.java").getWorkingCopy(new WorkingCopyOwner() {}, this.problemRequestor, null);
2647
		this.workingCopy.getBuffer().setContents(source);
2651
		this.workingCopy.getBuffer().setContents(source);
2648
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2652
		this.workingCopy.reconcile(AST.JLS3, true, null, null);
2649
		assertNoProblem(sourceChars);
2653
		assertNoProblem(sourceChars, this.workingCopy);
2654
	} finally {
2655
		deleteProject("P1");
2656
		deleteProject("P2");
2657
	}
2658
}
2659
/**
2660
 * Bug 118823: [model] Secondary types cache not reset while removing _all_ secondary types from CU
2661
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118823"
2662
 */
2663
public void testBug118823() throws CoreException, InterruptedException, IOException {
2664
	try {
2665
		// Resources creation
2666
		IJavaProject project = createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
2667
		String source1 = "class Test {}\n";
2668
		IFile file = createFile(
2669
			"/P1/Test.java", 
2670
			source1
2671
		);
2672
		createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
2673
		String source2 = 
2674
			"class A {\n" +
2675
			"	Secondary s;\n" +
2676
			"}\n";
2677
		createFile(
2678
			"/P2/A.java",
2679
			source2
2680
		);
2681
		waitUntilIndexesReady();
2682
2683
		// Get working copies and reconcile
2684
		this.workingCopies = new ICompilationUnit[2];
2685
		this.wcOwner = new WorkingCopyOwner() {};
2686
		this.workingCopies[0] = getCompilationUnit("/P1/Test.java").getWorkingCopy(this.wcOwner, this.problemRequestor, null);
2687
		char[] sourceChars = source1.toCharArray();
2688
		this.problemRequestor.initialize(sourceChars);
2689
		this.workingCopies[0].getBuffer().setContents(source1);
2690
		this.workingCopies[0].reconcile(AST.JLS3, true, null, null);
2691
		assertNoProblem(sourceChars, this.workingCopies[0]);
2692
		this.workingCopies[1] = getCompilationUnit("/P2/A.java").getWorkingCopy(this.wcOwner, this.problemRequestor, null);
2693
		this.problemRequestor.initialize(source2.toCharArray());
2694
		this.workingCopies[1].getBuffer().setContents(source2);
2695
		this.workingCopies[1].reconcile(AST.JLS3, true, null, null);
2696
		assertEquals("Working copy should not find secondary type 'Secondary'!", 1, this.problemRequestor.problemCount);
2697
		assertProblems("Working copy should have problem!",
2698
			"----------\n" +
2699
			"1. ERROR in /P2/A.java (at line 2)\n" +
2700
			"	Secondary s;\n" +
2701
			"	^^^^^^^^^\n" +
2702
			"Secondary cannot be resolved to a type\n" +
2703
			"----------\n"
2704
		);
2705
2706
		// Delete file and recreate it with secondary outside eclipse
2707
		File ioFile = file.getLocation().toFile();
2708
		ioFile.delete();
2709
		source1 = 
2710
			"public class Test {}\n" + 
2711
			"class Secondary{}\n";
2712
		Util.createFile(ioFile.getAbsolutePath(), source1);
2713
		project.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
2714
		sourceChars = source1.toCharArray();
2715
		this.problemRequestor.initialize(sourceChars);
2716
		this.workingCopies[0].getBuffer().setContents(source1);
2717
		this.workingCopies[0].reconcile(AST.JLS3, true, null, null);
2718
		assertNoProblem(sourceChars, this.workingCopies[0]);
2719
		sourceChars = source2.toCharArray();
2720
		this.problemRequestor.initialize(sourceChars);
2721
		this.workingCopies[1].reconcile(AST.JLS3, true, null, null);
2722
		assertNoProblem(sourceChars, this.workingCopies[1]);
2723
	} finally {
2724
		deleteProject("P1");
2725
		deleteProject("P2");
2726
	}
2727
}
2728
public void testBug118823b() throws CoreException, InterruptedException {
2729
	try {
2730
		// Resources creation
2731
		createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
2732
		String source1 = "class Test {}\n";
2733
		createFile(
2734
			"/P1/Test.java", 
2735
			source1
2736
		);
2737
		createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
2738
		String source2 = 
2739
			"class A {\n" +
2740
			"	Secondary s;\n" +
2741
			"}\n";
2742
		createFile(
2743
			"/P2/A.java",
2744
			source2
2745
		);
2746
		waitUntilIndexesReady();
2747
2748
		// Get working copies and reconcile
2749
		this.workingCopies = new ICompilationUnit[2];
2750
		this.wcOwner = new WorkingCopyOwner() {};
2751
		this.workingCopies[0] = getCompilationUnit("/P1/Test.java").getWorkingCopy(this.wcOwner, this.problemRequestor, null);
2752
		char[] sourceChars = source1.toCharArray();
2753
		this.problemRequestor.initialize(sourceChars);
2754
		this.workingCopies[0].getBuffer().setContents(source1);
2755
		this.workingCopies[0].reconcile(AST.JLS3, true, null, null);
2756
		assertNoProblem(sourceChars, this.workingCopies[0]);
2757
		this.workingCopies[1] = getCompilationUnit("/P2/A.java").getWorkingCopy(this.wcOwner, this.problemRequestor, null);
2758
		this.problemRequestor.initialize(source2.toCharArray());
2759
		this.workingCopies[1].getBuffer().setContents(source2);
2760
		this.workingCopies[1].reconcile(AST.JLS3, true, null, null);
2761
		assertEquals("Working copy should not find secondary type 'Secondary'!", 1, this.problemRequestor.problemCount);
2762
		assertProblems("Working copy should have problem!",
2763
			"----------\n" +
2764
			"1. ERROR in /P2/A.java (at line 2)\n" +
2765
			"	Secondary s;\n" +
2766
			"	^^^^^^^^^\n" +
2767
			"Secondary cannot be resolved to a type\n" +
2768
			"----------\n"
2769
		);
2770
2771
		// Add secondary and verify that there's no longer any error
2772
		source1 = 
2773
			"public class Test {}\n" + 
2774
			"class Secondary{}\n";
2775
		sourceChars = source1.toCharArray();
2776
		this.problemRequestor.initialize(sourceChars);
2777
		this.workingCopies[0].getBuffer().setContents(source1);
2778
		this.workingCopies[0].reconcile(AST.JLS3, true, null, null);
2779
		this.workingCopies[0].commitWorkingCopy(true, null);
2780
		assertNoProblem(sourceChars, this.workingCopies[0]);
2781
		sourceChars = source2.toCharArray();
2782
		this.problemRequestor.initialize(sourceChars);
2783
		this.workingCopies[1].reconcile(AST.JLS3, true, null, null);
2784
		assertNoProblem(sourceChars, this.workingCopies[1]);
2785
	} finally {
2786
		deleteProject("P1");
2787
		deleteProject("P2");
2788
	}
2789
}
2790
public void testBug118823c() throws CoreException, InterruptedException {
2791
	try {
2792
		// Resources creation
2793
		createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
2794
		String source1 = "class Test {}\n";
2795
		createFile(
2796
			"/P1/Test.java", 
2797
			source1
2798
		);
2799
		createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
2800
		String source2 = 
2801
			"class A {\n" +
2802
			"	Secondary s;\n" +
2803
			"}\n";
2804
		createFile(
2805
			"/P2/A.java",
2806
			source2
2807
		);
2808
		waitUntilIndexesReady();
2809
2810
		// Get working copies and reconcile
2811
		this.workingCopies = new ICompilationUnit[2];
2812
		this.wcOwner = new WorkingCopyOwner() {};
2813
		this.workingCopies[0] = getCompilationUnit("/P1/Test.java").getWorkingCopy(this.wcOwner, this.problemRequestor, null);
2814
		char[] sourceChars = source1.toCharArray();
2815
		this.problemRequestor.initialize(sourceChars);
2816
		this.workingCopies[0].getBuffer().setContents(source1);
2817
		this.workingCopies[0].reconcile(AST.JLS3, true, null, null);
2818
		assertNoProblem(sourceChars, this.workingCopies[0]);
2819
		this.workingCopies[1] = getCompilationUnit("/P2/A.java").getWorkingCopy(this.wcOwner, this.problemRequestor, null);
2820
		this.problemRequestor.initialize(source2.toCharArray());
2821
		this.workingCopies[1].getBuffer().setContents(source2);
2822
		this.workingCopies[1].reconcile(AST.JLS3, true, null, null);
2823
		assertEquals("Working copy should not find secondary type 'Secondary'!", 1, this.problemRequestor.problemCount);
2824
		assertProblems("Working copy should have problem!",
2825
			"----------\n" +
2826
			"1. ERROR in /P2/A.java (at line 2)\n" +
2827
			"	Secondary s;\n" +
2828
			"	^^^^^^^^^\n" +
2829
			"Secondary cannot be resolved to a type\n" +
2830
			"----------\n"
2831
		);
2832
2833
		// Delete file and recreate it with secondary
2834
		deleteFile("/P1/Test.java");
2835
		source1 = 
2836
			"public class Test {}\n" + 
2837
			"class Secondary{}\n";
2838
		createFile(
2839
			"/P1/Test.java", 
2840
			source1
2841
		);
2842
		sourceChars = source1.toCharArray();
2843
		this.problemRequestor.initialize(sourceChars);
2844
		this.workingCopies[0].getBuffer().setContents(source1);
2845
		this.workingCopies[0].reconcile(AST.JLS3, true, null, null);
2846
		assertNoProblem(sourceChars, this.workingCopies[0]);
2847
		sourceChars = source2.toCharArray();
2848
		this.problemRequestor.initialize(sourceChars);
2849
		this.workingCopies[1].reconcile(AST.JLS3, true, null, null);
2850
		assertNoProblem(sourceChars, this.workingCopies[1]);
2650
	} finally {
2851
	} finally {
2651
		deleteProject("P1");
2852
		deleteProject("P1");
2652
		deleteProject("P2");
2853
		deleteProject("P2");

Return to bug 118823