1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
21 import net.sourceforge.phpdt.core.ElementChangedEvent;
22 import net.sourceforge.phpdt.core.IClasspathEntry;
23 import net.sourceforge.phpdt.core.IElementChangedListener;
24 import net.sourceforge.phpdt.core.IJavaElement;
25 import net.sourceforge.phpdt.core.IJavaElementDelta;
26 import net.sourceforge.phpdt.core.IJavaModel;
27 import net.sourceforge.phpdt.core.IJavaProject;
28 import net.sourceforge.phpdt.core.JavaCore;
29 import net.sourceforge.phpdt.core.JavaModelException;
30 import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
31 import net.sourceforge.phpdt.internal.core.util.Util;
32 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
33 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
35 import org.eclipse.core.resources.IFile;
36 import org.eclipse.core.resources.IProject;
37 import org.eclipse.core.resources.IResource;
38 import org.eclipse.core.resources.IResourceChangeEvent;
39 import org.eclipse.core.resources.IResourceChangeListener;
40 import org.eclipse.core.resources.IResourceDelta;
41 import org.eclipse.core.resources.IResourceDeltaVisitor;
42 import org.eclipse.core.resources.IWorkspace;
43 import org.eclipse.core.resources.ResourcesPlugin;
44 import org.eclipse.core.runtime.CoreException;
45 import org.eclipse.core.runtime.IPath;
46 import org.eclipse.core.runtime.ISafeRunnable;
47 import org.eclipse.core.runtime.Platform;
48 import org.eclipse.core.runtime.QualifiedName;
52 * This class is used by <code>JavaModelManager</code> to convert
53 * <code>IResourceDelta</code>s into <code>IJavaElementDelta</code>s.
54 * It also does some processing on the <code>JavaElement</code>s involved
55 * (e.g. closing them or updating classpaths).
57 public class DeltaProcessor implements IResourceChangeListener {
59 final static int IGNORE = 0;
60 final static int SOURCE = 1;
61 final static int BINARY = 2;
63 final static String EXTERNAL_JAR_ADDED = "external jar added"; //$NON-NLS-1$
64 final static String EXTERNAL_JAR_REMOVED = "external jar removed"; //$NON-NLS-1$
65 final static String EXTERNAL_JAR_CHANGED = "external jar changed"; //$NON-NLS-1$
66 final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
67 final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
69 private final static int NON_JAVA_RESOURCE = -1;
70 public static boolean DEBUG = false;
71 public static boolean VERBOSE = false;
73 public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with ElementChangedEvent event masks
75 * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
77 protected JavaElementDelta currentDelta;
79 // protected IndexManager indexManager = new IndexManager();
81 /* A table from IPath (from a classpath entry) to RootInfo */
84 /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
85 * Used when an IPath corresponds to more than one root */
88 /* Whether the roots tables should be recomputed */
89 public boolean rootsAreStale = true;
91 /* A table from IPath (from a classpath entry) to RootInfo
92 * from the last time the delta processor was invoked. */
95 /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
96 * from the last time the delta processor was invoked.
97 * Used when an IPath corresponds to more than one root */
100 /* A table from IPath (a source attachment path from a classpath entry) to IPath (a root path) */
101 Map sourceAttachments;
103 /* The java element that was last created (see createElement(IResource)).
104 * This is used as a stack of java elements (using getParent() to pop it, and
105 * using the various get*(...) to push it. */
106 Openable currentElement;
108 * Queue of deltas created explicily by the Java Model that
109 * have yet to be fired.
111 public ArrayList javaModelDeltas= new ArrayList();
113 * Queue of reconcile deltas on working copies that have yet to be fired.
114 * This is a table form IWorkingCopy to IJavaElementDelta
116 public HashMap reconcileDeltas = new HashMap();
119 * Turns delta firing on/off. By default it is on.
121 private boolean isFiring= true;
124 public HashMap externalTimeStamps = new HashMap();
125 public HashSet projectsToUpdate = new HashSet();
126 // list of root projects which namelookup caches need to be updated for dependents
127 // TODO: (jerome) is it needed? projectsToUpdate might be sufficient
128 public HashSet projectsForDependentNamelookupRefresh = new HashSet();
131 * The global state of delta processing.
133 private DeltaProcessingState state;
136 * The Java model manager
138 private JavaModelManager manager;
140 /* A table from IJavaProject to an array of IPackageFragmentRoot.
141 * This table contains the pkg fragment roots of the project that are being deleted.
146 * A list of IJavaElement used as a scope for external archives refresh during POST_CHANGE.
147 * This is null if no refresh is needed.
149 HashSet refreshedElements;
155 OutputsInfo(IPath[] paths, int[] traverseModes, int outputCount) {
157 this.traverseModes = traverseModes;
158 this.outputCount = outputCount;
160 public String toString() {
161 if (this.paths == null) return "<none>"; //$NON-NLS-1$
162 StringBuffer buffer = new StringBuffer();
163 for (int i = 0; i < this.outputCount; i++) {
164 buffer.append("path="); //$NON-NLS-1$
165 buffer.append(this.paths[i].toString());
166 buffer.append("\n->traverse="); //$NON-NLS-1$
167 switch (this.traverseModes[i]) {
169 buffer.append("BINARY"); //$NON-NLS-1$
172 buffer.append("IGNORE"); //$NON-NLS-1$
175 buffer.append("SOURCE"); //$NON-NLS-1$
178 buffer.append("<unknown>"); //$NON-NLS-1$
180 if (i+1 < this.outputCount) {
184 return buffer.toString();
188 IJavaProject project;
190 char[][] exclusionPatterns;
191 RootInfo(IJavaProject project, IPath rootPath, char[][] exclusionPatterns) {
192 this.project = project;
193 this.rootPath = rootPath;
194 this.exclusionPatterns = exclusionPatterns;
196 boolean isRootOfProject(IPath path) {
197 return this.rootPath.equals(path) && this.project.getProject().getFullPath().isPrefixOf(path);
199 public String toString() {
200 StringBuffer buffer = new StringBuffer("project="); //$NON-NLS-1$
201 if (this.project == null) {
202 buffer.append("null"); //$NON-NLS-1$
204 buffer.append(this.project.getElementName());
206 buffer.append("\npath="); //$NON-NLS-1$
207 if (this.rootPath == null) {
208 buffer.append("null"); //$NON-NLS-1$
210 buffer.append(this.rootPath.toString());
212 buffer.append("\nexcluding="); //$NON-NLS-1$
213 if (this.exclusionPatterns == null) {
214 buffer.append("null"); //$NON-NLS-1$
216 for (int i = 0, length = this.exclusionPatterns.length; i < length; i++) {
217 buffer.append(new String(this.exclusionPatterns[i]));
219 buffer.append("|"); //$NON-NLS-1$
223 return buffer.toString();
227 // DeltaProcessor(JavaModelManager manager) {
228 // this.manager = manager;
232 * Type of event that should be processed no matter what the real event type is.
234 public int overridenEventType = -1;
236 public DeltaProcessor(DeltaProcessingState state, JavaModelManager manager) {
238 this.manager = manager;
241 * Adds the dependents of the given project to the list of the projects
244 // void addDependentProjects(IPath projectPath, HashSet result) {
246 // IJavaProject[] projects = this.manager.getJavaModel().getJavaProjects();
247 // for (int i = 0, length = projects.length; i < length; i++) {
248 // IJavaProject project = projects[i];
249 // IClasspathEntry[] classpath = ((JavaProject)project).getExpandedClasspath(true);
250 // for (int j = 0, length2 = classpath.length; j < length2; j++) {
251 // IClasspathEntry entry = classpath[j];
252 // if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
253 // && entry.getPath().equals(projectPath)) {
254 // result.add(project);
258 // } catch (JavaModelException e) {
262 * Adds the given element to the list of elements used as a scope for external jars refresh.
264 public void addForRefresh(IJavaElement element) {
265 if (this.refreshedElements == null) {
266 this.refreshedElements = new HashSet();
268 this.refreshedElements.add(element);
271 * Adds the given project and its dependents to the list of the projects
274 void addToProjectsToUpdateWithDependents(IProject project) {
275 this.projectsToUpdate.add(JavaCore.create(project));
276 // this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
280 * Adds the given child handle to its parent's cache of children.
282 protected void addToParentInfo(Openable child) {
284 Openable parent = (Openable) child.getParent();
285 if (parent != null && parent.isOpen()) {
287 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
288 info.addChild(child);
289 } catch (JavaModelException e) {
290 // do nothing - we already checked if open
296 * Check all external archive (referenced by given roots, projects or model) status and issue a corresponding root delta.
297 * Also triggers index updates
299 // public void checkExternalArchiveChanges(IJavaElement[] refreshedElements, IProgressMonitor monitor) throws JavaModelException {
301 // for (int i = 0, length = refreshedElements.length; i < length; i++) {
302 // this.addForRefresh(refreshedElements[i]);
304 // boolean hasDelta = this.createExternalArchiveDelta(monitor);
305 // if (monitor != null && monitor.isCanceled()) return;
307 // // force classpath marker refresh of affected projects
308 // JavaModel.flushExternalFileCache();
309 // IJavaElementDelta[] projectDeltas = this.currentDelta.getAffectedChildren();
310 // for (int i = 0, length = projectDeltas.length; i < length; i++) {
311 // IJavaElementDelta delta = projectDeltas[i];
312 // ((JavaProject)delta.getElement()).getResolvedClasspath(
313 // true, // ignoreUnresolvedEntry
314 // true); // generateMarkerOnError
316 // if (this.currentDelta != null) { // if delta has not been fired while creating markers
317 // this.manager.fire(this.currentDelta, JavaModelManager.DEFAULT_CHANGE_EVENT);
321 // this.currentDelta = null;
322 // if (monitor != null) monitor.done();
326 * Check if external archives have changed and create the corresponding deltas.
327 * Returns whether at least on delta was created.
329 // public boolean createExternalArchiveDelta(IProgressMonitor monitor) throws JavaModelException {
331 // if (this.refreshedElements == null) return false;
333 // HashMap externalArchivesStatus = new HashMap();
334 // boolean hasDelta = false;
336 // // find JARs to refresh
337 // HashSet archivePathsToRefresh = new HashSet();
339 // Iterator iterator = this.refreshedElements.iterator();
340 // while (iterator.hasNext()) {
341 // IJavaElement element = (IJavaElement)iterator.next();
342 // switch(element.getElementType()){
343 // case IJavaElement.PACKAGE_FRAGMENT_ROOT :
344 // archivePathsToRefresh.add(element.getPath());
346 // case IJavaElement.JAVA_PROJECT :
347 // IJavaProject project = (IJavaProject) element;
348 // if (!JavaProject.hasJavaNature(project.getProject())) {
349 // // project is not accessible or has lost its Java nature
352 // IClasspathEntry[] classpath = project.getResolvedClasspath(true);
353 // for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
354 // if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
355 // archivePathsToRefresh.add(classpath[j].getPath());
359 // case IJavaElement.JAVA_MODEL :
360 // IJavaProject[] projects = manager.getJavaModel().getOldJavaProjectsList();
361 // for (int j = 0, projectsLength = projects.length; j < projectsLength; j++){
362 // project = projects[j];
363 // if (!JavaProject.hasJavaNature(project.getProject())) {
364 // // project is not accessible or has lost its Java nature
367 // classpath = project.getResolvedClasspath(true);
368 // for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
369 // if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
370 // archivePathsToRefresh.add(classpath[k].getPath());
378 // this.refreshedElements = null;
381 // // perform refresh
382 // IJavaProject[] projects = manager.getJavaModel().getOldJavaProjectsList();
383 // IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
384 // for (int i = 0, length = projects.length; i < length; i++) {
386 // if (monitor != null && monitor.isCanceled()) break;
388 // IJavaProject project = projects[i];
389 // if (!JavaProject.hasJavaNature(project.getProject())) {
390 // // project is not accessible or has lost its Java nature
393 // IClasspathEntry[] entries = project.getResolvedClasspath(true);
394 // for (int j = 0; j < entries.length; j++){
395 // if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
397 // IPath entryPath = entries[j].getPath();
399 // if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
401 // String status = (String)externalArchivesStatus.get(entryPath);
402 // if (status == null){
404 // // compute shared status
405 // Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
407 // if (targetLibrary == null){ // missing JAR
408 // if (this.externalTimeStamps.containsKey(entryPath)){
409 // this.externalTimeStamps.remove(entryPath);
410 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
411 // // the jar was physically removed: remove the index
412 // indexManager.removeIndex(entryPath);
415 // } else if (targetLibrary instanceof File){ // external JAR
417 // File externalFile = (File)targetLibrary;
419 // // check timestamp to figure if JAR has changed in some way
420 // Long oldTimestamp =(Long) this.externalTimeStamps.get(entryPath);
421 // long newTimeStamp = getTimeStamp(externalFile);
422 // if (oldTimestamp != null){
424 // if (newTimeStamp == 0){ // file doesn't exist
425 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
426 // this.externalTimeStamps.remove(entryPath);
427 // // remove the index
428 // indexManager.removeIndex(entryPath);
430 // } else if (oldTimestamp.longValue() != newTimeStamp){
431 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_CHANGED);
432 // this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
433 // // first remove the index so that it is forced to be re-indexed
434 // indexManager.removeIndex(entryPath);
435 // // then index the jar
436 // indexManager.indexLibrary(entryPath, project.getProject());
438 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
441 // if (newTimeStamp == 0){ // jar still doesn't exist
442 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
444 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_ADDED);
445 // this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
446 // // index the new jar
447 // indexManager.indexLibrary(entryPath, project.getProject());
450 // } else { // internal JAR
451 // externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
454 // // according to computed status, generate a delta
455 // status = (String)externalArchivesStatus.get(entryPath);
456 // if (status != null){
457 // if (status == EXTERNAL_JAR_ADDED){
458 // PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
460 // System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
462 // elementAdded(root, null, null);
464 // } else if (status == EXTERNAL_JAR_CHANGED) {
465 // PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
467 // System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
469 // // reset the corresponding project built state, since the builder would miss this change
470 // this.manager.setLastBuiltState(project.getProject(), null /*no state*/);
471 // contentChanged(root, null);
473 // } else if (status == EXTERNAL_JAR_REMOVED) {
474 // PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
476 // System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
478 // elementRemoved(root, null, null);
487 JavaElementDelta currentDelta() {
488 if (this.currentDelta == null) {
489 this.currentDelta = new JavaElementDelta(this.manager.getJavaModel());
491 return this.currentDelta;
495 * Process the given delta and look for projects being added, opened, closed or
496 * with a java nature being added or removed.
497 * Note that projects being deleted are checked in deleting(IProject).
498 * In all cases, add the project's dependents to the list of projects to update
499 * so that the classpath related markers can be updated.
501 // public void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
502 // IResource resource = delta.getResource();
503 // switch (resource.getType()) {
504 // case IResource.ROOT :
505 // // workaround for bug 15168 circular errors not reported
506 // if (this.manager.javaProjectsCache == null) {
508 // this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
509 // } catch (JavaModelException e) {
513 // IResourceDelta[] children = delta.getAffectedChildren();
514 // for (int i = 0, length = children.length; i < length; i++) {
515 // this.checkProjectsBeingAddedOrRemoved(children[i]);
518 // case IResource.PROJECT :
519 // // NB: No need to check project's nature as if the project is not a java project:
520 // // - if the project is added or changed this is a noop for projectsBeingDeleted
521 // // - if the project is closed, it has already lost its java nature
522 // int deltaKind = delta.getKind();
523 // if (deltaKind == IResourceDelta.ADDED) {
524 // // remember project and its dependents
525 // IProject project = (IProject)resource;
526 // this.addToProjectsToUpdateWithDependents(project);
528 // // workaround for bug 15168 circular errors not reported
529 // if (JavaProject.hasJavaNature(project)) {
530 // this.addToParentInfo((JavaProject)JavaCore.create(project));
533 // } else if (deltaKind == IResourceDelta.CHANGED) {
534 // IProject project = (IProject)resource;
535 // if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
536 // // project opened or closed: remember project and its dependents
537 // this.addToProjectsToUpdateWithDependents(project);
539 // // workaround for bug 15168 circular errors not reported
540 // if (project.isOpen()) {
541 // if (JavaProject.hasJavaNature(project)) {
542 // this.addToParentInfo((JavaProject)JavaCore.create(project));
545 // JavaProject javaProject = (JavaProject)this.manager.getJavaModel().findJavaProject(project);
546 // if (javaProject != null) {
548 // javaProject.close();
549 // } catch (JavaModelException e) {
551 // this.removeFromParentInfo(javaProject);
554 // } else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
555 // boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
556 // boolean isJavaProject = JavaProject.hasJavaNature(project);
557 // if (wasJavaProject != isJavaProject) {
558 // // java nature added or removed: remember project and its dependents
559 // this.addToProjectsToUpdateWithDependents(project);
561 // // workaround for bug 15168 circular errors not reported
562 // if (isJavaProject) {
563 // this.addToParentInfo((JavaProject)JavaCore.create(project));
565 // JavaProject javaProject = (JavaProject)JavaCore.create(project);
567 // // flush classpath markers
569 // flushClasspathProblemMarkers(
570 // true, // flush cycle markers
571 // true //flush classpath format markers
574 // // remove problems and tasks created by the builder
575 // JavaBuilder.removeProblemsAndTasksFor(project);
579 // javaProject.close();
580 // } catch (JavaModelException e) {
582 // this.removeFromParentInfo(javaProject);
585 // // in case the project was removed then added then changed (see bug 19799)
586 // if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
587 // this.addToParentInfo((JavaProject)JavaCore.create(project));
591 // // workaround for bug 15168 circular errors not reported
592 // // in case the project was removed then added then changed
593 // if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
594 // this.addToParentInfo((JavaProject)JavaCore.create(project));
602 // private void checkSourceAttachmentChange(IResourceDelta delta, IResource res) {
603 // IPath rootPath = (IPath)this.sourceAttachments.get(res.getFullPath());
604 // if (rootPath != null) {
605 // RootInfo rootInfo = this.rootInfo(rootPath, delta.getKind());
606 // if (rootInfo != null) {
607 // IJavaProject projectOfRoot = rootInfo.project;
608 // IPackageFragmentRoot root = null;
610 // // close the root so that source attachement cache is flushed
611 // root = projectOfRoot.findPackageFragmentRoot(rootPath);
612 // if (root != null) {
615 // } catch (JavaModelException e) {
617 // if (root == null) return;
618 // switch (delta.getKind()) {
619 // case IResourceDelta.ADDED:
620 // currentDelta().sourceAttached(root);
622 // case IResourceDelta.CHANGED:
623 // currentDelta().sourceDetached(root);
624 // currentDelta().sourceAttached(root);
626 // case IResourceDelta.REMOVED:
627 // currentDelta().sourceDetached(root);
635 * Closes the given element, which removes it from the cache of open elements.
637 // protected static void close(Openable element) {
641 // } catch (JavaModelException e) {
646 * Generic processing for elements with changed contents:<ul>
647 * <li>The element is closed such that any subsequent accesses will re-open
648 * the element reflecting its new structure.
649 * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
651 * Delta argument could be null if processing an external JAR change
653 // protected void contentChanged(Openable element, IResourceDelta delta) {
656 // int flags = IJavaElementDelta.F_CONTENT;
657 // if (element instanceof JarPackageFragmentRoot){
658 // flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
660 // currentDelta().changed(element, flags);
664 * Creates the openables corresponding to this resource.
665 * Returns null if none was found.
667 // protected Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
668 // if (resource == null) return null;
670 // IPath path = resource.getFullPath();
671 // IJavaElement element = null;
672 // switch (elementType) {
674 // case IJavaElement.JAVA_PROJECT:
676 // // note that non-java resources rooted at the project level will also enter this code with
677 // // an elementType JAVA_PROJECT (see #elementType(...)).
678 // if (resource instanceof IProject){
680 // this.popUntilPrefixOf(path);
682 // if (this.currentElement != null
683 // && this.currentElement.getElementType() == IJavaElement.JAVA_PROJECT
684 // && ((IJavaProject)this.currentElement).getProject().equals(resource)) {
685 // return this.currentElement;
687 // if (rootInfo != null && rootInfo.project.getProject().equals(resource)){
688 // element = (Openable)rootInfo.project;
691 // IProject proj = (IProject)resource;
692 // if (JavaProject.hasJavaNature(proj)) {
693 // element = JavaCore.create(proj);
695 // // java project may have been been closed or removed (look for
696 // // element amongst old java project s list).
697 // element = (Openable) manager.getJavaModel().findJavaProject(proj);
701 // case IJavaElement.PACKAGE_FRAGMENT_ROOT:
702 // element = rootInfo == null ? JavaCore.create(resource) : rootInfo.project.getPackageFragmentRoot(resource);
704 // case IJavaElement.PACKAGE_FRAGMENT:
705 // // find the element that encloses the resource
706 // this.popUntilPrefixOf(path);
708 // if (this.currentElement == null) {
709 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
712 // IPackageFragmentRoot root = this.currentElement.getPackageFragmentRoot();
713 // if (root == null) {
714 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
715 // } else if (((JavaProject)root.getJavaProject()).contains(resource)) {
716 // // create package handle
717 // IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
718 // String pkg = Util.packageName(pkgPath);
719 // if (pkg == null) return null;
720 // element = root.getPackageFragment(pkg);
724 // case IJavaElement.COMPILATION_UNIT:
725 // case IJavaElement.CLASS_FILE:
726 // // find the element that encloses the resource
727 // this.popUntilPrefixOf(path);
729 // if (this.currentElement == null) {
730 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
732 // // find the package
733 // IPackageFragment pkgFragment = null;
734 // switch (this.currentElement.getElementType()) {
735 // case IJavaElement.PACKAGE_FRAGMENT_ROOT:
736 // IPackageFragmentRoot root = (IPackageFragmentRoot)this.currentElement;
737 // IPath rootPath = root.getPath();
738 // IPath pkgPath = path.removeLastSegments(1);
739 // String pkgName = Util.packageName(pkgPath.removeFirstSegments(rootPath.segmentCount()));
740 // if (pkgName != null) {
741 // pkgFragment = root.getPackageFragment(pkgName);
744 // case IJavaElement.PACKAGE_FRAGMENT:
745 // Openable pkg = (Openable)this.currentElement;
746 // if (pkg.getPath().equals(path.removeLastSegments(1))) {
747 // pkgFragment = (IPackageFragment)pkg;
748 // } // else case of package x which is a prefix of x.y
750 // case IJavaElement.COMPILATION_UNIT:
751 // case IJavaElement.CLASS_FILE:
752 // pkgFragment = (IPackageFragment)this.currentElement.getParent();
755 // if (pkgFragment == null) {
756 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
758 // if (elementType == IJavaElement.COMPILATION_UNIT) {
759 // // create compilation unit handle
760 // // fileName validation has been done in elementType(IResourceDelta, int, boolean)
761 // String fileName = path.lastSegment();
762 // element = pkgFragment.getCompilationUnit(fileName);
764 // // create class file handle
765 // // fileName validation has been done in elementType(IResourceDelta, int, boolean)
766 // String fileName = path.lastSegment();
767 // element = pkgFragment.getClassFile(fileName);
773 // if (element == null) {
776 // this.currentElement = (Openable)element;
777 // return this.currentElement;
781 * Note that the project is about to be deleted.
783 // public void deleting(IProject project) {
786 // // discard indexing jobs that belong to this project so that the project can be
787 // // deleted without interferences from the index manager
788 // this.indexManager.discardJobs(project.getName());
790 // JavaProject javaProject = (JavaProject)JavaCore.create(project);
792 // // remember roots of this project
793 // if (this.removedRoots == null) {
794 // this.removedRoots = new HashMap();
796 // if (javaProject.isOpen()) {
797 // this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
799 // // compute roots without opening project
800 // this.removedRoots.put(
802 // javaProject.computePackageFragmentRoots(
803 // javaProject.getResolvedClasspath(true),
807 // javaProject.close();
809 // // workaround for bug 15168 circular errors not reported
810 // if (this.manager.javaProjectsCache == null) {
811 // this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
813 // this.removeFromParentInfo(javaProject);
815 // } catch (JavaModelException e) {
818 // this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
823 * Processing for an element that has been added:<ul>
824 * <li>If the element is a project, do nothing, and do not process
825 * children, as when a project is created it does not yet have any
826 * natures - specifically a java nature.
827 * <li>If the elemet is not a project, process it as added (see
828 * <code>basicElementAdded</code>.
830 * Delta argument could be null if processing an external JAR change
832 // protected void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
833 // int elementType = element.getElementType();
835 // if (elementType == IJavaElement.JAVA_PROJECT) {
836 // // project add is handled by JavaProject.configure() because
837 // // when a project is created, it does not yet have a java nature
838 // if (delta != null && JavaProject.hasJavaNature((IProject)delta.getResource())) {
839 // addToParentInfo(element);
840 // if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
841 // Openable movedFromElement = (Openable)element.getJavaModel().getJavaProject(delta.getMovedFromPath().lastSegment());
842 // currentDelta().movedTo(element, movedFromElement);
844 // currentDelta().added(element);
846 // this.projectsToUpdate.add(element);
847 // this.updateRoots(element.getPath(), delta);
848 // this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
851 // addToParentInfo(element);
853 // // Force the element to be closed as it might have been opened
854 // // before the resource modification came in and it might have a new child
855 // // For example, in an IWorkspaceRunnable:
856 // // 1. create a package fragment p using a java model operation
857 // // 2. open package p
858 // // 3. add file X.java in folder p
859 // // When the resource delta comes in, only the addition of p is notified,
860 // // but the package p is already opened, thus its children are not recomputed
861 // // and it appears empty.
864 // if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
865 // IPath movedFromPath = delta.getMovedFromPath();
866 // IResource res = delta.getResource();
867 // IResource movedFromRes;
868 // if (res instanceof IFile) {
869 // movedFromRes = res.getWorkspace().getRoot().getFile(movedFromPath);
871 // movedFromRes = res.getWorkspace().getRoot().getFolder(movedFromPath);
874 // // find the element type of the moved from element
875 // RootInfo movedFromInfo = this.enclosingRootInfo(movedFromPath, IResourceDelta.REMOVED);
876 // int movedFromType =
879 // IResourceDelta.REMOVED,
880 // element.getParent().getElementType(),
883 // // reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
884 // this.currentElement = null;
886 // // create the moved from element
887 // Openable movedFromElement =
888 // elementType != IJavaElement.JAVA_PROJECT && movedFromType == IJavaElement.JAVA_PROJECT ?
889 // null : // outside classpath
890 // this.createElement(movedFromRes, movedFromType, movedFromInfo);
891 // if (movedFromElement == null) {
892 // // moved from outside classpath
893 // currentDelta().added(element);
895 // currentDelta().movedTo(element, movedFromElement);
898 // currentDelta().added(element);
901 // switch (elementType) {
902 // case IJavaElement.PACKAGE_FRAGMENT_ROOT :
903 // // when a root is added, and is on the classpath, the project must be updated
904 // JavaProject project = (JavaProject) element.getJavaProject();
905 // this.projectsToUpdate.add(project);
906 // this.projectsForDependentNamelookupRefresh.add(project);
909 // case IJavaElement.PACKAGE_FRAGMENT :
910 // // get rid of namelookup since it holds onto obsolete cached info
911 // project = (JavaProject) element.getJavaProject();
913 // project.getJavaProjectElementInfo().setNameLookup(null);
914 // this.projectsForDependentNamelookupRefresh.add(project);
915 // } catch (JavaModelException e) {
917 // // add subpackages
918 // if (delta != null){
919 // PackageFragmentRoot root = element.getPackageFragmentRoot();
920 // String name = element.getElementName();
921 // IResourceDelta[] children = delta.getAffectedChildren();
922 // for (int i = 0, length = children.length; i < length; i++) {
923 // IResourceDelta child = children[i];
924 // IResource resource = child.getResource();
925 // if (resource instanceof IFolder) {
926 // String folderName = resource.getName();
927 // if (Util.isValidFolderNameForPackage(folderName)) {
928 // String subpkgName =
929 // name.length() == 0 ?
931 // name + "." + folderName; //$NON-NLS-1$
932 // Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
933 // this.updateIndex(subpkg, child);
934 // this.elementAdded(subpkg, child, rootInfo);
945 * Generic processing for a removed element:<ul>
946 * <li>Close the element, removing its structure from the cache
947 * <li>Remove the element from its parent's cache of children
948 * <li>Add a REMOVED entry in the delta
950 * Delta argument could be null if processing an external JAR change
952 // protected void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
954 // if (element.isOpen()) {
957 // removeFromParentInfo(element);
958 // int elementType = element.getElementType();
959 // if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
960 // IPath movedToPath = delta.getMovedToPath();
961 // IResource res = delta.getResource();
962 // IResource movedToRes;
963 // switch (res.getType()) {
964 // case IResource.PROJECT:
965 // movedToRes = res.getWorkspace().getRoot().getProject(movedToPath.lastSegment());
967 // case IResource.FOLDER:
968 // movedToRes = res.getWorkspace().getRoot().getFolder(movedToPath);
970 // case IResource.FILE:
971 // movedToRes = res.getWorkspace().getRoot().getFile(movedToPath);
977 // // find the element type of the moved from element
978 // RootInfo movedToInfo = this.enclosingRootInfo(movedToPath, IResourceDelta.ADDED);
982 // IResourceDelta.ADDED,
983 // element.getParent().getElementType(),
986 // // reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
987 // this.currentElement = null;
989 // // create the moved To element
990 // Openable movedToElement =
991 // elementType != IJavaElement.JAVA_PROJECT && movedToType == IJavaElement.JAVA_PROJECT ?
992 // null : // outside classpath
993 // this.createElement(movedToRes, movedToType, movedToInfo);
994 // if (movedToElement == null) {
995 // // moved outside classpath
996 // currentDelta().removed(element);
998 // currentDelta().movedFrom(element, movedToElement);
1001 // currentDelta().removed(element);
1004 // switch (elementType) {
1005 // case IJavaElement.JAVA_MODEL :
1006 // this.indexManager.reset();
1008 // case IJavaElement.JAVA_PROJECT :
1009 // this.manager.removePerProjectInfo(
1010 // (JavaProject) element);
1011 // this.updateRoots(element.getPath(), delta);
1012 // this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
1014 // case IJavaElement.PACKAGE_FRAGMENT_ROOT :
1015 // JavaProject project = (JavaProject) element.getJavaProject();
1016 // this.projectsToUpdate.add(project);
1017 // this.projectsForDependentNamelookupRefresh.add(project);
1019 // case IJavaElement.PACKAGE_FRAGMENT :
1020 // //1G1TW2T - get rid of namelookup since it holds onto obsolete cached info
1021 // project = (JavaProject) element.getJavaProject();
1023 // project.getJavaProjectElementInfo().setNameLookup(null);
1024 // this.projectsForDependentNamelookupRefresh.add(project);
1025 // } catch (JavaModelException e) {
1027 // // remove subpackages
1028 // if (delta != null){
1029 // PackageFragmentRoot root = element.getPackageFragmentRoot();
1030 // String name = element.getElementName();
1031 // IResourceDelta[] children = delta.getAffectedChildren();
1032 // for (int i = 0, length = children.length; i < length; i++) {
1033 // IResourceDelta child = children[i];
1034 // IResource resource = child.getResource();
1035 // if (resource instanceof IFolder) {
1036 // String folderName = resource.getName();
1037 // if (Util.isValidFolderNameForPackage(folderName)) {
1038 // String subpkgName =
1039 // name.length() == 0 ?
1041 // name + "." + folderName; //$NON-NLS-1$
1042 // Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
1043 // this.updateIndex(subpkg, child);
1044 // this.elementRemoved(subpkg, child, rootInfo);
1054 * Returns the type of the java element the given delta matches to.
1055 * Returns NON_JAVA_RESOURCE if unknown (e.g. a non-java resource or excluded .java file)
1057 // private int elementType(IResource res, int kind, int parentType, RootInfo rootInfo) {
1058 // switch (parentType) {
1059 // case IJavaElement.JAVA_MODEL:
1060 // // case of a movedTo or movedFrom project (other cases are handled in processResourceDelta(...)
1061 // return IJavaElement.JAVA_PROJECT;
1062 // case NON_JAVA_RESOURCE:
1063 // case IJavaElement.JAVA_PROJECT:
1064 // if (rootInfo == null) {
1065 // rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
1067 // if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
1068 // return IJavaElement.PACKAGE_FRAGMENT_ROOT;
1070 // return NON_JAVA_RESOURCE; // not yet in a package fragment root or root of another project
1072 // case IJavaElement.PACKAGE_FRAGMENT_ROOT:
1073 // case IJavaElement.PACKAGE_FRAGMENT:
1074 // if (rootInfo == null) {
1075 // rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
1077 // if (rootInfo == null || Util.isExcluded(res, rootInfo.exclusionPatterns)) {
1078 // return NON_JAVA_RESOURCE;
1080 // if (res instanceof IFolder) {
1081 // if (Util.isValidFolderNameForPackage(res.getName())) {
1082 // return IJavaElement.PACKAGE_FRAGMENT;
1084 // return NON_JAVA_RESOURCE;
1087 // String fileName = res.getName();
1088 // if (Util.isValidCompilationUnitName(fileName)) {
1089 // return IJavaElement.COMPILATION_UNIT;
1090 // } else if (Util.isValidClassFileName(fileName)) {
1091 // return IJavaElement.CLASS_FILE;
1092 // } else if (this.rootInfo(res.getFullPath(), kind) != null) {
1093 // // case of proj=src=bin and resource is a jar file on the classpath
1094 // return IJavaElement.PACKAGE_FRAGMENT_ROOT;
1096 // return NON_JAVA_RESOURCE;
1100 // return NON_JAVA_RESOURCE;
1105 * Answer a combination of the lastModified stamp and the size.
1106 * Used for detecting external JAR changes
1108 public static long getTimeStamp(File file) {
1109 return file.lastModified() + file.length();
1112 public void initializeRoots() {
1113 // remember roots infos as old roots infos
1114 this.oldRoots = this.roots == null ? new HashMap() : this.roots;
1115 this.oldOtherRoots = this.otherRoots == null ? new HashMap() : this.otherRoots;
1117 // recompute root infos only if necessary
1118 if (!rootsAreStale) return;
1120 this.roots = new HashMap();
1121 this.otherRoots = new HashMap();
1122 this.sourceAttachments = new HashMap();
1124 IJavaModel model = this.manager.getJavaModel();
1125 IJavaProject[] projects;
1127 projects = model.getJavaProjects();
1128 } catch (JavaModelException e) {
1129 // nothing can be done
1132 for (int i = 0, length = projects.length; i < length; i++) {
1133 IJavaProject project = projects[i];
1134 IClasspathEntry[] classpath;
1136 classpath = project.getResolvedClasspath(true);
1137 } catch (JavaModelException e) {
1138 // continue with next project
1141 for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
1142 IClasspathEntry entry = classpath[j];
1143 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
1146 IPath path = entry.getPath();
1147 if (this.roots.get(path) == null) {
1148 this.roots.put(path, new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
1150 ArrayList rootList = (ArrayList)this.otherRoots.get(path);
1151 if (rootList == null) {
1152 rootList = new ArrayList();
1153 this.otherRoots.put(path, rootList);
1155 rootList.add(new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
1158 // source attachment path
1159 if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
1160 QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
1161 String propertyString = null;
1163 propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
1164 } catch (CoreException e) {
1167 IPath sourceAttachmentPath;
1168 // if (propertyString != null) {
1169 // int index= propertyString.lastIndexOf(JarPackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER);
1170 // sourceAttachmentPath = (index < 0) ? new Path(propertyString) : new Path(propertyString.substring(0, index));
1172 sourceAttachmentPath = entry.getSourceAttachmentPath();
1174 if (sourceAttachmentPath != null) {
1175 this.sourceAttachments.put(sourceAttachmentPath, path);
1179 this.rootsAreStale = false;
1183 * Returns whether a given delta contains some information relevant to the JavaModel,
1184 * in particular it will not consider SYNC or MARKER only deltas.
1186 public boolean isAffectedBy(IResourceDelta rootDelta){
1187 //if (rootDelta == null) System.out.println("NULL DELTA");
1188 //long start = System.currentTimeMillis();
1189 if (rootDelta != null) {
1190 // use local exception to quickly escape from delta traversal
1191 class FoundRelevantDeltaException extends RuntimeException {}
1193 rootDelta.accept(new IResourceDeltaVisitor() {
1194 public boolean visit(IResourceDelta delta) throws CoreException {
1195 switch (delta.getKind()){
1196 case IResourceDelta.ADDED :
1197 case IResourceDelta.REMOVED :
1198 throw new FoundRelevantDeltaException();
1199 case IResourceDelta.CHANGED :
1200 // if any flag is set but SYNC or MARKER, this delta should be considered
1201 if (delta.getAffectedChildren().length == 0 // only check leaf delta nodes
1202 && (delta.getFlags() & ~(IResourceDelta.SYNC | IResourceDelta.MARKERS)) != 0) {
1203 throw new FoundRelevantDeltaException();
1209 } catch(FoundRelevantDeltaException e) {
1210 //System.out.println("RELEVANT DELTA detected in: "+ (System.currentTimeMillis() - start));
1212 } catch(CoreException e) { // ignore delta if not able to traverse
1215 //System.out.println("IGNORE SYNC DELTA took: "+ (System.currentTimeMillis() - start));
1220 * Returns whether the given resource is in one of the given output folders and if
1221 * it is filtered out from this output folder.
1223 private boolean isResFilteredFromOutput(OutputsInfo info, IResource res, int elementType) {
1225 IPath resPath = res.getFullPath();
1226 for (int i = 0; i < info.outputCount; i++) {
1227 if (info.paths[i].isPrefixOf(resPath)) {
1228 if (info.traverseModes[i] != IGNORE) {
1230 if (info.traverseModes[i] == SOURCE && elementType == IJavaElement.CLASS_FILE) {
1233 // case of .class file under project and no source folder
1235 if (elementType == IJavaElement.JAVA_PROJECT
1236 && res instanceof IFile
1237 && PHPFileUtil.isPHPFile((IFile)res)) {
1250 * Merges all awaiting deltas.
1252 private IJavaElementDelta mergeDeltas(Collection deltas) {
1253 if (deltas.size() == 0) return null;
1254 if (deltas.size() == 1) return (IJavaElementDelta)deltas.iterator().next();
1257 System.out.println("MERGING " + deltas.size() + " DELTAS ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1260 Iterator iterator = deltas.iterator();
1261 JavaElementDelta rootDelta = new JavaElementDelta(this.manager.javaModel);
1262 boolean insertedTree = false;
1263 while (iterator.hasNext()) {
1264 JavaElementDelta delta = (JavaElementDelta)iterator.next();
1266 System.out.println(delta.toString());
1268 IJavaElement element = delta.getElement();
1269 if (this.manager.javaModel.equals(element)) {
1270 IJavaElementDelta[] children = delta.getAffectedChildren();
1271 for (int j = 0; j < children.length; j++) {
1272 JavaElementDelta projectDelta = (JavaElementDelta) children[j];
1273 rootDelta.insertDeltaTree(projectDelta.getElement(), projectDelta);
1274 insertedTree = true;
1276 IResourceDelta[] resourceDeltas = delta.getResourceDeltas();
1277 if (resourceDeltas != null) {
1278 for (int i = 0, length = resourceDeltas.length; i < length; i++) {
1279 rootDelta.addResourceDelta(resourceDeltas[i]);
1280 insertedTree = true;
1284 rootDelta.insertDeltaTree(element, delta);
1285 insertedTree = true;
1288 if (insertedTree) return rootDelta;
1293 * Check whether the updated file is affecting some of the properties of a given project (like
1294 * its classpath persisted as a file).
1295 * Also force classpath problems to be refresh if not running in autobuild mode.
1296 * NOTE: It can induce resource changes, and cannot be called during POST_CHANGE notification.
1299 // public void performPreBuildCheck(
1300 // IResourceDelta delta,
1301 // IJavaElement parent) {
1303 // IResource resource = delta.getResource();
1304 // IJavaElement element = null;
1305 // boolean processChildren = false;
1307 // switch (resource.getType()) {
1309 // case IResource.ROOT :
1310 // if (delta.getKind() == IResourceDelta.CHANGED) {
1311 // element = JavaCore.create(resource);
1312 // processChildren = true;
1315 // case IResource.PROJECT :
1316 // int kind = delta.getKind();
1318 // case IResourceDelta.CHANGED:
1319 // // do not visit non-java projects (see bug 16140 Non-java project gets .classpath)
1320 // IProject project = (IProject)resource;
1321 // if (JavaProject.hasJavaNature(project)) {
1322 // element = JavaCore.create(resource);
1323 // processChildren = true;
1324 // } else if (JavaModelManager.getJavaModelManager().getJavaModel().findJavaProject(project) != null) {
1325 // // project had the java nature
1326 // this.rootsAreStale = true;
1328 // // remove classpath cache so that initializeRoots() will not consider the project has a classpath
1329 // this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
1332 // case IResourceDelta.ADDED:
1333 // this.rootsAreStale = true;
1335 // case IResourceDelta.REMOVED:
1336 // // remove classpath cache so that initializeRoots() will not consider the project has a classpath
1337 // this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
1339 // this.rootsAreStale = true;
1343 // case IResource.FILE :
1344 // if (parent.getElementType() == IJavaElement.JAVA_PROJECT) {
1345 // IFile file = (IFile) resource;
1346 // JavaProject project = (JavaProject) parent;
1348 // /* check classpath file change */
1349 // if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
1350 // reconcileClasspathFileUpdate(delta, file, project);
1351 // this.rootsAreStale = true;
1354 //// /* check custom preference file change */
1355 //// if (file.getName().equals(JavaProject.PREF_FILENAME)) {
1356 //// reconcilePreferenceFileUpdate(delta, file, project);
1362 // if (processChildren) {
1363 // IResourceDelta[] children = delta.getAffectedChildren();
1364 // for (int i = 0; i < children.length; i++) {
1365 // performPreBuildCheck(children[i], element);
1370 // private void popUntilPrefixOf(IPath path) {
1371 // while (this.currentElement != null) {
1372 // IPath currentElementPath = null;
1373 // if (this.currentElement instanceof IPackageFragmentRoot) {
1374 // currentElementPath = ((IPackageFragmentRoot)this.currentElement).getPath();
1376 // IResource currentElementResource = this.currentElement.getResource();
1377 // if (currentElementResource != null) {
1378 // currentElementPath = currentElementResource.getFullPath();
1381 // if (currentElementPath != null) {
1382 // if (this.currentElement instanceof IPackageFragment
1383 // && this.currentElement.getElementName().length() == 0
1384 // && currentElementPath.segmentCount() != path.segmentCount()-1) {
1385 // // default package and path is not a direct child
1386 // this.currentElement = (Openable)this.currentElement.getParent();
1388 // if (currentElementPath.isPrefixOf(path)) {
1392 // this.currentElement = (Openable)this.currentElement.getParent();
1397 * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
1398 * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
1399 * relevant <code>JavaModel</code>s.
1403 * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
1404 * call to JavaProject#setRawClasspath or as a result of some user update (through repository)
1406 // void reconcileClasspathFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
1408 // switch (delta.getKind()) {
1409 // case IResourceDelta.REMOVED : // recreate one based on in-memory classpath
1411 // JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
1412 // if (info.classpath != null) { // if there is an in-memory classpath
1413 // project.saveClasspath(info.classpath, info.outputLocation);
1415 // } catch (JavaModelException e) {
1416 // if (project.getProject().isAccessible()) {
1417 // Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
1421 // case IResourceDelta.CHANGED :
1422 // if ((delta.getFlags() & IResourceDelta.CONTENT) == 0 // only consider content change
1423 // && (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
1425 // case IResourceDelta.ADDED :
1426 // // check if any actual difference
1427 // project.flushClasspathProblemMarkers(false, true);
1428 // boolean wasSuccessful = false; // flag recording if .classpath file change got reflected
1430 // // force to (re)read the property file
1431 // IClasspathEntry[] fileEntries = project.readClasspathFile(true/*create markers*/, false/*don't log problems*/);
1432 // if (fileEntries == null)
1433 // break; // could not read, ignore
1434 // JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
1435 // if (info.classpath != null) { // if there is an in-memory classpath
1436 // if (project.isClasspathEqualsTo(info.classpath, info.outputLocation, fileEntries)) {
1437 // wasSuccessful = true;
1442 // // will force an update of the classpath/output location based on the file information
1443 // // extract out the output location
1444 // IPath outputLocation = null;
1445 // if (fileEntries != null && fileEntries.length > 0) {
1446 // IClasspathEntry entry = fileEntries[fileEntries.length - 1];
1447 // if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
1448 // outputLocation = entry.getPath();
1449 // IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
1450 // System.arraycopy(fileEntries, 0, copy, 0, copy.length);
1451 // fileEntries = copy;
1454 // // restore output location
1455 // if (outputLocation == null) {
1456 // outputLocation = SetClasspathOperation.ReuseOutputLocation;
1457 // // clean mode will also default to reusing current one
1459 // project.setRawClasspath(
1463 // true, // canChangeResource
1464 // project.getResolvedClasspath(true), // ignoreUnresolvedVariable
1465 // true, // needValidation
1466 // false); // no need to save
1468 // // if reach that far, the classpath file change got absorbed
1469 // wasSuccessful = true;
1470 // } catch (RuntimeException e) {
1471 // // setRawClasspath might fire a delta, and a listener may throw an exception
1472 // if (project.getProject().isAccessible()) {
1473 // Util.log(e, "Could not set classpath for "+ project.getPath()); //$NON-NLS-1$
1476 // } catch (JavaModelException e) { // CP failed validation
1477 // if (project.getProject().isAccessible()) {
1478 // if (e.getJavaModelStatus().getException() instanceof CoreException) {
1479 // // happens if the .classpath could not be written to disk
1480 // project.createClasspathProblemMarker(new JavaModelStatus(
1481 // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1482 // Util.bind("classpath.couldNotWriteClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
1484 // project.createClasspathProblemMarker(new JavaModelStatus(
1485 // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1486 // Util.bind("classpath.invalidClasspathInClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
1491 // if (!wasSuccessful) {
1493 // project.setRawClasspath0(JavaProject.INVALID_CLASSPATH);
1494 // project.updatePackageFragmentRoots();
1495 // } catch (JavaModelException e) {
1503 * Update the JavaModel according to a .jprefs file change. The file can have changed as a result of a previous
1504 * call to JavaProject#setOptions or as a result of some user update (through repository)
1505 * Unused until preference file get shared (.jpref)
1507 // void reconcilePreferenceFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
1509 // switch (delta.getKind()) {
1510 // case IResourceDelta.REMOVED : // flush project custom settings
1511 // project.setOptions(null);
1513 // case IResourceDelta.CHANGED :
1514 // if ((delta.getFlags() & IResourceDelta.CONTENT) == 0 // only consider content change
1515 // && (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move and overide scenario
1517 // identityCheck : { // check if any actual difference
1518 // // force to (re)read the property file
1519 // Preferences filePreferences = project.loadPreferences();
1520 // if (filePreferences == null){
1521 // project.setOptions(null); // should have got removed delta.
1524 // Preferences projectPreferences = project.getPreferences();
1525 // if (projectPreferences == null) return; // not a Java project
1527 // // compare preferences set to their default
1528 // String[] defaultProjectPropertyNames = projectPreferences.defaultPropertyNames();
1529 // String[] defaultFilePropertyNames = filePreferences.defaultPropertyNames();
1530 // if (defaultProjectPropertyNames.length == defaultFilePropertyNames.length) {
1531 // for (int i = 0; i < defaultProjectPropertyNames.length; i++){
1532 // String propertyName = defaultProjectPropertyNames[i];
1533 // if (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
1534 // break identityCheck;
1537 // } else break identityCheck;
1539 // // compare custom preferences not set to their default
1540 // String[] projectPropertyNames = projectPreferences.propertyNames();
1541 // String[] filePropertyNames = filePreferences.propertyNames();
1542 // if (projectPropertyNames.length == filePropertyNames.length) {
1543 // for (int i = 0; i < projectPropertyNames.length; i++){
1544 // String propertyName = projectPropertyNames[i];
1545 // if (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
1546 // break identityCheck;
1549 // } else break identityCheck;
1551 // // identical - do nothing
1554 // case IResourceDelta.ADDED :
1555 // // not identical, create delta and reset cached preferences
1556 // project.setPreferences(null);
1558 // //fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);
1562 * Registers the given delta with this delta processor.
1564 public void registerJavaModelDelta(IJavaElementDelta delta) {
1565 this.javaModelDeltas.add(delta);
1568 * Removes the given element from its parents cache of children. If the
1569 * element does not have a parent, or the parent is not currently open,
1570 * this has no effect.
1572 protected void removeFromParentInfo(Openable child) {
1574 Openable parent = (Openable) child.getParent();
1575 if (parent != null && parent.isOpen()) {
1577 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
1578 info.removeChild(child);
1579 } catch (JavaModelException e) {
1580 // do nothing - we already checked if open
1586 * Notification that some resource changes have happened
1587 * on the platform, and that the Java Model should update any required
1588 * internal structures such that its elements remain consistent.
1589 * Translates <code>IResourceDeltas</code> into <code>IJavaElementDeltas</code>.
1591 * @see IResourceDelta
1594 public void resourceChanged(IResourceChangeEvent event) {
1595 if (event.getSource() instanceof IWorkspace) {
1596 int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
1597 IResource resource = event.getResource();
1598 IResourceDelta delta = event.getDelta();
1601 case IResourceChangeEvent.PRE_DELETE :
1603 if(resource.getType() == IResource.PROJECT
1604 && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
1606 deleting((IProject)resource);
1608 } catch(CoreException e){
1609 // project doesn't exist or is not open: ignore
1613 case IResourceChangeEvent.POST_CHANGE :
1614 if (isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
1618 // checkProjectsBeingAddedOrRemoved(delta);
1619 // if (this.refreshedElements != null) {
1620 // createExternalArchiveDelta(null);
1622 IJavaElementDelta translatedDelta = processResourceDelta(delta);
1623 if (translatedDelta != null) {
1624 registerJavaModelDelta(translatedDelta);
1629 // notifyTypeHierarchies(this.state.elementChangedListeners, this.state.elementChangedListenerCount);
1630 fire(null, ElementChangedEvent.POST_CHANGE);
1632 // workaround for bug 15168 circular errors not reported
1633 this.state.modelProjectsCache = null;
1634 this.removedRoots = null;
1639 case IResourceChangeEvent.PRE_BUILD :
1640 DeltaProcessingState.ProjectUpdateInfo[] updates = this.state.removeAllProjectUpdates();
1641 if (updates != null) {
1642 for (int i = 0, length = updates.length; i < length; i++) {
1644 updates[i].updateProjectReferencesIfNecessary();
1645 } catch(JavaModelException e) {
1650 // this.processPostChange = false;
1651 if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
1652 // updateClasspathMarkers(delta);
1653 PHPBuilder.buildStarting();
1655 // does not fire any deltas
1658 case IResourceChangeEvent.POST_BUILD :
1659 PHPBuilder.buildFinished();
1663 // // jsurfer TODO compare 3.0 sources
1664 // if (event.getSource() instanceof IWorkspace) {
1665 // int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
1666 // IResource resource = event.getResource();
1667 // IResourceDelta delta = event.getDelta();
1669 // switch(eventType){
1670 // case IResourceChangeEvent.PRE_DELETE :
1672 // if(resource.getType() == IResource.PROJECT
1673 // && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
1674 // // TODO jsurfer temp-del
1675 //// this.deleting((IProject)resource);
1677 // } catch(CoreException e){
1681 // case IResourceChangeEvent.PRE_BUILD :
1682 //// TODO jsurfer temp-del
1683 //// if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
1684 //// this.checkProjectsBeingAddedOrRemoved(delta);
1686 //// // update the classpath related markers
1687 //// this.updateClasspathMarkers();
1689 //// // the following will close project if affected by the property file change
1691 //// // don't fire classpath change deltas right away, but batch them
1692 //// this.manager.stopDeltas();
1693 //// this.performPreBuildCheck(delta, null);
1695 //// this.manager.startDeltas();
1698 // // only fire already computed deltas (resource ones will be processed in post change only)
1699 // this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
1702 // case IResourceChangeEvent.POST_BUILD :
1703 //// TODO jsurfer temp-del
1704 //// JavaBuilder.finishedBuilding(event);
1707 // case IResourceChangeEvent.POST_CHANGE :
1708 //// TODO jsurfer temp-del
1709 //// if (isAffectedBy(delta)) {
1711 //// if (this.refreshedElements != null) {
1713 //// createExternalArchiveDelta(null);
1714 //// } catch (JavaModelException e) {
1715 //// e.printStackTrace();
1718 //// IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
1719 //// if (translatedDelta != null) {
1720 //// this.manager.registerJavaModelDelta(translatedDelta);
1722 //// this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
1724 //// // workaround for bug 15168 circular errors not reported
1725 //// this.manager.javaProjectsCache = null;
1726 //// this.removedRoots = null;
1733 * Turns the firing mode to on. That is, deltas that are/have been
1734 * registered will be fired.
1736 private void startDeltas() {
1737 this.isFiring= true;
1740 * Turns the firing mode to off. That is, deltas that are/have been
1741 * registered will not be fired until deltas are started again.
1743 private void stopDeltas() {
1744 this.isFiring= false;
1747 * Note that the project is about to be deleted.
1749 private void deleting(IProject project) {
1752 // discard indexing jobs that belong to this project so that the project can be
1753 // deleted without interferences from the index manager
1754 // this.manager.indexManager.discardJobs(project.getName());
1756 JavaProject javaProject = (JavaProject)JavaCore.create(project);
1758 // remember roots of this project
1759 if (this.removedRoots == null) {
1760 this.removedRoots = new HashMap();
1762 if (javaProject.isOpen()) {
1763 this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
1765 // compute roots without opening project
1766 // this.removedRoots.put(
1768 // javaProject.computePackageFragmentRoots(
1769 // javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
1773 javaProject.close();
1775 // workaround for bug 15168 circular errors not reported
1776 if (this.state.modelProjectsCache == null) {
1777 this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
1779 this.removeFromParentInfo(javaProject);
1781 } catch (JavaModelException e) {
1782 // java project doesn't exist: ignore
1786 * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
1787 * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
1788 * relevant <code>JavaModel</code>s.
1790 private IJavaElementDelta processResourceDelta(IResourceDelta changes) {
1793 IJavaModel model = this.manager.getJavaModel();
1794 if (!model.isOpen()) {
1795 // force opening of java model so that java element delta are reported
1798 } catch (JavaModelException e) {
1800 e.printStackTrace();
1805 this.state.initializeRoots();
1806 this.currentElement = null;
1808 // get the workspace delta, and start processing there.
1809 IResourceDelta[] deltas = changes.getAffectedChildren();
1810 for (int i = 0; i < deltas.length; i++) {
1811 IResourceDelta delta = deltas[i];
1812 IResource res = delta.getResource();
1814 // find out the element type
1815 RootInfo rootInfo = null;
1817 IProject proj = (IProject)res;
1818 boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(proj) != null;
1819 boolean isJavaProject = JavaProject.hasJavaNature(proj);
1820 if (!wasJavaProject && !isJavaProject) {
1821 elementType = NON_JAVA_RESOURCE;
1823 rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
1824 if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
1825 elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
1827 elementType = IJavaElement.JAVA_PROJECT;
1832 // this.traverseDelta(delta, elementType, rootInfo, null);
1834 if (elementType == NON_JAVA_RESOURCE
1835 || (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project has changed nature (description or open/closed)
1837 // add child as non java resource
1838 nonJavaResourcesChanged((JavaModel)model, delta);
1839 } catch (JavaModelException e) {
1840 // java model could not be opened
1845 // refreshPackageFragmentRoots();
1846 // resetProjectCaches();
1848 return this.currentDelta;
1850 this.currentDelta = null;
1851 // this.rootsToRefresh.clear();
1852 // this.projectCachesToReset.clear();
1857 * Converts an <code>IResourceDelta</code> and its children into
1858 * the corresponding <code>IJavaElementDelta</code>s.
1860 // private void traverseDelta(
1861 // IResourceDelta delta,
1863 // RootInfo rootInfo,
1864 // OutputsInfo outputsInfo) {
1866 // IResource res = delta.getResource();
1868 // // set stack of elements
1869 // if (this.currentElement == null && rootInfo != null) {
1870 //// this.currentElement = rootInfo.project;
1873 // // process current delta
1874 // boolean processChildren = true;
1875 // if (res instanceof IProject) {
1876 // processChildren =
1877 // this.updateCurrentDeltaAndIndex(
1879 // elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ?
1880 // IJavaElement.JAVA_PROJECT : // case of prj=src
1883 // } else if (rootInfo != null) {
1884 // processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
1886 // // not yet inside a package fragment root
1887 // processChildren = true;
1890 // // get the project's output locations and traverse mode
1891 // if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
1893 // // process children if needed
1894 // if (processChildren) {
1895 // IResourceDelta[] children = delta.getAffectedChildren();
1896 // boolean oneChildOnClasspath = false;
1897 // int length = children.length;
1898 // IResourceDelta[] orphanChildren = null;
1899 // Openable parent = null;
1900 // boolean isValidParent = true;
1901 // for (int i = 0; i < length; i++) {
1902 // IResourceDelta child = children[i];
1903 // IResource childRes = child.getResource();
1905 // // check source attachment change
1906 // this.checkSourceAttachmentChange(child, childRes);
1908 // // find out whether the child is a package fragment root of the current project
1909 // IPath childPath = childRes.getFullPath();
1910 // int childKind = child.getKind();
1911 // RootInfo childRootInfo = this.rootInfo(childPath, childKind);
1912 // if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
1913 // // package fragment root of another project (dealt with later)
1914 // childRootInfo = null;
1917 // // compute child type
1919 // this.elementType(
1923 // rootInfo == null ? childRootInfo : rootInfo
1926 // // is childRes in the output folder and is it filtered out ?
1927 // boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);
1929 // boolean isNestedRoot = rootInfo != null && childRootInfo != null;
1930 // if (!isResFilteredFromOutput
1931 // && !isNestedRoot) { // do not treat as non-java rsc if nested root
1933 // this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo); // traverse delta for child in the same project
1935 // if (childType == NON_JAVA_RESOURCE) {
1936 // if (rootInfo != null) { // if inside a package fragment root
1937 // if (!isValidParent) continue;
1938 // if (parent == null) {
1939 // // find the parent of the non-java resource to attach to
1940 // if (this.currentElement == null
1941 // || !rootInfo.project.equals(this.currentElement.getJavaProject())) { // note if currentElement is the IJavaModel, getJavaProject() is null
1942 // // force the currentProject to be used
1943 // this.currentElement = rootInfo.project;
1945 // if (elementType == IJavaElement.JAVA_PROJECT
1946 // || (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT
1947 // && res instanceof IProject)) {
1948 // // NB: attach non-java resource to project (not to its package fragment root)
1949 // parent = rootInfo.project;
1951 // parent = this.createElement(res, elementType, rootInfo);
1953 // if (parent == null) {
1954 // isValidParent = false;
1958 // // add child as non java resource
1960 // nonJavaResourcesChanged(parent, child);
1961 // } catch (JavaModelException e) {
1965 // // the non-java resource (or its parent folder) will be attached to the java project
1966 // if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
1967 // orphanChildren[i] = child;
1970 // oneChildOnClasspath = true;
1973 // oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
1976 // // if child is a nested root
1977 // // or if it is not a package fragment root of the current project
1978 // // but it is a package fragment root of another project, traverse delta too
1980 // || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) {
1981 // this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
1984 // // if the child is a package fragment root of one or several other projects
1985 // ArrayList rootList;
1986 // if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
1987 // Iterator iterator = rootList.iterator();
1988 // while (iterator.hasNext()) {
1989 // childRootInfo = (RootInfo) iterator.next();
1990 // this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
1994 // if (orphanChildren != null
1995 // && (oneChildOnClasspath // orphan children are siblings of a package fragment root
1996 // || res instanceof IProject)) { // non-java resource directly under a project
1998 // // attach orphan children
1999 // IProject rscProject = res.getProject();
2000 // JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
2001 // if (adoptiveProject != null
2002 // && JavaProject.hasJavaNature(rscProject)) { // delta iff Java project (18698)
2003 // for (int i = 0; i < length; i++) {
2004 // if (orphanChildren[i] != null) {
2006 // nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
2007 // } catch (JavaModelException e) {
2013 // } // else resource delta will be added by parent
2014 // } // else resource delta will be added by parent
2016 private void notifyListeners(IJavaElementDelta deltaToNotify, int eventType, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) {
2017 final ElementChangedEvent extraEvent = new ElementChangedEvent(deltaToNotify, eventType);
2018 for (int i= 0; i < listenerCount; i++) {
2019 if ((listenerMask[i] & eventType) != 0){
2020 final IElementChangedListener listener = listeners[i];
2023 System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
2024 start = System.currentTimeMillis();
2026 // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
2027 Platform.run(new ISafeRunnable() {
2028 public void handleException(Throwable exception) {
2029 Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
2031 public void run() throws Exception {
2032 listener.elementChanged(extraEvent);
2036 System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
2041 // private void notifyTypeHierarchies(IElementChangedListener[] listeners, int listenerCount) {
2042 // for (int i= 0; i < listenerCount; i++) {
2043 // final IElementChangedListener listener = listeners[i];
2044 // if (!(listener instanceof TypeHierarchy)) continue;
2046 // // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
2047 // Platform.run(new ISafeRunnable() {
2048 // public void handleException(Throwable exception) {
2049 // Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
2051 // public void run() throws Exception {
2052 // TypeHierarchy typeHierarchy = (TypeHierarchy)listener;
2053 // if (typeHierarchy.hasFineGrainChanges()) {
2054 // // case of changes in primary working copies
2055 // typeHierarchy.needsRefresh = true;
2056 // typeHierarchy.fireChange();
2063 * Generic processing for elements with changed contents:<ul>
2064 * <li>The element is closed such that any subsequent accesses will re-open
2065 * the element reflecting its new structure.
2066 * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
2069 private void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
2070 throws JavaModelException {
2072 // reset non-java resources if element was open
2073 if (element.isOpen()) {
2074 JavaElementInfo info = (JavaElementInfo)element.getElementInfo();
2075 switch (element.getElementType()) {
2076 case IJavaElement.JAVA_MODEL :
2077 ((JavaModelInfo) info).nonJavaResources = null;
2078 currentDelta().addResourceDelta(delta);
2080 case IJavaElement.JAVA_PROJECT :
2081 ((JavaProjectElementInfo) info).setNonJavaResources(null);
2083 // if a package fragment root is the project, clear it too
2084 JavaProject project = (JavaProject) element;
2085 PackageFragmentRoot projectRoot =
2086 (PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject());
2087 if (projectRoot.isOpen()) {
2088 ((PackageFragmentRootInfo) projectRoot.getElementInfo()).setNonJavaResources(
2092 case IJavaElement.PACKAGE_FRAGMENT :
2093 ((PackageFragmentInfo) info).setNonJavaResources(null);
2095 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
2096 ((PackageFragmentRootInfo) info).setNonJavaResources(null);
2100 JavaElementDelta current = currentDelta();
2101 JavaElementDelta elementDelta = current.find(element);
2102 if (elementDelta == null) {
2103 // don't use find after creating the delta as it can be null (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63434)
2104 elementDelta = current.changed(element, IJavaElementDelta.F_CONTENT);
2106 elementDelta.addResourceDelta(delta);
2109 * Flushes all deltas without firing them.
2111 public void flush() {
2112 this.javaModelDeltas = new ArrayList();
2115 * Finds the root info this path is included in.
2116 * Returns null if not found.
2118 RootInfo enclosingRootInfo(IPath path, int kind) {
2119 while (path != null && path.segmentCount() > 0) {
2120 RootInfo rootInfo = this.rootInfo(path, kind);
2121 if (rootInfo != null) return rootInfo;
2122 path = path.removeLastSegments(1);
2127 * Fire Java Model delta, flushing them after the fact after post_change notification.
2128 * If the firing mode has been turned off, this has no effect.
2130 public void fire(IJavaElementDelta customDelta, int eventType) {
2131 if (!this.isFiring) return;
2134 System.out.println("-----------------------------------------------------------------------------------------------------------------------");//$NON-NLS-1$
2137 IJavaElementDelta deltaToNotify;
2138 if (customDelta == null){
2139 deltaToNotify = this.mergeDeltas(this.javaModelDeltas);
2141 deltaToNotify = customDelta;
2144 // Refresh internal scopes
2145 // if (deltaToNotify != null) {
2146 // Iterator scopes = this.manager.searchScopes.keySet().iterator();
2147 // while (scopes.hasNext()) {
2148 // AbstractSearchScope scope = (AbstractSearchScope)scopes.next();
2149 // scope.processDelta(deltaToNotify);
2155 // Important: if any listener reacts to notification by updating the listeners list or mask, these lists will
2156 // be duplicated, so it is necessary to remember original lists in a variable (since field values may change under us)
2157 IElementChangedListener[] listeners = this.state.elementChangedListeners;
2158 int[] listenerMask = this.state.elementChangedListenerMasks;
2159 int listenerCount = this.state.elementChangedListenerCount;
2161 switch (eventType) {
2162 case DEFAULT_CHANGE_EVENT:
2163 firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
2164 fireReconcileDelta(listeners, listenerMask, listenerCount);
2166 case ElementChangedEvent.POST_CHANGE:
2167 firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
2168 fireReconcileDelta(listeners, listenerMask, listenerCount);
2173 private void firePostChangeDelta(
2174 IJavaElementDelta deltaToNotify,
2175 IElementChangedListener[] listeners,
2177 int listenerCount) {
2179 // post change deltas
2181 System.out.println("FIRING POST_CHANGE Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$
2182 System.out.println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
2184 if (deltaToNotify != null) {
2185 // flush now so as to keep listener reactions to post their own deltas for subsequent iteration
2188 notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE, listeners, listenerMask, listenerCount);
2191 private void fireReconcileDelta(
2192 IElementChangedListener[] listeners,
2194 int listenerCount) {
2197 IJavaElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas.values());
2199 System.out.println("FIRING POST_RECONCILE Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$
2200 System.out.println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
2202 if (deltaToNotify != null) {
2203 // flush now so as to keep listener reactions to post their own deltas for subsequent iteration
2204 this.reconcileDeltas = new HashMap();
2206 notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE, listeners, listenerMask, listenerCount);
2210 * Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
2212 RootInfo rootInfo(IPath path, int kind) {
2213 if (kind == IResourceDelta.REMOVED) {
2214 return (RootInfo)this.oldRoots.get(path);
2216 return (RootInfo)this.roots.get(path);
2220 * Returns the other root infos for the given path. Look in the old other roots table if kind is REMOVED.
2222 ArrayList otherRootsInfo(IPath path, int kind) {
2223 if (kind == IResourceDelta.REMOVED) {
2224 return (ArrayList)this.oldOtherRoots.get(path);
2226 return (ArrayList)this.otherRoots.get(path);
2231 * Converts an <code>IResourceDelta</code> and its children into
2232 * the corresponding <code>IJavaElementDelta</code>s.
2233 * Return whether the delta corresponds to a java element.
2234 * If it is not a java element, it will be added as a non-java
2235 * resource by the sender of this method.
2237 // protected boolean traverseDelta(
2238 // IResourceDelta delta,
2240 // RootInfo rootInfo,
2241 // OutputsInfo outputsInfo) {
2243 // IResource res = delta.getResource();
2245 // // set stack of elements
2246 // if (this.currentElement == null && rootInfo != null) {
2247 // this.currentElement = (Openable)rootInfo.project;
2250 // // process current delta
2251 // boolean processChildren = true;
2252 // if (res instanceof IProject) {
2253 // processChildren =
2254 // this.updateCurrentDeltaAndIndex(
2256 // elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ?
2257 // IJavaElement.JAVA_PROJECT : // case of prj=src
2260 // } else if (rootInfo != null) {
2261 // processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
2263 // // not yet inside a package fragment root
2264 // processChildren = true;
2267 // // get the project's output locations and traverse mode
2268 // if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
2270 // // process children if needed
2271 // if (processChildren) {
2272 // IResourceDelta[] children = delta.getAffectedChildren();
2273 // boolean oneChildOnClasspath = false;
2274 // int length = children.length;
2275 // IResourceDelta[] orphanChildren = null;
2276 // Openable parent = null;
2277 // boolean isValidParent = true;
2278 // for (int i = 0; i < length; i++) {
2279 // IResourceDelta child = children[i];
2280 // IResource childRes = child.getResource();
2282 // // check source attachment change
2283 // this.checkSourceAttachmentChange(child, childRes);
2285 // // find out whether the child is a package fragment root of the current project
2286 // IPath childPath = childRes.getFullPath();
2287 // int childKind = child.getKind();
2288 // RootInfo childRootInfo = this.rootInfo(childPath, childKind);
2289 // if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
2290 // // package fragment root of another project (dealt with later)
2291 // childRootInfo = null;
2294 // // compute child type
2296 // this.elementType(
2300 // rootInfo == null ? childRootInfo : rootInfo
2303 // // is childRes in the output folder and is it filtered out ?
2304 // boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);
2306 // boolean isNestedRoot = rootInfo != null && childRootInfo != null;
2307 // if (!isResFilteredFromOutput
2308 // && !isNestedRoot) { // do not treat as non-java rsc if nested root
2309 // if (!this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo)) { // traverse delta for child in the same project
2310 // // it is a non-java resource
2312 // if (rootInfo != null) { // if inside a package fragment root
2313 // if (!isValidParent) continue;
2314 // if (parent == null) {
2315 // // find the parent of the non-java resource to attach to
2316 // if (this.currentElement == null
2317 // || !this.currentElement.getJavaProject().equals(rootInfo.project)) {
2318 // // force the currentProject to be used
2319 // this.currentElement = (Openable)rootInfo.project;
2321 // if (elementType == IJavaElement.JAVA_PROJECT
2322 // || (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT
2323 // && res instanceof IProject)) {
2324 // // NB: attach non-java resource to project (not to its package fragment root)
2325 // parent = (Openable)rootInfo.project;
2327 // parent = this.createElement(res, elementType, rootInfo);
2329 // if (parent == null) {
2330 // isValidParent = false;
2334 // // add child as non java resource
2335 // nonJavaResourcesChanged(parent, child);
2337 // // the non-java resource (or its parent folder) will be attached to the java project
2338 // if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
2339 // orphanChildren[i] = child;
2341 // } catch (JavaModelException e) {
2344 // oneChildOnClasspath = true;
2347 // oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
2350 // // if child is a nested root
2351 // // or if it is not a package fragment root of the current project
2352 // // but it is a package fragment root of another project, traverse delta too
2354 // || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) {
2355 // this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
2356 // // NB: No need to check the return value as the child can only be on the classpath
2359 // // if the child is a package fragment root of one or several other projects
2360 // ArrayList rootList;
2361 // if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
2362 // Iterator iterator = rootList.iterator();
2363 // while (iterator.hasNext()) {
2364 // childRootInfo = (RootInfo) iterator.next();
2365 // this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
2369 // if (orphanChildren != null
2370 // && (oneChildOnClasspath // orphan children are siblings of a package fragment root
2371 // || res instanceof IProject)) { // non-java resource directly under a project
2373 // // attach orphan children
2374 // IProject rscProject = res.getProject();
2375 // JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
2376 // if (adoptiveProject != null
2377 // && JavaProject.hasJavaNature(rscProject)) { // delta iff Java project (18698)
2378 // for (int i = 0; i < length; i++) {
2379 // if (orphanChildren[i] != null) {
2381 // nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
2382 // } catch (JavaModelException e) {
2387 // } // else resource delta will be added by parent
2388 // return elementType != NON_JAVA_RESOURCE; // TODO: (jerome) do we still need to return? (check could be done by caller)
2390 // return elementType != NON_JAVA_RESOURCE;
2395 * Update the classpath markers and cycle markers for the projects to update.
2397 // void updateClasspathMarkers() {
2399 // if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
2400 // Iterator iterator = this.projectsToUpdate.iterator();
2401 // while (iterator.hasNext()) {
2403 // JavaProject project = (JavaProject)iterator.next();
2405 // // force classpath marker refresh
2406 // project.getResolvedClasspath(
2407 // true, // ignoreUnresolvedEntry
2408 // true); // generateMarkerOnError
2410 // } catch (JavaModelException e) {
2414 // if (!this.projectsToUpdate.isEmpty()){
2416 // // update all cycle markers
2417 // JavaProject.updateAllCycleMarkers();
2418 // } catch (JavaModelException e) {
2422 // this.projectsToUpdate = new HashSet();
2427 * Update the current delta (ie. add/remove/change the given element) and update the correponding index.
2428 * Returns whether the children of the given delta must be processed.
2429 * @throws a JavaModelException if the delta doesn't correspond to a java element of the given type.
2431 // private boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType, RootInfo rootInfo) {
2432 // Openable element;
2433 // switch (delta.getKind()) {
2434 // case IResourceDelta.ADDED :
2435 // IResource deltaRes = delta.getResource();
2436 // element = this.createElement(deltaRes, elementType, rootInfo);
2437 // if (element == null) {
2438 // // resource might be containing shared roots (see bug 19058)
2439 // this.updateRoots(deltaRes.getFullPath(), delta);
2442 // this.updateIndex(element, delta);
2443 // this.elementAdded(element, delta, rootInfo);
2445 // case IResourceDelta.REMOVED :
2446 // deltaRes = delta.getResource();
2447 // element = this.createElement(deltaRes, elementType, rootInfo);
2448 // if (element == null) {
2449 // // resource might be containing shared roots (see bug 19058)
2450 // this.updateRoots(deltaRes.getFullPath(), delta);
2453 // this.updateIndex(element, delta);
2454 // this.elementRemoved(element, delta, rootInfo);
2456 // if (deltaRes.getType() == IResource.PROJECT){
2457 // // reset the corresponding project built state, since cannot reuse if added back
2458 // this.manager.setLastBuiltState((IProject)deltaRes, null /*no state*/);
2461 // case IResourceDelta.CHANGED :
2462 // int flags = delta.getFlags();
2463 // if ((flags & IResourceDelta.CONTENT) != 0) {
2464 // // content has changed
2465 // element = this.createElement(delta.getResource(), elementType, rootInfo);
2466 // if (element == null) return false;
2467 // this.updateIndex(element, delta);
2468 // this.contentChanged(element, delta);
2469 // } else if (elementType == IJavaElement.JAVA_PROJECT) {
2470 // if ((flags & IResourceDelta.OPEN) != 0) {
2471 // // project has been opened or closed
2472 // IProject res = (IProject)delta.getResource();
2473 // element = this.createElement(res, elementType, rootInfo);
2474 // if (element == null) {
2475 // // resource might be containing shared roots (see bug 19058)
2476 // this.updateRoots(res.getFullPath(), delta);
2479 // if (res.isOpen()) {
2480 // if (JavaProject.hasJavaNature(res)) {
2481 // this.elementAdded(element, delta, rootInfo);
2482 // this.indexManager.indexAll(res);
2485 // JavaModel javaModel = this.manager.getJavaModel();
2486 // boolean wasJavaProject = javaModel.findJavaProject(res) != null;
2487 // if (wasJavaProject) {
2488 // this.elementRemoved(element, delta, rootInfo);
2489 // this.indexManager.discardJobs(element.getElementName());
2490 // this.indexManager.removeIndexFamily(res.getFullPath());
2494 // return false; // when a project is open/closed don't process children
2496 // if ((flags & IResourceDelta.DESCRIPTION) != 0) {
2497 // IProject res = (IProject)delta.getResource();
2498 // JavaModel javaModel = this.manager.getJavaModel();
2499 // boolean wasJavaProject = javaModel.findJavaProject(res) != null;
2500 // boolean isJavaProject = JavaProject.hasJavaNature(res);
2501 // if (wasJavaProject != isJavaProject) {
2502 // // project's nature has been added or removed
2503 // element = this.createElement(res, elementType, rootInfo);
2504 // if (element == null) return false; // note its resources are still visible as roots to other projects
2505 // if (isJavaProject) {
2506 // this.elementAdded(element, delta, rootInfo);
2507 // this.indexManager.indexAll(res);
2509 // this.elementRemoved(element, delta, rootInfo);
2510 // this.indexManager.discardJobs(element.getElementName());
2511 // this.indexManager.removeIndexFamily(res.getFullPath());
2512 // // reset the corresponding project built state, since cannot reuse if added back
2513 // this.manager.setLastBuiltState(res, null /*no state*/);
2515 // return false; // when a project's nature is added/removed don't process children
2525 * Traverse the set of projects which have changed namespace, and refresh their dependents
2527 // public void updateDependentNamelookups() {
2528 // Iterator iterator;
2529 // // update namelookup of dependent projects
2530 // iterator = this.projectsForDependentNamelookupRefresh.iterator();
2531 // HashSet affectedDependents = new HashSet();
2532 // while (iterator.hasNext()) {
2533 // JavaProject project = (JavaProject)iterator.next();
2534 // addDependentProjects(project.getPath(), affectedDependents);
2536 // iterator = affectedDependents.iterator();
2537 // while (iterator.hasNext()) {
2538 // JavaProject project = (JavaProject) iterator.next();
2539 // if (project.isOpen()){
2541 // ((JavaProjectElementInfo)project.getElementInfo()).setNameLookup(null);
2542 // } catch (JavaModelException e) {
2548 //protected void updateIndex(Openable element, IResourceDelta delta) {
2550 // if (indexManager == null)
2553 // switch (element.getElementType()) {
2554 // case IJavaElement.JAVA_PROJECT :
2555 // switch (delta.getKind()) {
2556 // case IResourceDelta.ADDED :
2557 // this.indexManager.indexAll(element.getJavaProject().getProject());
2559 // case IResourceDelta.REMOVED :
2560 // this.indexManager.removeIndexFamily(element.getJavaProject().getProject().getFullPath());
2561 // // NB: Discarding index jobs belonging to this project was done during PRE_DELETE
2563 // // NB: Update of index if project is opened, closed, or its java nature is added or removed
2564 // // is done in updateCurrentDeltaAndIndex
2567 // case IJavaElement.PACKAGE_FRAGMENT_ROOT :
2568 // if (element instanceof JarPackageFragmentRoot) {
2569 // JarPackageFragmentRoot root = (JarPackageFragmentRoot)element;
2570 // // index jar file only once (if the root is in its declaring project)
2571 // IPath jarPath = root.getPath();
2572 // switch (delta.getKind()) {
2573 // case IResourceDelta.ADDED:
2574 // // index the new jar
2575 // indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
2577 // case IResourceDelta.CHANGED:
2578 // // first remove the index so that it is forced to be re-indexed
2579 // indexManager.removeIndex(jarPath);
2580 // // then index the jar
2581 // indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
2583 // case IResourceDelta.REMOVED:
2584 // // the jar was physically removed: remove the index
2585 // this.indexManager.discardJobs(jarPath.toString());
2586 // this.indexManager.removeIndex(jarPath);
2591 // int kind = delta.getKind();
2592 // if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
2593 // IPackageFragmentRoot root = (IPackageFragmentRoot)element;
2594 // this.updateRootIndex(root, root.getPackageFragment(""), delta); //$NON-NLS-1$
2598 // // don't break as packages of the package fragment root can be indexed below
2599 // case IJavaElement.PACKAGE_FRAGMENT :
2600 // switch (delta.getKind()) {
2601 // case IResourceDelta.ADDED:
2602 // case IResourceDelta.REMOVED:
2603 // IPackageFragment pkg = null;
2604 // if (element instanceof IPackageFragmentRoot) {
2605 // IPackageFragmentRoot root = (IPackageFragmentRoot)element;
2606 // pkg = root.getPackageFragment(""); //$NON-NLS-1$
2608 // pkg = (IPackageFragment)element;
2610 // IResourceDelta[] children = delta.getAffectedChildren();
2611 // for (int i = 0, length = children.length; i < length; i++) {
2612 // IResourceDelta child = children[i];
2613 // IResource resource = child.getResource();
2614 // if (resource instanceof IFile) {
2615 // String name = resource.getName();
2616 // if (Util.isJavaFileName(name)) {
2617 // Openable cu = (Openable)pkg.getCompilationUnit(name);
2618 // this.updateIndex(cu, child);
2619 // } else if (Util.isClassFileName(name)) {
2620 // Openable classFile = (Openable)pkg.getClassFile(name);
2621 // this.updateIndex(classFile, child);
2628 // case IJavaElement.CLASS_FILE :
2629 // IFile file = (IFile) delta.getResource();
2630 // IJavaProject project = element.getJavaProject();
2631 // IPath binaryFolderPath = element.getPackageFragmentRoot().getPath();
2632 // // if the class file is part of the binary output, it has been created by
2633 // // the java builder -> ignore
2635 // if (binaryFolderPath.equals(project.getOutputLocation())) {
2638 // } catch (JavaModelException e) {
2640 // switch (delta.getKind()) {
2641 // case IResourceDelta.CHANGED :
2642 // // no need to index if the content has not changed
2643 // if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
2645 // case IResourceDelta.ADDED :
2646 // indexManager.addBinary(file, binaryFolderPath);
2648 // case IResourceDelta.REMOVED :
2649 // indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
2653 // case IJavaElement.COMPILATION_UNIT :
2654 // file = (IFile) delta.getResource();
2655 // switch (delta.getKind()) {
2656 // case IResourceDelta.CHANGED :
2657 // // no need to index if the content has not changed
2658 // if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
2660 // case IResourceDelta.ADDED :
2661 // indexManager.addSource(file, file.getProject().getProject().getFullPath());
2663 // case IResourceDelta.REMOVED :
2664 // indexManager.remove(file.getFullPath().toString(), file.getProject().getProject().getFullPath());
2670 * Upadtes the index of the given root (assuming it's an addition or a removal).
2671 * This is done recusively, pkg being the current package.
2673 //private void updateRootIndex(IPackageFragmentRoot root, IPackageFragment pkg, IResourceDelta delta) {
2674 // this.updateIndex((Openable)pkg, delta);
2675 // IResourceDelta[] children = delta.getAffectedChildren();
2676 // String name = pkg.getElementName();
2677 // for (int i = 0, length = children.length; i < length; i++) {
2678 // IResourceDelta child = children[i];
2679 // IResource resource = child.getResource();
2680 // if (resource instanceof IFolder) {
2681 // String subpkgName =
2682 // name.length() == 0 ?
2683 // resource.getName() :
2684 // name + "." + resource.getName(); //$NON-NLS-1$
2685 // IPackageFragment subpkg = root.getPackageFragment(subpkgName);
2686 // this.updateRootIndex(root, subpkg, child);
2691 * Update the roots that are affected by the addition or the removal of the given container resource.
2693 //private void updateRoots(IPath containerPath, IResourceDelta containerDelta) {
2696 // if (containerDelta.getKind() == IResourceDelta.REMOVED) {
2697 // roots = this.oldRoots;
2698 // otherRoots = this.oldOtherRoots;
2700 // roots = this.roots;
2701 // otherRoots = this.otherRoots;
2703 // Iterator iterator = roots.keySet().iterator();
2704 // while (iterator.hasNext()) {
2705 // IPath path = (IPath)iterator.next();
2706 // if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
2707 // IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(1));
2708 // if (rootDelta == null) continue;
2709 // RootInfo rootInfo = (RootInfo)roots.get(path);
2711 // if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
2712 // this.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
2715 // ArrayList rootList = (ArrayList)otherRoots.get(path);
2716 // if (rootList != null) {
2717 // Iterator otherProjects = rootList.iterator();
2718 // while (otherProjects.hasNext()) {
2719 // rootInfo = (RootInfo)otherProjects.next();
2720 // if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
2721 // this.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);