X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java index a55c97a..8cfe6d8 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElement.java @@ -11,12 +11,15 @@ package net.sourceforge.phpdt.internal.core; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.core.IJavaElement; import net.sourceforge.phpdt.core.IJavaModel; import net.sourceforge.phpdt.core.IJavaModelStatusConstants; import net.sourceforge.phpdt.core.IJavaProject; +import net.sourceforge.phpdt.core.IMember; import net.sourceforge.phpdt.core.IOpenable; import net.sourceforge.phpdt.core.IParent; import net.sourceforge.phpdt.core.ISourceRange; @@ -26,12 +29,20 @@ import net.sourceforge.phpdt.core.jdom.IDOMCompilationUnit; import net.sourceforge.phpdt.core.jdom.IDOMNode; import net.sourceforge.phpdt.internal.corext.Assert; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import net.sourceforge.phpdt.internal.core.JavaElementInfo; + +import net.sourceforge.phpdt.internal.core.JavaModelManager; +import net.sourceforge.phpdt.internal.core.util.Util; /** * Root of Java element handle hierarchy. @@ -60,83 +71,58 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * them. The occurrence count starts at 1 (thus the first * occurrence is occurrence 1, not occurrence 0). */ - protected int fOccurrenceCount = 1; + protected int occurrenceCount = 1; /** * This element's type - one of the constants defined * in IJavaLanguageElementTypes. */ - protected int fLEType = 0; + //protected int fLEType = 0; /** * This element's parent, or null if this * element does not have a parent. */ - protected IJavaElement fParent; + protected IJavaElement parent; /** * This element's name, or an empty String if this * element does not have a name. */ - protected String fName; + protected String name; protected static final Object NO_INFO = new Object(); /** - * Constructs a handle for a java element of the specified type, with + * Constructs a handle for a java element with * the given parent element and name. * - * @param type - one of the constants defined in IJavaLanguageElement + * @param parent The parent of java element + * @param name The name of java element * * @exception IllegalArgumentException if the type is not one of the valid * Java element type constants * */ - protected JavaElement(int type, IJavaElement parent, String name) throws IllegalArgumentException { - if (type < JAVA_MODEL || type > IMPORT_DECLARATION) { - throw new IllegalArgumentException(Util.bind("element.invalidType")); //$NON-NLS-1$ - } - fLEType= type; - fParent= parent; - fName= name; + protected JavaElement(JavaElement parent, String name) throws IllegalArgumentException { + this.parent = parent; + this.name = name; } /** * @see IOpenable */ public void close() throws JavaModelException { - Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this); - if (info != null) { - boolean wasVerbose = false; - try { - if (JavaModelManager.VERBOSE) { - System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$ - wasVerbose = true; - JavaModelManager.VERBOSE = false; - } - if (this instanceof IParent) { - IJavaElement[] children = ((JavaElementInfo) info).getChildren(); - for (int i = 0, size = children.length; i < size; ++i) { - JavaElement child = (JavaElement) children[i]; - child.close(); - } - } - closing(info); - JavaModelManager.getJavaModelManager().removeInfo(this); - if (wasVerbose) { - System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$ - System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$ - } - } finally { - JavaModelManager.VERBOSE = wasVerbose; - } - } + JavaModelManager.getJavaModelManager().removeInfoAndChildren(this); } /** * This element is being closed. Do any necessary cleanup. */ - protected void closing(Object info) throws JavaModelException { - } + protected abstract void closing(Object info) throws JavaModelException; + /* + * Returns a new element info for this element. + */ + protected abstract Object createElementInfo(); /** * Returns true if this handle represents the same Java element * as the given handle. By default, two handles represent the same @@ -153,17 +139,13 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement if (this == o) return true; // Java model parent is null - if (fParent == null) return super.equals(o); + if (this.parent == null) return super.equals(o); - if (o instanceof JavaElement) { - JavaElement other = (JavaElement) o; - if (fLEType != other.fLEType) return false; - - return fName.equals(other.fName) && - fParent.equals(other.fParent) && - fOccurrenceCount == other.fOccurrenceCount; - } - return false; + // assume instanceof check is done in subclass + JavaElement other = (JavaElement) o; + return this.occurrenceCount == other.occurrenceCount && + this.name.equals(other.name) && + this.parent.equals(other.parent); } /** * Returns true if this JavaElement is equivalent to the given @@ -262,6 +244,12 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement return null; } /** + * Generates the element infos for this element, its ancestors (if they are not opened) and its children (if it is an Openable). + * Puts the newly created element info in the given map. + */ + protected abstract void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException; + + /** * @see IParent */ public IJavaElement[] getChildren() throws JavaModelException { @@ -301,48 +289,33 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * Returns the info for this handle. * If this element is not already open, it and all of its parents are opened. * Does not return null. - * NOTE: BinaryType infos are NJOT rooted under JavaElementInfo. + * NOTE: BinaryType infos are NOT rooted under JavaElementInfo. * @exception JavaModelException if the element is not present or not accessible */ public Object getElementInfo() throws JavaModelException { - // workaround to ensure parent project resolved classpath is available to avoid triggering initializers - // while the JavaModelManager lock is acquired (can cause deadlocks in clients) - IJavaProject project = getJavaProject(); - if (project != null && !project.isOpen()) { - // TODO: need to revisit, since deadlock could still occur if perProjectInfo is removed concurrent before entering the lock - try { - project.getResolvedClasspath(true); // trigger all possible container/variable initialization outside the model lock - } catch (JavaModelException e) { - // project is not accessible or is not a java project - } - } - - // element info creation is done inside a lock on the JavaModelManager - JavaModelManager manager; - synchronized(manager = JavaModelManager.getJavaModelManager()){ - Object info = manager.getInfo(this); - if (info == null) { - openHierarchy(); - info= manager.getInfo(this); - if (info == null) { - throw newNotPresentException(); - } - } - return info; - } + return getElementInfo(null); } /** - * @see IAdaptable + * Returns the info for this handle. + * If this element is not already open, it and all of its parents are opened. + * Does not return null. + * NOTE: BinaryType infos are NOT rooted under JavaElementInfo. + * @exception JavaModelException if the element is not present or not accessible */ - public String getElementName() { - return fName; + public Object getElementInfo(IProgressMonitor monitor) throws JavaModelException { + + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + Object info = manager.getInfo(this); + if (info != null) return info; + return openWhenClosed(createElementInfo(), monitor); } /** - * @see IJavaElement + * @see IAdaptable */ - public int getElementType() { - return fLEType; + public String getElementName() { + return name; } + /** * @see IJavaElement */ @@ -388,7 +361,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * Returns the occurrence count of the handle. */ protected int getOccurrenceCount() { - return fOccurrenceCount; + return occurrenceCount; } /* * @see IJavaElement @@ -404,15 +377,28 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement */ public IOpenable getOpenableParent() { - return (IOpenable)fParent; + return (IOpenable)parent; } /** * @see IJavaElement */ public IJavaElement getParent() { - return fParent; + return parent; } + /* + * @see IJavaElement#getPrimaryElement() + */ + public IJavaElement getPrimaryElement() { + return getPrimaryElement(true); + } + /* + * Returns the primary element. If checkOwner, and the cu owner is primary, + * return this element. + */ + public IJavaElement getPrimaryElement(boolean checkOwner) { + return this; + } /** * Returns the element that is located at the given source position * in this element. This is a helper method for ICompilationUnit#getElementAt, @@ -452,6 +438,51 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement // public SourceMapper getSourceMapper() { // return ((JavaElement)getParent()).getSourceMapper(); // } + /* (non-Javadoc) + * @see org.eclipse.jdt.core.IJavaElement#getSchedulingRule() + */ + public ISchedulingRule getSchedulingRule() { + IResource resource = getResource(); + if (resource == null) { + class NoResourceSchedulingRule implements ISchedulingRule { + public IPath path; + public NoResourceSchedulingRule(IPath path) { + this.path = path; + } + public boolean contains(ISchedulingRule rule) { + if (rule instanceof NoResourceSchedulingRule) { + return this.path.isPrefixOf(((NoResourceSchedulingRule)rule).path); + } else { + return false; + } + } + public boolean isConflicting(ISchedulingRule rule) { + if (rule instanceof NoResourceSchedulingRule) { + IPath otherPath = ((NoResourceSchedulingRule)rule).path; + return this.path.isPrefixOf(otherPath) || otherPath.isPrefixOf(this.path); + } else { + return false; + } + } + } + return new NoResourceSchedulingRule(getPath()); + } else { + return resource; + } + } + /** + * @see IParent + */ + public boolean hasChildren() throws JavaModelException { + // if I am not open, return true to avoid opening (case of a Java project, a compilation unit or a class file). + // also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52474 + Object elementInfo = JavaModelManager.getJavaModelManager().getInfo(this); + if (elementInfo instanceof JavaElementInfo) { + return ((JavaElementInfo)elementInfo).getChildren().length > 0; + } else { + return true; + } + } /** * Returns the hash code for this Java element. By default, @@ -460,9 +491,10 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * override this method. */ public int hashCode() { - if (fParent == null) return super.hashCode(); - return Util.combineHashCodes(fName.hashCode(), fParent.hashCode()); + if (this.parent == null) return super.hashCode(); + return Util.combineHashCodes(this.name.hashCode(), this.parent.hashCode()); } + /** * Returns true if this element is an ancestor of the given element, * otherwise false. @@ -498,26 +530,60 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * * @exception JavaModelException this element is not present or accessible */ - protected void openHierarchy() throws JavaModelException { - if (this instanceof IOpenable) { - ((Openable) this).openWhenClosed(null); - } else { - Openable openableParent = (Openable)getOpenableParent(); - if (openableParent != null) { - JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent); - if (openableParentInfo == null) { - openableParent.openWhenClosed(null); - } else { - throw newNotPresentException(); - } - } - } - } +// protected void openHierarchy() throws JavaModelException { +// if (this instanceof IOpenable) { +// ((Openable) this).openWhenClosed(null); +// } else { +// Openable openableParent = (Openable)getOpenableParent(); +// if (openableParent != null) { +// JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent); +// if (openableParentInfo == null) { +// openableParent.openWhenClosed(null); +// } else { +// throw newNotPresentException(); +// } +// } +// } +// } /** * This element has just been opened. Do any necessary setup. */ protected void opening(Object info) { } + /* + * Opens an Openable that is known to be closed (no check for isOpen()). + * Returns the created element info. + */ + protected Object openWhenClosed(Object info, IProgressMonitor monitor) throws JavaModelException { + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + boolean hadTemporaryCache = manager.hasTemporaryCache(); + try { + HashMap newElements = manager.getTemporaryCache(); + generateInfos(info, newElements, monitor); + if (info == null) { + info = newElements.get(this); + } + if (info == null) { // a source ref element could not be opened + // close any buffer that was opened for the openable parent + Iterator iterator = newElements.keySet().iterator(); + while (iterator.hasNext()) { + IJavaElement element = (IJavaElement)iterator.next(); + if (element instanceof Openable) { + ((Openable)element).closeBuffer(); + } + } + throw newNotPresentException(); + } + if (!hadTemporaryCache) { + manager.putInfos(this, newElements); + } + } finally { + if (!hadTemporaryCache) { + manager.resetTemporaryCache(); + } + } + return info; + } /** */ public String readableName() { @@ -527,23 +593,23 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * Removes all cached info from the Java Model, including all children, * but does not close this element. */ - protected void removeInfo() { - Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this); - if (info != null) { - if (this instanceof IParent) { - IJavaElement[] children = ((JavaElementInfo)info).getChildren(); - for (int i = 0, size = children.length; i < size; ++i) { - JavaElement child = (JavaElement) children[i]; - child.removeInfo(); - } - } - JavaModelManager.getJavaModelManager().removeInfo(this); - } - } - /** - * Returns a copy of this element rooted at the given project. - */ - public abstract IJavaElement rootedAt(IJavaProject project); +// protected void removeInfo() { +// Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this); +// if (info != null) { +// if (this instanceof IParent) { +// IJavaElement[] children = ((JavaElementInfo)info).getChildren(); +// for (int i = 0, size = children.length; i < size; ++i) { +// JavaElement child = (JavaElement) children[i]; +// child.removeInfo(); +// } +// } +// JavaModelManager.getJavaModelManager().removeInfo(this); +// } +// } +// /** +// * Returns a copy of this element rooted at the given project. +// */ +// public abstract IJavaElement rootedAt(IJavaProject project); /** * Runs a Java Model Operation */ @@ -573,7 +639,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement * Sets the occurrence count of the handle. */ protected void setOccurrenceCount(int count) { - fOccurrenceCount = count; + occurrenceCount = count; } protected String tabString(int tab) { StringBuffer buffer = new StringBuffer();