X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/CompilationUnit.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/CompilationUnit.java index 50c264c..56c944e 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/CompilationUnit.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/CompilationUnit.java @@ -12,7 +12,6 @@ package net.sourceforge.phpdt.internal.core; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import net.sourceforge.phpdt.core.IBuffer; @@ -36,12 +35,15 @@ import net.sourceforge.phpdt.core.IType; import net.sourceforge.phpdt.core.IWorkingCopy; import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.Signature; +import net.sourceforge.phpdt.core.WorkingCopyOwner; import net.sourceforge.phpdt.core.compiler.CharOperation; import net.sourceforge.phpdt.core.jdom.IDOMNode; import net.sourceforge.phpdt.internal.compiler.IProblemFactory; import net.sourceforge.phpdt.internal.compiler.SourceElementParser; import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions; import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory; +import net.sourceforge.phpdt.internal.core.util.Util; +import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -50,30 +52,38 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; +import net.sourceforge.phpdt.internal.core.JavaModelManager; +//import net.sourceforge.phpdt.core.dom.AST; +import net.sourceforge.phpdt.internal.core.ReconcileWorkingCopyOperation; -/** +import net.sourceforge.phpdt.internal.core.DiscardWorkingCopyOperation; + +import net.sourceforge.phpdt.internal.core.CompilationUnitElementInfo; +import net.sourceforge.phpdt.internal.core.JavaModelStatus; + +import net.sourceforge.phpdt.internal.core.BufferManager; +import net.sourceforge.phpdt.internal.core.DefaultWorkingCopyOwner; +import net.sourceforge.phpdt.internal.core.Openable; + +import net.sourceforge.phpdt.internal.core.PackageFragment; + +/** * @see ICompilationUnit */ public class CompilationUnit extends Openable implements ICompilationUnit, net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit { - - public static boolean SHARED_WC_VERBOSE = false; - - // TODO: Remove when we are certain that every client is ready for this fix - public static final boolean FIX_BUG25184 = true; + public WorkingCopyOwner owner; /** * Constructs a handle to a compilation unit with the given name in the - * specified package. + * specified package for the specified owner * * @exception IllegalArgumentException if the name of the compilation unit * does not end with ".java" */ -protected CompilationUnit(IPackageFragment parent, String name) { - super(COMPILATION_UNIT, parent, name); - if (!Util.isJavaFileName(name)) { - throw new IllegalArgumentException(net.sourceforge.phpdt.internal.core.Util.bind("convention.unit.notJavaName")); //$NON-NLS-1$ - } +protected CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) { + super(parent, name); + this.owner = owner; } /** * Accepts the given visitor onto the parsed tree of this compilation unit, after @@ -92,28 +102,121 @@ protected CompilationUnit(IPackageFragment parent, String name) { //public void accept(IAbstractSyntaxTreeVisitor visitor) throws JavaModelException { // CompilationUnitVisitor.visit(this, visitor); //} +/* + * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor) + */ +public void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException { + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(this, false/*don't create*/, true /*record usage*/, null/*no problem requestor needed*/); + if (perWorkingCopyInfo == null) { + // close cu and its children + close(); -protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException { + BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(this, problemRequestor); + operation.runOperation(monitor); + } +} +//protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException { +// +// if (monitor != null && monitor.isCanceled()) return; +// +// // remove existing (old) infos +// removeInfo(); +// +// HashMap newElements = new HashMap(11); +// info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource())); +// JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this); +// for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) { +// IJavaElement key = (IJavaElement) iter.next(); +// Object value = newElements.get(key); +// JavaModelManager.getJavaModelManager().putInfo(key, value); +// } +// // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs +// // to be flushed. Might lead to performance issues. +// // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type +// JavaModelManager.getJavaModelManager().putInfo(this, info); +//} +protected boolean buildStructure(OpenableElementInfo info, final IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { - if (monitor != null && monitor.isCanceled()) return; + // check if this compilation unit can be opened + if (!isWorkingCopy()) { // no check is done on root kind or exclusion pattern for working copies + if ( // ((IPackageFragment)getParent()).getKind() == IPackageFragmentRoot.K_BINARY|| + !isValidCompilationUnit() + || !underlyingResource.isAccessible()) { + throw newNotPresentException(); + } + } + + // prevents reopening of non-primary working copies (they are closed when they are discarded and should not be reopened) + if (!isPrimary() && getPerWorkingCopyInfo() == null) { + throw newNotPresentException(); + } - // remove existing (old) infos - removeInfo(); + CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info; - HashMap newElements = new HashMap(11); - info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource())); - JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this); - for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) { - IJavaElement key = (IJavaElement) iter.next(); - Object value = newElements.get(key); - JavaModelManager.getJavaModelManager().putInfo(key, value); + // get buffer contents + IBuffer buffer = getBufferManager().getBuffer(CompilationUnit.this); + if (buffer == null) { + buffer = openBuffer(pm, unitInfo); // open buffer independently from the info, since we are building the info } - // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs - // to be flushed. Might lead to performance issues. - // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type - JavaModelManager.getJavaModelManager().putInfo(this, info); -} + final char[] contents = buffer == null ? null : buffer.getCharacters(); + // generate structure and compute syntax problems if needed + CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements); + JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = getPerWorkingCopyInfo(); + IJavaProject project = getJavaProject(); + boolean computeProblems = JavaProject.hasJavaNature(project.getProject()) && perWorkingCopyInfo != null && perWorkingCopyInfo.isActive(); + IProblemFactory problemFactory = new DefaultProblemFactory(); + Map options = project.getOptions(true); + SourceElementParser parser = new SourceElementParser( + requestor, + problemFactory, + new CompilerOptions(options)); + //, true/*report local declarations*/); + requestor.parser = parser; + CompilationUnitDeclaration unit = parser.parseCompilationUnit(new net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit() { + public char[] getContents() { + return contents; + } + public char[] getMainTypeName() { + return CompilationUnit.this.getMainTypeName(); + } + public char[][] getPackageName() { + return CompilationUnit.this.getPackageName(); + } + public char[] getFileName() { + return CompilationUnit.this.getFileName(); + } + }, true /*full parse to find local elements*/); + + // update timestamp (might be IResource.NULL_STAMP if original does not exist) + if (underlyingResource == null) { + underlyingResource = getResource(); + } + unitInfo.timestamp = ((IFile)underlyingResource).getModificationStamp(); + + // compute other problems if needed + CompilationUnitDeclaration compilationUnitDeclaration = null; + try { + if (computeProblems){ + perWorkingCopyInfo.beginReporting(); + compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, perWorkingCopyInfo, problemFactory, false/*don't cleanup cu*/, pm); + perWorkingCopyInfo.endReporting(); + } + +// if (info instanceof ASTHolderCUInfo) { +// int astLevel = ((ASTHolderCUInfo) info).astLevel; +// org.eclipse.jdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, unit, contents, options, pm); +// ((ASTHolderCUInfo) info).ast = cu; +// } + } finally { + if (compilationUnitDeclaration != null) { + compilationUnitDeclaration.cleanUp(); + } + } + + return unitInfo.isStructureKnown(); +} ///** // * @see ICodeAssist#codeComplete(int, ICompletionRequestor) // */ @@ -133,6 +236,13 @@ public void commit(boolean force, IProgressMonitor monitor) throws JavaModelExce throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this)); } /** + * @see ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor) + */ +public void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException { + CommitWorkingCopyOperation op= new CommitWorkingCopyOperation(this, force); + op.runOperation(monitor); +} +/** * @see ISourceManipulation#copy(IJavaElement, IJavaElement, String, boolean, IProgressMonitor) */ public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException { @@ -147,10 +257,11 @@ public void copy(IJavaElement container, IJavaElement sibling, String rename, bo } getJavaModel().copy(elements, containers, null, renamings, force, monitor); } + /** * Returns a new element info for this element. */ -protected OpenableElementInfo createElementInfo() { +protected Object createElementInfo() { return new CompilationUnitElementInfo(); } ///** @@ -203,24 +314,35 @@ public void delete(boolean force, IProgressMonitor monitor) throws JavaModelExce getJavaModel().delete(elements, force, monitor); } /** - * This is not a working copy, do nothing. - * * @see IWorkingCopy#destroy() + * @deprecated */ public void destroy() { + try { + discardWorkingCopy(); + } catch (JavaModelException e) { + e.printStackTrace(); + } +} +/* + * @see ICompilationUnit#discardWorkingCopy + */ +public void discardWorkingCopy() throws JavaModelException { + // discard working copy and its children + DiscardWorkingCopyOperation op = new DiscardWorkingCopyOperation(this); + op.runOperation(null); } - /** * Returns true if this handle represents the same Java element * as the given handle. * - *

Compilation units must also check working copy state; - * * @see Object#equals(java.lang.Object) */ -public boolean equals(Object o) { - return super.equals(o) && !((ICompilationUnit)o).isWorkingCopy(); +public boolean equals(Object obj) { + if (!(obj instanceof CompilationUnit)) return false; + CompilationUnit other = (CompilationUnit)obj; + return this.owner.equals(other.owner) && super.equals(obj); } /** * @see JavaElement#equalsDOMNode(IDOMNode) @@ -303,25 +425,35 @@ public IType findPrimaryType() { } return null; } - /** * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory) + * @deprecated */ public IJavaElement findSharedWorkingCopy(IBufferFactory factory) { // if factory is null, default factory must be used if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory(); - - // In order to be shared, working copies have to denote the same compilation unit - // AND use the same buffer factory. - // Assuming there is a little set of buffer factories, then use a 2 level Map cache. - Map sharedWorkingCopies = JavaModelManager.getJavaModelManager().sharedWorkingCopies; - Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory); - if (perFactoryWorkingCopies == null) return null; - return (WorkingCopy)perFactoryWorkingCopies.get(this); + return findWorkingCopy(BufferFactoryWrapper.create(factory)); } +/** + * @see ICompilationUnit#findWorkingCopy(WorkingCopyOwner) + */ +public ICompilationUnit findWorkingCopy(WorkingCopyOwner workingCopyOwner) { + CompilationUnit cu = new CompilationUnit((PackageFragment)this.parent, getElementName(), workingCopyOwner); + if (workingCopyOwner == DefaultWorkingCopyOwner.PRIMARY) { + return cu; + } else { + // must be a working copy + JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = cu.getPerWorkingCopyInfo(); + if (perWorkingCopyInfo != null) { + return perWorkingCopyInfo.getWorkingCopy(); + } else { + return null; + } + } +} protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { // if (getParent() instanceof JarPackageFragment) { @@ -342,7 +474,7 @@ protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, M if (isWorkingCopy()) { CompilationUnit original = (CompilationUnit) getOriginalElement(); // might be IResource.NULL_STAMP if original does not exist - unitInfo.fTimestamp = ((IFile) original.getResource()).getModificationStamp(); + unitInfo.timestamp = ((IFile) original.getResource()).getModificationStamp(); } return unitInfo.isStructureKnown(); // } @@ -414,6 +546,12 @@ public IJavaElement getElementAt(int position) throws JavaModelException { return e; } } +/** + * @see IJavaElement + */ +public int getElementType() { + return COMPILATION_UNIT; +} public char[] getFileName(){ return getElementName().toCharArray(); } @@ -463,21 +601,36 @@ public char[] getMainTypeName(){ name= name.substring(0, name.length() - 5); return name.toCharArray(); } + /** - * Returns null, this is not a working copy. - * * @see IWorkingCopy#getOriginal(IJavaElement) + * @deprecated */ public IJavaElement getOriginal(IJavaElement workingCopyElement) { - return null; + // backward compatibility + if (!isWorkingCopy()) return null; + CompilationUnit cu = (CompilationUnit)workingCopyElement.getAncestor(COMPILATION_UNIT); + if (cu == null || !this.owner.equals(cu.owner)) { + return null; + } + + return workingCopyElement.getPrimaryElement(); } /** - * Returns null, this is not a working copy. - * * @see IWorkingCopy#getOriginalElement() + * @deprecated */ public IJavaElement getOriginalElement() { - return null; + // backward compatibility + if (!isWorkingCopy()) return null; + + return getPrimaryElement(); +} +/* + * @see ICompilationUnit#getOwner() + */ +public WorkingCopyOwner getOwner() { + return isPrimary() || !isWorkingCopy() ? null : this.owner; } /** * @see ICompilationUnit#getPackageDeclaration(String) @@ -511,6 +664,27 @@ public IPath getPath() { return this.getParent().getPath().append(this.getElementName()); } } +/* + * Returns the per working copy info for the receiver, or null if none exist. + * Note: the use count of the per working copy info is NOT incremented. + */ +public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() { + return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/); +} +/* + * @see ICompilationUnit#getPrimary() + */ +public ICompilationUnit getPrimary() { + return (ICompilationUnit)getPrimaryElement(true); +} +/* + * @see JavaElement#getPrimaryElement(boolean) + */ +public IJavaElement getPrimaryElement(boolean checkOwner) { + if (checkOwner && isPrimary()) return this; + return new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY); +} + /** * @see IJavaElement#getResource() */ @@ -552,70 +726,113 @@ public IType[] getTypes() throws JavaModelException { list.toArray(array); return array; } +/** + * @see IJavaElement + */ public IResource getUnderlyingResource() throws JavaModelException { - if (FIX_BUG25184) { - return super.getUnderlyingResource(); - } else { - return getResource(); - } + if (isWorkingCopy() && !isPrimary()) return null; + return super.getUnderlyingResource(); } +///** +// * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) +// */ +//public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException { +// +// // if factory is null, default factory must be used +// if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory(); +// +// JavaModelManager manager = JavaModelManager.getJavaModelManager(); +// +// // In order to be shared, working copies have to denote the same compilation unit +// // AND use the same buffer factory. +// // Assuming there is a little set of buffer factories, then use a 2 level Map cache. +// Map sharedWorkingCopies = manager.sharedWorkingCopies; +// +// Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory); +// if (perFactoryWorkingCopies == null){ +// perFactoryWorkingCopies = new HashMap(); +// sharedWorkingCopies.put(factory, perFactoryWorkingCopies); +// } +// WorkingCopy workingCopy = (WorkingCopy)perFactoryWorkingCopies.get(this); +// if (workingCopy != null) { +// workingCopy.useCount++; +// +// if (SHARED_WC_VERBOSE) { +// System.out.println("Incrementing use count of shared working copy " + workingCopy.toStringWithAncestors()); //$NON-NLS-1$ +// } +// +// return workingCopy; +// } else { +// CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, perFactoryWorkingCopies, factory, problemRequestor); +// runOperation(op, pm); +// return op.getResultElements()[0]; +// } +//} +///** +// * @see IWorkingCopy#getWorkingCopy() +// */ +//public IJavaElement getWorkingCopy() throws JavaModelException { +// return this.getWorkingCopy(null, null, null); +//} +// +///** +// * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) +// */ +//public IJavaElement getWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException { +// CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, null, factory, problemRequestor); +// runOperation(op, pm); +// return op.getResultElements()[0]; +//} /** * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) + * @deprecated */ public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException { // if factory is null, default factory must be used if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory(); - - JavaModelManager manager = JavaModelManager.getJavaModelManager(); - // In order to be shared, working copies have to denote the same compilation unit - // AND use the same buffer factory. - // Assuming there is a little set of buffer factories, then use a 2 level Map cache. - Map sharedWorkingCopies = manager.sharedWorkingCopies; - - Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory); - if (perFactoryWorkingCopies == null){ - perFactoryWorkingCopies = new HashMap(); - sharedWorkingCopies.put(factory, perFactoryWorkingCopies); - } - WorkingCopy workingCopy = (WorkingCopy)perFactoryWorkingCopies.get(this); - if (workingCopy != null) { - workingCopy.useCount++; - - if (SHARED_WC_VERBOSE) { - System.out.println("Incrementing use count of shared working copy " + workingCopy.toStringWithAncestors()); //$NON-NLS-1$ - } - - return workingCopy; - } else { - CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, perFactoryWorkingCopies, factory, problemRequestor); - runOperation(op, pm); - return op.getResultElements()[0]; - } + return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, pm); } /** * @see IWorkingCopy#getWorkingCopy() + * @deprecated */ public IJavaElement getWorkingCopy() throws JavaModelException { - return this.getWorkingCopy(null, null, null); + return getWorkingCopy(null); +} +/** + * @see ICompilationUnit#getWorkingCopy(IProgressMonitor) + */ +public ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException { + return getWorkingCopy(new WorkingCopyOwner() {/*non shared working copy*/}, null/*no problem requestor*/, monitor); } - /** * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) + * @deprecated */ -public IJavaElement getWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException { - CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, null, factory, problemRequestor); - runOperation(op, pm); - return op.getResultElements()[0]; +public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException { + return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, monitor); } - /** - * @see Openable#hasBuffer() + * @see ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) */ -protected boolean hasBuffer() { - return true; +public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException { + if (!isPrimary()) return this; + + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + + CompilationUnit workingCopy = new CompilationUnit((PackageFragment)getParent(), getElementName(), workingCopyOwner); + JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = + manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true/*record usage*/, null/*not used since don't create*/); + if (perWorkingCopyInfo != null) { + return perWorkingCopyInfo.getWorkingCopy(); // return existing handle instead of the one created above + } + BecomeWorkingCopyOperation op = new BecomeWorkingCopyOperation(workingCopy, problemRequestor); + op.runOperation(monitor); + return workingCopy; } + /** * If I am not open, return true to avoid parsing. * @@ -630,41 +847,120 @@ public boolean hasChildren() throws JavaModelException { return false; } /** - * Returns false, this is not a working copy. - * + * @see Openable#hasBuffer() + */ +protected boolean hasBuffer() { + return true; +} +/* + * @see ICompilationUnit#hasResourceChanged() + */ +public boolean hasResourceChanged() { + if (!isWorkingCopy()) return false; + + // if resource got deleted, then #getModificationStamp() will answer IResource.NULL_STAMP, which is always different from the cached + // timestamp + Object info = JavaModelManager.getJavaModelManager().getInfo(this); + if (info == null) return false; + return ((CompilationUnitElementInfo)info).timestamp != getResource().getModificationStamp(); +} +/** * @see IWorkingCopy#isBasedOn(IResource) + * @deprecated */ public boolean isBasedOn(IResource resource) { - return false; + if (!isWorkingCopy()) return false; + if (!getResource().equals(resource)) return false; + return !hasResourceChanged(); } /** * @see IOpenable#isConsistent() */ -public boolean isConsistent() throws JavaModelException { +public boolean isConsistent() { return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null; } + +/** + * + * @see IOpenable + */ +public boolean isOpen() { + Object info = JavaModelManager.getJavaModelManager().getInfo(this); + return info != null && ((CompilationUnitElementInfo)info).isOpen(); +} +public boolean isPrimary() { + return this.owner == DefaultWorkingCopyOwner.PRIMARY; +} /** * @see Openable#isSourceElement() */ protected boolean isSourceElement() { return true; } -/** - * @see IWorkingCopy#isWorkingCopy() +protected boolean isValidCompilationUnit() { + IPackageFragmentRoot root = getPackageFragmentRoot(); + try { + if (root.getKind() != IPackageFragmentRoot.K_SOURCE) return false; + } catch (JavaModelException e) { + return false; + } +// IResource resource = getResource(); +// if (resource != null) { +// char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars(); +// char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars(); +// if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false; +// } + if (!Util.isValidCompilationUnitName(getElementName())) return false; + return true; +} +/* + * @see ICompilationUnit#isWorkingCopy() */ public boolean isWorkingCopy() { - return false; + // For backward compatibility, non primary working copies are always returning true; in removal + // delta, clients can still check that element was a working copy before being discarded. + return !isPrimary() || getPerWorkingCopyInfo() != null; } /** * @see IOpenable#makeConsistent(IProgressMonitor) */ public void makeConsistent(IProgressMonitor monitor) throws JavaModelException { - if (!isConsistent()) { // TODO: this code isn't synchronized with regular opening of a working copy - // create a new info and make it the current info - OpenableElementInfo info = createElementInfo(); - buildStructure(info, monitor); - } + makeConsistent(false/*don't create AST*/, 0, monitor); +} +public Object makeConsistent(boolean createAST, int astLevel, IProgressMonitor monitor) throws JavaModelException { + if (isConsistent()) return null; + + // create a new info and make it the current info + // (this will remove the info and its children just before storing the new infos) +// if (createAST) { +// ASTHolderCUInfo info = new ASTHolderCUInfo(); +// info.astLevel = astLevel; +// openWhenClosed(info, monitor); +// org.eclipse.jdt.core.dom.CompilationUnit result = info.ast; +// info.ast = null; +// return result; +// } else { + openWhenClosed(createElementInfo(), monitor); + return null; +// } } +//public net.sourceforge.phpdt.core.dom.CompilationUnit makeConsistent(boolean createAST, int astLevel, IProgressMonitor monitor) throws JavaModelException { +// if (isConsistent()) return null; +// +// // create a new info and make it the current info +// // (this will remove the info and its children just before storing the new infos) +// if (createAST) { +// ASTHolderCUInfo info = new ASTHolderCUInfo(); +// info.astLevel = astLevel; +// openWhenClosed(info, monitor); +// net.sourceforge.phpdt.core.dom.CompilationUnit result = info.ast; +// info.ast = null; +// return result; +// } else { +// openWhenClosed(createElementInfo(), monitor); +// return null; +// } +//} /** * @see ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor) @@ -683,24 +979,69 @@ public void move(IJavaElement container, IJavaElement sibling, String rename, bo getJavaModel().move(elements, containers, null, renamings, force, monitor); } +///** +// * @see Openable#openBuffer(IProgressMonitor) +// */ +//protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException { +// +// // create buffer - compilation units only use default buffer factory +// BufferManager bufManager = getBufferManager(); +// IBuffer buffer = getBufferFactory().createBuffer(this); +// if (buffer == null) return null; +// +// // set the buffer source +// if (buffer.getCharacters() == null){ +// IFile file = (IFile)this.getResource(); +// if (file == null || !file.exists()) throw newNotPresentException(); +// buffer.setContents(Util.getResourceContentsAsCharArray(file)); +// } +// +// // add buffer to buffer cache +// bufManager.addBuffer(buffer); +// +// // listen to buffer changes +// buffer.addBufferChangedListener(this); +// +// return buffer; +//} /** - * @see Openable#openBuffer(IProgressMonitor) + * @see Openable#openBuffer(IProgressMonitor, Object) */ -protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException { +protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException { - // create buffer - compilation units only use default buffer factory - BufferManager bufManager = getBufferManager(); - IBuffer buffer = getBufferFactory().createBuffer(this); + // create buffer + boolean isWorkingCopy = isWorkingCopy(); + IBuffer buffer = + isWorkingCopy + ? this.owner.createBuffer(this) + : BufferManager.getDefaultBufferManager().createBuffer(this); if (buffer == null) return null; // set the buffer source - if (buffer.getCharacters() == null){ - IFile file = (IFile)this.getResource(); - if (file == null || !file.exists()) throw newNotPresentException(); - buffer.setContents(Util.getResourceContentsAsCharArray(file)); + if (buffer.getCharacters() == null) { + if (isWorkingCopy) { + ICompilationUnit original; + if (!isPrimary() + && (original = new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY)).isOpen()) { + buffer.setContents(original.getSource()); + } else { + IFile file = (IFile)getResource(); + if (file == null || !file.exists()) { + // initialize buffer with empty contents + buffer.setContents(CharOperation.NO_CHAR); + } else { + buffer.setContents(Util.getResourceContentsAsCharArray(file)); + } + } + } else { + IFile file = (IFile)this.getResource(); + if (file == null || !file.exists()) throw newNotPresentException(); + buffer.setContents(Util.getResourceContentsAsCharArray(file)); + } } // add buffer to buffer cache + BufferManager bufManager = getBufferManager(); bufManager.addBuffer(buffer); // listen to buffer changes @@ -708,44 +1049,67 @@ protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException { return buffer; } -protected void openParent(IProgressMonitor pm) throws JavaModelException { - if (FIX_BUG25184) { - super.openParent(pm); - } else { - try { - super.openParent(pm); - } catch(JavaModelException e){ - // allow parent to not exist for compilation units defined outside classpath - if (!e.isDoesNotExist()){ - throw e; - } +/* + * @see Openable#openParent + */ +protected void openParent(Object childInfo, HashMap newElements, IProgressMonitor pm) throws JavaModelException { + try { + super.openParent(childInfo, newElements, pm); + } catch(JavaModelException e){ + // allow parent to not exist for working copies defined outside classpath + if (!isWorkingCopy() && !e.isDoesNotExist()){ + throw e; } } } -protected boolean parentExists() { - if (FIX_BUG25184) { - return super.parentExists(); - } else { - return true; // tolerate units outside classpath - } -} /** - * @see IWorkingCopy#reconcile() + * @see ICompilationUnit#reconcile() + * @deprecated */ public IMarker[] reconcile() throws JavaModelException { - // Reconciling is not supported on non working copies + reconcile(NO_AST, false/*don't force problem detection*/, null/*use primary owner*/, null/*no progress monitor*/); return null; } +/** + * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor) + */ +public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException { + reconcile(NO_AST, forceProblemDetection, null/*use primary owner*/, monitor); +} /** - * @see IWorkingCopy#reconcile(boolean, IProgressMonitor) + * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor) + * @since 3.0 */ -public void reconcile( +//public org.eclipse.jdt.core.dom.CompilationUnit reconcile( + public Object reconcile( + int astLevel, boolean forceProblemDetection, + WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor) throws JavaModelException { - // Reconciling is not supported on non working copies + + if (!isWorkingCopy()) return null; // Reconciling is not supported on non working copies + if (workingCopyOwner == null) workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY; + + boolean createAST = false; +// if (astLevel == AST.JLS2) { +// // client asking for level 2 AST; these are supported +// createAST = true; +// } else if (astLevel == AST.JLS3) { +// // client asking for level 3 ASTs; these are not supported +// // TODO (jerome) - these should also be supported in 1.5 stream +// createAST = false; +// } else { +// // client asking for no AST (0) or unknown ast level +// // either way, request denied +// createAST = false; +// } + ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner); + op.runOperation(monitor); +// return op.ast; + return null; } /** @@ -836,14 +1200,25 @@ public void restore () throws JavaModelException { // } // }); //} -/** - * @see JavaElement#rootedAt(IJavaProject) +///** +// * @see JavaElement#rootedAt(IJavaProject) +// */ +//public IJavaElement rootedAt(IJavaProject project) { +// return +// new CompilationUnit( +// (IPackageFragment)((JavaElement)parent).rootedAt(project), +// name); +//} +/* + * Assume that this is a working copy */ -public IJavaElement rootedAt(IJavaProject project) { - return - new CompilationUnit( - (IPackageFragment)((JavaElement)fParent).rootedAt(project), - fName); +protected void updateTimeStamp(CompilationUnit original) throws JavaModelException { + long timeStamp = + ((IFile) original.getResource()).getModificationStamp(); + if (timeStamp == IResource.NULL_STAMP) { + throw new JavaModelException( + new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE)); + } + ((CompilationUnitElementInfo) getElementInfo()).timestamp = timeStamp; } - }