X-Git-Url: http://git.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 5a56373..72e516f 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 @@ -10,43 +10,67 @@ *******************************************************************************/ package net.sourceforge.phpdt.internal.core; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + import net.sourceforge.phpdt.core.IBuffer; +import net.sourceforge.phpdt.core.IBufferFactory; import net.sourceforge.phpdt.core.ICompilationUnit; +import net.sourceforge.phpdt.core.IImportContainer; +import net.sourceforge.phpdt.core.IImportDeclaration; import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IJavaModelStatusConstants; import net.sourceforge.phpdt.core.IJavaProject; -import net.sourceforge.phpdt.core.IPackageFragment; +import net.sourceforge.phpdt.core.IMember; +import net.sourceforge.phpdt.core.IMethod; +import net.sourceforge.phpdt.core.IOpenable; +import net.sourceforge.phpdt.core.IPackageDeclaration; +import net.sourceforge.phpdt.core.IPackageFragmentRoot; +import net.sourceforge.phpdt.core.IParent; +import net.sourceforge.phpdt.core.IProblemRequestor; +import net.sourceforge.phpdt.core.ISourceManipulation; +import net.sourceforge.phpdt.core.ISourceRange; +import net.sourceforge.phpdt.core.ISourceReference; +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 net.sourceforge.phpdt.core.*; import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; -/** +/** * @see ICompilationUnit */ -public class CompilationUnit extends Openable implements 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 class CompilationUnit extends Openable implements ICompilationUnit, net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit { + 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(org.eclipse.jdt.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 @@ -65,7 +89,20 @@ 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(); + + BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(this, problemRequestor); + operation.runOperation(monitor); + } +} //protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException { // // if (monitor != null && monitor.isCanceled()) return; @@ -86,46 +123,134 @@ protected CompilationUnit(IPackageFragment parent, String name) { // // 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 { + + // 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(); + } + + CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info; + + // 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 + } + 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) // */ //public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException { // codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, offset, requestor); //} -///** -// * @see ICodeAssist#codeSelect(int, int) -// */ +/** + * @see ICodeAssist#codeSelect(int, int) + */ //public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException { // return super.codeSelect(this, offset, length); //} -///** -// * @see IWorkingCopy#commit(boolean, IProgressMonitor) -// */ -//public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException { -// throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this)); -//} +/** + * @see IWorkingCopy#commit(boolean, IProgressMonitor) + */ +public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException { + 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 { -// if (container == null) { -// throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$ -// } -// IJavaElement[] elements = new IJavaElement[] {this}; -// IJavaElement[] containers = new IJavaElement[] {container}; -// String[] renamings = null; -// if (rename != null) { -// renamings = new String[] {rename}; -// } -// getJavaModel().copy(elements, containers, null, renamings, force, monitor); -//} +public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException { + if (container == null) { + throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$ + } + IJavaElement[] elements = new IJavaElement[] {this}; + IJavaElement[] containers = new IJavaElement[] {container}; + String[] renamings = null; + if (rename != null) { + renamings = new String[] {rename}; + } + getJavaModel().copy(elements, containers, null, renamings, force, monitor); +} + /** * Returns a new element info for this element. */ -//protected OpenableElementInfo createElementInfo() { -// return new CompilationUnitElementInfo(); -//} +protected Object createElementInfo() { + return new CompilationUnitElementInfo(); +} ///** // * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor) // */ @@ -140,12 +265,12 @@ protected CompilationUnit(IPackageFragment parent, String name) { /** * @see ICompilationUnit#createPackageDeclaration(String, IProgressMonitor) */ -//public IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException { -// -// CreatePackageDeclarationOperation op= new CreatePackageDeclarationOperation(name, this); -// runOperation(op, monitor); -// return getPackageDeclaration(name); -//} +public IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException { + + CreatePackageDeclarationOperation op= new CreatePackageDeclarationOperation(name, this); + runOperation(op, monitor); + return getPackageDeclaration(name); +} ///** // * @see ICompilationUnit#createType(String, IJavaElement, boolean, IProgressMonitor) // */ @@ -171,67 +296,78 @@ protected CompilationUnit(IPackageFragment parent, String name) { /** * @see ISourceManipulation#delete(boolean, IProgressMonitor) */ -//public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException { -// IJavaElement[] elements= new IJavaElement[] {this}; -// getJavaModel().delete(elements, force, monitor); -//} +public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException { + IJavaElement[] elements= new IJavaElement[] {this}; + 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(); -//} -///** -// * @see JavaElement#equalsDOMNode(IDOMNode) -// */ -//protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException { -// String name = getElementName(); -// if (node.getNodeType() == IDOMNode.COMPILATION_UNIT && name != null ) { -// String nodeName = node.getName(); -// if (nodeName == null) return false; -// if (name.equals(nodeName)) { -// return true; -// } else { -// // iterate through all the types inside the receiver and see if one of them can fit -// IType[] types = getTypes(); -// String typeNodeName = nodeName.substring(0, nodeName.indexOf(".java")); //$NON-NLS-1$ -// for (int i = 0, max = types.length; i < max; i++) { -// if (types[i].getElementName().equals(typeNodeName)) { -// return true; -// } -// } -// } -// } -// return false; -//} +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) + */ +protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException { + String name = getElementName(); + if (node.getNodeType() == IDOMNode.COMPILATION_UNIT && name != null ) { + String nodeName = node.getName(); + if (nodeName == null) return false; + if (name.equals(nodeName)) { + return true; + } else { + // iterate through all the types inside the receiver and see if one of them can fit + IType[] types = getTypes(); + String typeNodeName = nodeName.substring(0, nodeName.indexOf(".java")); //$NON-NLS-1$ + for (int i = 0, max = types.length; i < max; i++) { + if (types[i].getElementName().equals(typeNodeName)) { + return true; + } + } + } + } + return false; +} /** * @see IWorkingCopy#findElements(IJavaElement) */ -//public IJavaElement[] findElements(IJavaElement element) { -// ArrayList children = new ArrayList(); -// while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) { -// children.add(element); -// element = element.getParent(); -// } -// if (element == null) return null; -// IJavaElement currentElement = this; -// for (int i = children.size()-1; i >= 0; i--) { -// IJavaElement child = (IJavaElement)children.get(i); -// switch (child.getElementType()) { +public IJavaElement[] findElements(IJavaElement element) { + ArrayList children = new ArrayList(); + while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) { + children.add(element); + element = element.getParent(); + } + if (element == null) return null; + IJavaElement currentElement = this; + for (int i = children.size()-1; i >= 0; i--) { + IJavaElement child = (IJavaElement)children.get(i); + switch (child.getElementType()) { // case IJavaElement.PACKAGE_DECLARATION: // currentElement = ((ICompilationUnit)currentElement).getPackageDeclaration(child.getElementName()); // break; @@ -241,108 +377,119 @@ public void destroy() { // case IJavaElement.IMPORT_DECLARATION: // currentElement = ((IImportContainer)currentElement).getImport(child.getElementName()); // break; -// case IJavaElement.TYPE: -// if (currentElement.getElementType() == IJavaElement.COMPILATION_UNIT) { -// currentElement = ((ICompilationUnit)currentElement).getType(child.getElementName()); -// } else { -// currentElement = ((IType)currentElement).getType(child.getElementName()); -// } -// break; + case IJavaElement.TYPE: + if (currentElement.getElementType() == IJavaElement.COMPILATION_UNIT) { + currentElement = ((ICompilationUnit)currentElement).getType(child.getElementName()); + } else { + currentElement = ((IType)currentElement).getType(child.getElementName()); + } + break; // case IJavaElement.INITIALIZER: // currentElement = ((IType)currentElement).getInitializer(((JavaElement)child).getOccurrenceCount()); // break; -// case IJavaElement.FIELD: -// currentElement = ((IType)currentElement).getField(child.getElementName()); -// break; -// case IJavaElement.METHOD: -// return ((IType)currentElement).findMethods((IMethod)child); -// } -// -// } -// if (currentElement != null && currentElement.exists()) { -// return new IJavaElement[] {currentElement}; -// } else { -// return null; -// } -//} + case IJavaElement.FIELD: + currentElement = ((IType)currentElement).getField(child.getElementName()); + break; + case IJavaElement.METHOD: + return ((IType)currentElement).findMethods((IMethod)child); + } + + } + if (currentElement != null && currentElement.exists()) { + return new IJavaElement[] {currentElement}; + } else { + return null; + } +} /** * @see IWorkingCopy#findPrimaryType() */ -//public IType findPrimaryType() { -// String typeName = Signature.getQualifier(this.getElementName()); -// IType primaryType= this.getType(typeName); -// if (primaryType.exists()) { -// return primaryType; -// } -// return null; -//} - +public IType findPrimaryType() { + String typeName = Signature.getQualifier(this.getElementName()); + IType primaryType= this.getType(typeName); + if (primaryType.exists()) { + return primaryType; + } + 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); -//} +public IJavaElement findSharedWorkingCopy(IBufferFactory factory) { + + // if factory is null, default factory must be used + if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory(); + + 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 { -//protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { -// // if (getParent() instanceof JarPackageFragment) { // // ignore .java files in jar // throw newNotPresentException(); // } else { -// // put the info now, because getting the contents requires it -// JavaModelManager.getJavaModelManager().putInfo(this, info); -// CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info; -// -// // generate structure -// CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements); -// IProblemFactory factory = new DefaultProblemFactory(); -// SourceElementParser parser = new SourceElementParser(requestor, factory, new CompilerOptions(getJavaProject().getOptions(true))); -// requestor.parser = parser; -// parser.parseCompilationUnit(this, false); -// if (isWorkingCopy()) { -// CompilationUnit original = (CompilationUnit) getOriginalElement(); -// // might be IResource.NULL_STAMP if original does not exist -// unitInfo.fTimestamp = ((IFile) original.getResource()).getModificationStamp(); -// } -// return unitInfo.isStructureKnown(); + // put the info now, because getting the contents requires it + JavaModelManager.getJavaModelManager().putInfo(this, info); + CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info; + + // generate structure + CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements); + IProblemFactory factory = new DefaultProblemFactory(); + SourceElementParser parser = new SourceElementParser(requestor, factory, new CompilerOptions(getJavaProject().getOptions(true))); +// SourceElementParser parser = new SourceElementParser(requestor, factory); + requestor.parser = parser; + parser.parseCompilationUnit(this, false); + if (isWorkingCopy()) { + CompilationUnit original = (CompilationUnit) getOriginalElement(); + // might be IResource.NULL_STAMP if original does not exist + unitInfo.timestamp = ((IFile) original.getResource()).getModificationStamp(); + } + return unitInfo.isStructureKnown(); // } -//} +} /** * @see ICompilationUnit#getAllTypes() */ -//public IType[] getAllTypes() throws JavaModelException { -// IJavaElement[] types = getTypes(); -// int i; -// ArrayList allTypes = new ArrayList(types.length); -// ArrayList typesToTraverse = new ArrayList(types.length); -// for (i = 0; i < types.length; i++) { -// typesToTraverse.add(types[i]); -// } -// while (!typesToTraverse.isEmpty()) { -// IType type = (IType) typesToTraverse.get(0); -// typesToTraverse.remove(type); -// allTypes.add(type); -// types = type.getTypes(); -// for (i = 0; i < types.length; i++) { -// typesToTraverse.add(types[i]); -// } -// } -// IType[] arrayOfAllTypes = new IType[allTypes.size()]; -// allTypes.toArray(arrayOfAllTypes); -// return arrayOfAllTypes; -//} +public IType[] getAllTypes() throws JavaModelException { + IJavaElement[] types = getTypes(); + int i; + ArrayList allTypes = new ArrayList(types.length); + ArrayList typesToTraverse = new ArrayList(types.length); + for (i = 0; i < types.length; i++) { + typesToTraverse.add(types[i]); + } + while (!typesToTraverse.isEmpty()) { + IType type = (IType) typesToTraverse.get(0); + typesToTraverse.remove(type); + allTypes.add(type); + types = type.getTypes(); + for (i = 0; i < types.length; i++) { + typesToTraverse.add(types[i]); + } + } + IType[] arrayOfAllTypes = new IType[allTypes.size()]; + allTypes.toArray(arrayOfAllTypes); + return arrayOfAllTypes; +} /** * @see IMember#getCompilationUnit() */ @@ -366,26 +513,32 @@ public char[] getContents() { * * @see IJavaElement#getCorrespondingResource() */ -//public IResource getCorrespondingResource() throws JavaModelException { -// IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent(); -// if (root.isArchive()) { -// return null; -// } else { -// return getUnderlyingResource(); -// } -//} -///** -// * @see ICompilationUnit#getElementAt(int) -// */ -//public IJavaElement getElementAt(int position) throws JavaModelException { -// -// IJavaElement e= getSourceElementAt(position); -// if (e == this) { -// return null; -// } else { -// return e; -// } -//} +public IResource getCorrespondingResource() throws JavaModelException { + IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent(); + if (root.isArchive()) { + return null; + } else { + return getUnderlyingResource(); + } +} +/** + * @see ICompilationUnit#getElementAt(int) + */ +public IJavaElement getElementAt(int position) throws JavaModelException { + + IJavaElement e= getSourceElementAt(position); + if (e == this) { + return null; + } else { + return e; + } +} +/** + * @see IJavaElement + */ +public int getElementType() { + return COMPILATION_UNIT; +} public char[] getFileName(){ return getElementName().toCharArray(); } @@ -398,15 +551,16 @@ protected char getHandleMementoDelimiter() { /** * @see ICompilationUnit#getImport(String) */ -//public IImportDeclaration getImport(String name) { -// return new ImportDeclaration(getImportContainer(), name); -//} -///** -// * @see ICompilationUnit#getImportContainer() -// */ -//public IImportContainer getImportContainer() { -// return new ImportContainer(this); -//} +public IImportDeclaration getImport(String importName) { + return new ImportDeclaration((ImportContainer)getImportContainer(), importName); +} + +/** + * @see ICompilationUnit#getImportContainer() + */ +public ImportContainer getImportContainer() { + return new ImportContainer(this); +} /** @@ -435,37 +589,52 @@ 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) */ -//public IPackageDeclaration getPackageDeclaration(String name) { -// return new PackageDeclaration(this, name); -//} -///** -// * @see ICompilationUnit#getPackageDeclarations() -// */ -//public IPackageDeclaration[] getPackageDeclarations() throws JavaModelException { -// ArrayList list = getChildrenOfType(PACKAGE_DECLARATION); -// IPackageDeclaration[] array= new IPackageDeclaration[list.size()]; -// list.toArray(array); -// return array; -//} +public IPackageDeclaration getPackageDeclaration(String name) { + return new PackageDeclaration(this, name); +} +/** + * @see ICompilationUnit#getPackageDeclarations() + */ +public IPackageDeclaration[] getPackageDeclarations() throws JavaModelException { + ArrayList list = getChildrenOfType(PACKAGE_DECLARATION); + IPackageDeclaration[] array= new IPackageDeclaration[list.size()]; + list.toArray(array); + return array; +} /** * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getPackageName() */ @@ -475,14 +644,35 @@ public char[][] getPackageName() { /** * @see IJavaElement#getPath() */ -//public IPath getPath() { -// PackageFragmentRoot root = this.getPackageFragmentRoot(); -// if (root.isArchive()) { -// return root.getPath(); -// } else { -// return this.getParent().getPath().append(this.getElementName()); -// } -//} +public IPath getPath() { + PackageFragmentRoot root = this.getPackageFragmentRoot(); + if (root.isArchive()) { + return root.getPath(); + } else { + 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() */ @@ -506,31 +696,31 @@ public String getSource() throws JavaModelException { /** * @see ISourceReference#getSourceRange() */ -//public ISourceRange getSourceRange() throws JavaModelException { -// return ((CompilationUnitElementInfo) getElementInfo()).getSourceRange(); -//} -///** -// * @see ICompilationUnit#getType(String) -// */ -//public IType getType(String name) { -// return new SourceType(this, name); -//} -///** -// * @see ICompilationUnit#getTypes() -// */ -//public IType[] getTypes() throws JavaModelException { -// ArrayList list = getChildrenOfType(TYPE); -// IType[] array= new IType[list.size()]; -// list.toArray(array); -// return array; -//} -//public IResource getUnderlyingResource() throws JavaModelException { -// if (FIX_BUG25184) { -// return super.getUnderlyingResource(); -// } else { -// return getResource(); -// } -//} +public ISourceRange getSourceRange() throws JavaModelException { + return ((CompilationUnitElementInfo) getElementInfo()).getSourceRange(); +} +/** + * @see ICompilationUnit#getType(String) + */ +public IType getType(String name) { + return new SourceType(this, name); +} +/** + * @see ICompilationUnit#getTypes() + */ +public IType[] getTypes() throws JavaModelException { + ArrayList list = getChildrenOfType(TYPE); + IType[] array= new IType[list.size()]; + list.toArray(array); + return array; +} +/** + * @see IJavaElement + */ +public IResource getUnderlyingResource() throws JavaModelException { + if (isWorkingCopy() && !isPrimary()) return null; + return super.getUnderlyingResource(); +} ///** // * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) // */ @@ -566,29 +756,72 @@ public String getSource() throws JavaModelException { // return op.getResultElements()[0]; // } //} -/** - * @see IWorkingCopy#getWorkingCopy() - */ +///** +// * @see IWorkingCopy#getWorkingCopy() +// */ //public IJavaElement getWorkingCopy() throws JavaModelException { // return this.getWorkingCopy(null, null, null); //} - -/** - * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) - */ +// +///** +// * @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 Openable#hasBuffer() + * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor) + * @deprecated */ -protected boolean hasBuffer() { - return true; +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(); + + return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, pm); } /** + * @see IWorkingCopy#getWorkingCopy() + * @deprecated + */ +public IJavaElement getWorkingCopy() throws JavaModelException { + 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 monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException { + return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, monitor); +} +/** + * @see ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) + */ +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. * * @see IParent#hasChildren() @@ -602,62 +835,141 @@ 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 { -// return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null; -//} +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); +public void makeConsistent(IProgressMonitor monitor) throws JavaModelException { + 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) */ -//public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException { -// if (container == null) { -// throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$ -// } -// IJavaElement[] elements= new IJavaElement[] {this}; -// IJavaElement[] containers= new IJavaElement[] {container}; -// -// String[] renamings= null; -// if (rename != null) { -// renamings= new String[] {rename}; -// } -// getJavaModel().move(elements, containers, null, renamings, force, monitor); -//} +public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException { + if (container == null) { + throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$ + } + IJavaElement[] elements= new IJavaElement[] {this}; + IJavaElement[] containers= new IJavaElement[] {container}; + + String[] renamings= null; + if (rename != null) { + renamings= new String[] {rename}; + } + getJavaModel().move(elements, containers, null, renamings, force, monitor); +} -/** - * @see Openable#openBuffer(IProgressMonitor) - */ +///** +// * @see Openable#openBuffer(IProgressMonitor) +// */ //protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException { // // // create buffer - compilation units only use default buffer factory @@ -680,58 +992,126 @@ public boolean isWorkingCopy() { // // 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; -// } -// } -// } -//} -//protected boolean parentExists() { -// if (FIX_BUG25184) { -// return super.parentExists(); -// } else { -// return true; // tolerate units outside classpath -// } -//} +/** + * @see Openable#openBuffer(IProgressMonitor, Object) + */ +protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException { + + // 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) { + 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 + buffer.addBufferChangedListener(this); + + return buffer; +} +/* + * @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; + } + } +} /** - * @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; } /** * @see ISourceManipulation#rename(String, boolean, IProgressMonitor) */ -//public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException { -// if (name == null) { -// throw new IllegalArgumentException(Util.bind("operation.nullName")); //$NON-NLS-1$ -// } -// IJavaElement[] elements= new IJavaElement[] {this}; -// IJavaElement[] dests= new IJavaElement[] {this.getParent()}; -// String[] renamings= new String[] {name}; -// getJavaModel().rename(elements, dests, renamings, force, monitor); -//} +public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException { + if (name == null) { + throw new IllegalArgumentException(Util.bind("operation.nullName")); //$NON-NLS-1$ + } + IJavaElement[] elements= new IJavaElement[] {this}; + IJavaElement[] dests= new IJavaElement[] {this.getParent()}; + String[] renamings= new String[] {name}; + getJavaModel().rename(elements, dests, renamings, force, monitor); +} /** * Does nothing - this is not a working copy. * @@ -808,14 +1188,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; } - }